2 #using scripts\shared\ai_shared;
3 #using scripts\shared\ai_shared;
4 #using scripts\shared\ai\systems\ai_blackboard;
5 #using scripts\shared\ai\systems\ai_interface;
6 #using scripts\shared\ai\systems\animation_state_machine_utility;
7 #using scripts\shared\ai\systems\behavior_tree_utility;
8 #using scripts\shared\ai\systems\blackboard;
10 #insert scripts\shared\ai\systems\animation_state_machine.gsh;
11 #insert scripts\shared\ai\systems\blackboard.gsh;
12 #insert scripts\shared\ai\systems\behavior.gsh;
13 #insert scripts\shared\ai\systems\behavior_tree.gsh;
16 #using scripts\shared\ai\archetype_utility;
17 #using scripts\shared\ai\archetype_cover_utility;
18 #using scripts\shared\array_shared;
19 #using scripts\shared\laststand_shared;
21 #insert scripts\shared\ai\utility.gsh;
22 #insert scripts\shared\shared.gsh;
57 if(
IS_TRUE(level.AIDisableGrenadeThrows) )
62 if( !IsDefined( behaviorTreeEntity.enemy ) )
67 if ( !IsSentient( behaviorTreeEntity.enemy ) )
72 if ( IsVehicle( behaviorTreeEntity.enemy ) && behaviorTreeEntity.enemy.vehicleclass ===
"helicopter" )
83 entityAngles = behaviorTreeEntity.angles;
85 if ( IsDefined( behaviorTreeEntity.node ) &&
87 behaviorTreeEntity IsAtCoverNodeStrict() )
89 entityAngles = behaviorTreeEntity.node.angles;
92 toEnemy = behaviorTreeEntity.enemy.origin - behaviorTreeEntity.origin;
93 toEnemy = VectorNormalize( ( toEnemy[0], toEnemy[1], 0 ) );
95 entityForward = AnglesToForward( entityAngles );
96 entityForward = VectorNormalize( ( entityForward[0], entityForward[1], 0 ) );
99 if ( VectorDot( toEnemy, entityForward ) < 0.5 )
104 if ( !throwIfPossible )
107 if ( behaviorTreeEntity.team ===
"allies" )
109 foreach( player
in level.players )
119 foreach( player
in level.players )
130 foreach ( grenadeThrowInfo
in grenadeThrowInfos )
132 if( grenadeThrowInfo.data.grenadeThrowerTeam === behaviorTreeEntity.team )
141 foreach ( grenadeThrowInfo
in grenadeThrowInfos )
143 if( IsDefined( grenadeThrowInfo.data.grenadeThrownAt ) && IsAlive( grenadeThrowInfo.data.grenadeThrownAt ) )
145 if( grenadeThrowInfo.data.grenadeThrower == behaviorTreeEntity )
150 if( IsDefined( grenadeThrowInfo.data.grenadeThrownAt ) &&
151 grenadeThrowInfo.data.grenadeThrownAt == behaviorTreeEntity.enemy )
156 if ( IsDefined( grenadeThrowInfo.data.grenadeThrownPosition ) &&
157 IsDefined( behaviorTreeEntity.grenadeThrowPosition ) &&
158 DistanceSquared( grenadeThrowInfo.data.grenadeThrownPosition, behaviorTreeEntity.grenadeThrowPosition ) <=
GRENADE_OVERLAP_DIST_SQ )
167 throw_dist = Distance2DSquared( behaviorTreeEntity.origin, behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy ) );
173 arm_offset =
TEMP_get_arm_offset( behaviorTreeEntity, behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy ) );
174 throw_vel = behaviorTreeEntity CanThrowGrenadePos( arm_offset, behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy ) );
176 if ( !IsDefined( throw_vel ) )
184 #define SENSE_DISTANCE 360
185 #define SENSE_DISTANCE_SQ SQR(SENSE_DISTANCE)
188 players = GetPlayers();
190 foreach ( player
in players )
192 distanceSq = DistanceSquared( player.origin, entity.origin );
196 distanceToPlayer = Sqrt( distanceSq );
198 chanceToDetect = RandomFloat( 1.0 );
202 entity GetPerfectInfo( player );
212 if ( IsDefined( behaviorTreeEntity.enemy ) )
214 behaviorTreeEntity.grenadeThrowPosition = behaviorTreeEntity LastKnownPos( behaviorTreeEntity.enemy );
217 grenadeThrowInfo = SpawnStruct();
218 grenadeThrowInfo.grenadeThrower = behaviorTreeEntity;
219 grenadeThrowInfo.grenadeThrownAt = behaviorTreeEntity.enemy;
220 grenadeThrowInfo.grenadeThrownPosition = behaviorTreeEntity.grenadeThrowPosition;
223 grenadeThrowInfo = SpawnStruct();
224 grenadeThrowInfo.grenadeThrowerTeam = behaviorTreeEntity.team;
227 behaviorTreeEntity.prepareGrenadeAmmo = behaviorTreeEntity.grenadeammo;
234 if ( behaviorTreeEntity.prepareGrenadeAmmo == behaviorTreeEntity.grenadeammo )
237 if ( behaviorTreeEntity.health <= 0 )
242 if ( IsActor( behaviorTreeEntity.enemy ) && IsDefined( behaviorTreeEntity.grenadeweapon ) )
244 grenade = behaviorTreeEntity.enemy MagicGrenadeType(
245 behaviorTreeEntity.grenadeweapon,
246 behaviorTreeEntity GetTagOrigin(
"j_wrist_ri" ),
248 behaviorTreeEntity.grenadeweapon.aifusetime / 1000 );
250 else if ( IsPlayer( behaviorTreeEntity.enemy ) && IsDefined( behaviorTreeEntity.grenadeweapon ) )
252 grenade = behaviorTreeEntity.enemy MagicGrenadePlayer(
253 behaviorTreeEntity.grenadeweapon,
254 behaviorTreeEntity GetTagOrigin(
"j_wrist_ri" ),
258 if ( IsDefined( grenade ) )
260 grenade.owner = behaviorTreeEntity;
261 grenade.team = behaviorTreeEntity.team;
284 if ( !entity IsAtGoal() )
294 if ( behaviorTreeEntity ASMIsTransitionRunning() )
299 if ( IsDefined( behaviorTreeEntity.coverShootStartTime ) )
308 if ( IsDefined( behaviorTreeEntity.enemy ) &&
309 IsPlayer( behaviorTreeEntity.enemy ) &&
310 behaviorTreeEntity.enemy.health < behaviorTreeEntity.enemy.maxHealth * 0.5 )
324 if ( !behaviorTreeEntity IsAtGoal() )
327 if ( IsDefined( behaviorTreeEntity.node ) )
329 offsetOrigin = behaviorTreeEntity GetNodeOffsetPosition( behaviorTreeEntity.node );
331 return !behaviorTreeEntity IsPosAtGoal( offsetOrigin );
337 if ( !behaviorTreeEntity IsSafeFromGrenade() )
347 if( !IsDefined( behaviorTreeEntity.node ) )
387 if( !IsDefined( behaviorTreeEntity.node ) ||
388 !IsDefined( behaviorTreeEntity.node.type ) ||
389 !IsDefined( behaviorTreeEntity.enemy) ||
390 !IsDefined( behaviorTreeEntity.enemy.origin ) )
395 yawToEnemyPosition = AiUtility::GetAimYawToEnemyFromNode( behaviorTreeEntity, behaviorTreeEntity.node, behaviorTreeEntity.enemy );
396 pitchToEnemyPosition = AiUtility::GetAimPitchToEnemyFromNode( behaviorTreeEntity, behaviorTreeEntity.node, behaviorTreeEntity.enemy );
402 if ( yawToEnemyPosition < aimLimitsForCover[
AIM_LEFT] &&
403 yawToEnemyPosition > aimLimitsForCover[
AIM_RIGHT] &&
404 pitchToEnemyPosition < 85.0 &&
405 pitchToEnemyPosition > 25.0 &&
406 ( behaviorTreeEntity.node.origin[2] - behaviorTreeEntity.enemy.origin[2] ) >= ( 3 * 12 ) )
457 behaviorTreeEntity.newEnemyReaction =
false;
469 behaviorTreeEntity.newEnemyReaction =
false;
498 #define COVER_AIM_ANGLE_EPSILON 10
503 arm_offset = undefined;
508 arm_offset = ( 13, -1, 56 );
512 arm_offset = ( 14, -3, 80 );
515 if( IsDefined( behaviorTreeEntity.node ) && behaviorTreeEntity IsAtCoverNodeStrict() )
521 arm_offset = ( -38, 15, 23 );
525 arm_offset = ( -45, 0, 40 );
532 arm_offset = ( 46, 12, 26 );
536 arm_offset = ( 34, -21, 50 );
541 arm_offset = ( 10, 7, 77 );
545 arm_offset = ( 19, 5, 60 );
549 leftOffset = undefined;
550 rightOffset = undefined;
554 leftOffset = ( -20, 0, 35 );
555 rightOffset = ( 34, 6, 50 );
559 leftOffset = ( -24, 0, 76 );
560 rightOffset = ( 24, 0, 76 );
565 arm_offset = rightOffset;
569 arm_offset = leftOffset;
573 yawToEnemyPosition = AngleClamp180( VectorToAngles( throwPosition - behaviorTreeEntity.node.origin )[1] - behaviorTreeEntity.node.angles[1] );
578 if( legalRightDirectionYaw )
580 arm_offset = rightOffset;
584 arm_offset = leftOffset;