1 #using scripts\codescripts\struct;
3 #using scripts\shared\array_shared;
4 #using scripts\shared\colors_shared;
5 #using scripts\shared\flag_shared;
6 #using scripts\shared\flagsys_shared;
7 #using scripts\shared\scene_shared;
8 #using scripts\shared\util_shared;
9 #using scripts\shared\vehicle_ai_shared;
11 #using scripts\shared\ai\systems\init;
12 #using scripts\shared\ai\systems\shared;
13 #using scripts\shared\ai\archetype_utility;
14 #using scripts\shared\ai\systems\weaponList;
15 #using scripts\shared\ai\systems\ai_interface;
17 #insert scripts\shared\ai\systems\blackboard.gsh;
18 #insert scripts\shared\shared.gsh;
19 #insert scripts\shared\ai\utility.gsh;
35 assert( IsSentient(
self ),
"Non ai tried to set ignoreme" );
51 assert( isSentient(
self ),
"Non ai tried to set ignoraell" );
67 assert( IsSentient(
self ),
"Non ai tried to set pacifist" );
82 assert( isalive(
self ),
"Tried to disable pain on a non ai" );
83 self.allowPain =
false;
97 assert( isalive(
self ),
"Tried to enable pain on a non ai" );
98 self.allowPain =
true;
113 self.gun_removed =
true;
144 self.gun_removed = undefined;
212 if ( IsSentient(
self ) && !IsAlive(
self ) )
237 for( i = 0;i < guys.size;i++ )
239 if( isalive( guys[ i ] ) )
246 assert( allAlive,
"Waittill_Dead was called with dead or removed AI in the array, meaning it will never pass." );
250 for( i = 0;i < guys.size;i++ )
252 if( isalive( guys[ i ] ) )
254 newArray[ newArray.size ] = guys[ i ];
261 if( isdefined( timeoutLength ) )
263 ent endon(
"thread_timed_out" );
267 ent.count = guys.size;
268 if( isdefined( num ) && num < ent.count )
274 while( ent.count > 0 )
276 ent waittill(
"waittill_dead guy died" );
296 for( i = 0;i < guys.size;i++ )
298 if( isalive( guys[ i ] ) && !guys[ i ].ignoreForFixedNodeSafeCheck )
300 newArray[ newArray.size ] = guys[ i ];
306 if( isdefined( timeoutLength ) )
308 ent endon(
"thread_timed_out" );
312 ent.count = guys.size;
315 if( isdefined( num ) && num < ent.count )
322 while( ent.count > 0 )
324 ent waittill(
"waittill_dead_guy_dead_or_dying" );
330 self waittill(
"death" );
332 ent notify(
"waittill_dead guy died" );
339 ent notify(
"waittill_dead_guy_dead_or_dying" );
344 wait( timeoutLength );
345 self notify(
"thread_timed_out" );
351 self endon(
"stop_shoot_at_target" );
352 if( IsVehicle(
self ) )
354 self waittill(
"weapon_fired" );
358 self waittill(
"shoot");
360 self.start_duration_comp =
true;
383 self endon(
"stop_shoot_at_target");
385 Assert( IsDefined( target ),
"shoot_at_target was passed an undefined target" );
386 Assert( IsDefined( mode ),
"Undefined mode. A mode must be passed to shoot_at_target" );
388 Assert( mode_flag,
"Unsupported mode. 'Mode must be normal', 'shoot_until_target_dead' or 'kill_within_time'" );
390 if( isdefined( duration ) )
392 Assert( duration >= 0,
"Duration must be a zero or a positive quantity" );
399 if ( isdefined(setHealth) && isdefined(target) )
401 target.health = setHealth;
404 if ( !isdefined( target ) || ( (
IS_EQUAL( mode,
"shoot_until_target_dead" ) ) && ( target.health <= 0 ) ) )
409 if( IsDefined(tag) && tag !=
"" )
411 self SetEntityTarget( target, 1, tag );
415 self SetEntityTarget( target, 1 );
419 self.cansee_override =
true;
420 self.start_duration_comp =
false;
426 case "shoot_until_target_dead":
429 case "kill_within_time":
430 target DamageMode(
"next_shot_kills" );
434 if( IsVehicle(
self ) )
442 if(ignoreFirstShotWait ===
true)
444 self.start_duration_comp =
true;
452 if( isdefined(duration) && isdefined( target ) && target.health > 0 )
457 while( isdefined(target) && target.health > 0 && elapsed <= duration )
460 if( !
IS_TRUE(
self.start_duration_comp ) )
465 if( isdefined(target) && mode ==
"kill_within_time" )
467 self.perfectaim =
true;
468 self.aim_set_by_shoot_at_target =
true;
470 target waittill(
"death" );
473 else if (duration == -1)
475 target waittill(
"death" );
493 self ClearEntityTarget();
495 if(
IS_TRUE(
self.aim_set_by_shoot_at_target ) )
497 self.perfectaim =
false;
498 self.aim_set_by_shoot_at_target =
false;
501 self.cansee_override =
false;
503 self notify(
"stop_shoot_at_target");
508 self endon(
"death" );
509 while (
self.isSpeaking )
527 function set_goal( value, key =
"targetname", b_force =
false )
529 goal = GetNode( value, key );
531 if ( isdefined( goal ) )
533 self SetGoal( goal, b_force );
537 goal = GetEnt( value, key );
539 if ( isdefined( goal ) )
541 self SetGoal( goal, b_force );
547 if ( isdefined( goal ) )
549 self SetGoal( goal.origin, b_force );
570 function force_goal(
goto, n_radius, b_shoot =
true, str_end_on, b_keep_colors =
false, b_should_sprint =
false )
572 self endon(
"death" );
573 s_tracker = SpawnStruct();
574 self thread
_force_goal( s_tracker,
goto, n_radius, b_shoot, str_end_on, b_keep_colors, b_should_sprint );
575 s_tracker waittill(
"done" );
578 function _force_goal( s_tracker,
goto, n_radius, b_shoot =
true, str_end_on, b_keep_colors =
false, b_should_sprint =
false )
580 self endon(
"death" );
582 self notify(
"new_force_goal" );
587 goalradius =
self.goalradius;
588 if ( IsDefined( n_radius ) )
590 Assert( ( IsFloat( n_radius ) || IsInt( n_radius ) ),
"ai_shared::force_goal expects n_radius to be an int or a float." );
591 self.goalradius = n_radius;
594 color_enabled =
false;
595 if ( !b_keep_colors )
599 color_enabled =
true;
604 allowpain =
self.allowpain;
605 ignoreall =
self.ignoreall;
606 ignoreme =
self.ignoreme;
607 ignoresuppression =
self.ignoresuppression;
608 grenadeawareness =
self.grenadeawareness;
615 if( b_should_sprint )
620 self.ignoresuppression =
true;
621 self.grenadeawareness = 0;
625 self PushPlayer(
true );
627 if ( isdefined(
goto ) )
629 if ( IsDefined( n_radius ) )
631 Assert( ( IsFloat( n_radius ) || IsInt( n_radius ) ),
"ai_shared::force_goal expects n_radius to be an int or a float." );
632 self SetGoal(
goto );
636 self SetGoal(
goto,
true );
647 self PushPlayer(
false );
649 self ClearForcedGoal();
651 self.goalradius = goalradius;
662 self.ignoresuppression = ignoresuppression;
663 self.grenadeawareness = grenadeawareness;
666 s_tracker notify(
"done" );
679 self notify(
"painWaitIntervalRemove");
686 self.allowPain =
true;
701 self notify(
"painWaitInterval");
702 self endon(
"painWaitInterval");
703 self endon(
"painWaitIntervalRemove");
706 if(!isDefined(mSec) || mSec < 20 )
711 self waittill(
"pain");
712 self.allowPain =
false;
714 self.allowPain =
true;
731 self endon(
"death" );
732 self endon(
"stop_patrolling" );
734 assert( isDefined( start_path_node ),
self.targetname +
" has not been assigned a valid node or scene scriptbundle for his patrol path to start on" );
735 if ( start_path_node.type ==
"BAD NODE" )
738 errorMsg =
"ERROR: patrol node '" + start_path_node.targetname +
"' (" + int(start_path_node.origin[0]) +
"," + int(start_path_node.origin[1]) +
"," + int(start_path_node.origin[2]) +
") is 'BAD NODE'";
739 IPrintLn( errorMsg );
740 LogPrint( errorMsg );
744 assert( start_path_node.type ==
"Path" || isdefined( start_path_node.scriptbundlename ),
"The starting point '" + start_path_node.targetname +
"' for a patrol path is not a path node or scene script bundle" );
746 self notify(
"go_to_spawner_target");
747 self.target = undefined;
749 self.old_goal_radius =
self.goalradius;
753 self.currentgoal = start_path_node;
755 self.patroller =
true;
760 if( isDefined(
self.currentgoal.type) &&
self.currentgoal.type ==
"Path" )
765 self setgoal(
self.currentgoal,
true );
767 self waittill(
"goal" );
769 if( isDefined(
self.currentgoal.script_notify ))
771 self notify (
self.currentgoal.script_notify );
772 level notify (
self.currentgoal.script_notify );
776 if (isDefined(
self.currentgoal.script_flag_set ))
778 flag =
self.currentgoal.script_flag_set;
780 if ( !isdefined( level.flag[ flag ] ) )
789 if( !isDefined(
self.currentgoal.script_wait_min ))
791 self.currentgoal.script_wait_min = 0;
794 if( !isDefined(
self.currentgoal.script_wait_max ))
796 self.currentgoal.script_wait_max = 0;
799 assert(
self.currentgoal.script_wait_min <=
self.currentgoal.script_wait_max ,
"Patrol max wait is less than the min wait on " +
self.currentgoal.targetname );
801 if( !isdefined(
self.currentgoal.scriptbundlename) )
803 wait_variability =
self.currentgoal.script_wait_max -
self.currentgoal.script_wait_min;
804 wait_time =
self.currentgoal.script_wait_min + randomfloat( wait_variability );
805 self notify(
"patrol_goal",
self.currentgoal );
810 self scene::play(
self.currentgoal.scriptbundlename ,
self );
828 if ( isdefined(
self.currentgoal.target ) )
830 target_nodes = getnodearray(
self.currentgoal.target,
"targetname" );
834 if( target_nodes.size == 0 && target_scenes.size == 0 )
840 if( target_nodes.size != 0)
842 self.currentgoal = array::random( target_nodes );
846 self.currentgoal = array::random( target_scenes );
854 self endon(
"death" );
855 self endon(
"stop_patrolling" );
859 if( isdefined(
self.enemy) ||
self.should_stop_patrolling ===
true )
870 if ( isdefined(
self.currentgoal ) && isdefined(
self.currentgoal.scriptbundlename ) && isDefined(
self._o_scene ) )
875 if ( isDefined(
self.old_goal_radius ) )
876 self.goalradius =
self.old_goal_radius;
877 self ClearForcedGoal();
878 self notify(
"stop_patrolling" );
879 self.patroller = undefined;
895 self endon(
"death" );
897 if( !IsDefined(
self ) )
902 assert( IsActor(
self ) );
903 assert( IsAlive(
self ) );
905 if(
IS_TRUE(
self.__bloody_death ) )
908 self.__bloody_death =
true;
910 if( IsDefined( n_delay ) )
915 if( !IsDefined(
self ) || !IsAlive(
self ) )
920 if( IsDefined( hit_loc ) )
922 assert( IsInArray( HITLOC_ALL, hit_loc ),
"bloody_death() : Invalid hit location. Check the list of allowed hit location in blackboard.gsh, HITLOC_ALL." );
926 hit_loc = array::random( HITLOC_ALL );
929 self DoDamage(
self.health + 100,
self.origin, undefined, undefined, hit_loc );
943 if(
IS_TRUE( level.clientFieldAICheck ) && !IsArchetypeLoaded( archetype ) )