IL-GSC/BO1/PC/ZM/maps/_spawner.gsc
2024-02-18 17:32:07 -05:00

2414 lines
60 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include maps\_utility;
#include maps\_anim;
#include maps\_serverfaceanim;
#include common_scripts\utility;
main()
{
CreateThreatBiasGroup( "allies" );
CreateThreatBiasGroup( "axis" );
if (level.script!="frontend" && !isDefined(level.zombietron_mode) )
precachemodel("grenade_bag");
level._nextcoverprint = 0;
level._ai_group = [];
level.killedaxis = 0;
level.ffpoints = 0;
level.missionfailed = false;
level.gather_delay = [];
level.smoke_thrown = [];
level.deathflags = [];
level.spawner_number = 0;
level.go_to_node_arrays = [];
level.next_health_drop_time = 0;
level.guys_to_die_before_next_health_drop = RandomIntRange( 1, 4 );
level.default_goalradius = 2048;
level.default_goalheight = 80;
level.portable_mg_gun_tag = "J_Shoulder_RI";
level.mg42_hide_distance = 1024;
if( !IsDefined( level.maxFriendlies ) )
{
level.maxFriendlies = 11;
}
ai = GetAISpeciesArray("all");
array_thread( ai, ::living_ai_prethink );
level.ai_classname_in_level = [];
spawners = GetSpawnerArray();
for( i = 0; i < spawners.size; i++ )
{
spawners[i].is_spawner = true;
spawners[i] thread spawn_prethink();
}
thread process_deathflags();
array_thread( ai, ::spawn_think );
precache_player_weapon_drops( array("rpg", "panzerschreck") );
if( IsDefined( level.hiding_door_spawner ) )
{
run_thread_on_noteworthy( "hiding_door_spawner", level.hiding_door_spawner );
}
level thread trigger_spawner_monitor();
}
precache_player_weapon_drops( weapon_names )
{
level.ai_classname_in_level_keys = getarraykeys( level.ai_classname_in_level );
for ( i = 0 ; i < level.ai_classname_in_level_keys.size ; i++ )
{
if( weapon_names.size <= 0 )
{
break;
}
for( j = 0 ; j < weapon_names.size ; j++ )
{
weaponName = weapon_names[j];
if ( !issubstr( tolower( level.ai_classname_in_level_keys[ i ] ), weaponName ) )
{
continue;
}
precacheItem( weaponName + "_player_sp" );
weapon_names = array_remove( weapon_names, weaponName );
break;
}
}
level.ai_classname_in_level_keys = undefined;
}
process_deathflags()
{
keys = getarraykeys( level.deathflags );
level.deathflags = [];
for ( i=0; i < keys.size; i++ )
{
deathflag = keys[ i ];
level.deathflags[ deathflag ] = [];
level.deathflags[ deathflag ][ "spawners" ] = [];
level.deathflags[ deathflag ][ "ai" ] = [];
if ( !IsDefined( level.flag[ deathflag ] ) )
{
flag_init( deathflag );
}
}
}
spawn_guys_until_death_or_no_count()
{
self endon( "death" );
self waittill( "count_gone" );
}
deathflag_check_count()
{
self endon( "death" );
waittillframeend;
if ( self.count > 0 )
{
return;
}
self notify( "count_gone" );
}
ai_deathflag()
{
level.deathflags[ self.script_deathflag ][ "ai" ][ self.ai_number ] = self;
ai_number = self.ai_number;
deathflag = self.script_deathflag;
if ( IsDefined( self.script_deathflag_longdeath ) )
{
self waittillDeathOrPainDeath();
}
else
{
self waittill( "death" );
}
level.deathflags[ deathflag ][ "ai" ][ ai_number ] = undefined;
update_deathflag( deathflag );
}
spawner_deathflag()
{
level.deathflags[ self.script_deathflag ] = true;
waittillframeend;
if ( !IsDefined( self ) || self.count == 0 )
{
return;
}
self.spawner_number = level.spawner_number;
level.spawner_number++;
level.deathflags[ self.script_deathflag ][ "spawners" ][ self.spawner_number ] = self;
deathflag = self.script_deathflag;
id = self.spawner_number;
spawn_guys_until_death_or_no_count();
level.deathflags[ deathflag ][ "spawners" ][ id ] = undefined;
update_deathflag( deathflag );
}
update_deathflag( deathflag )
{
level notify( "updating_deathflag_" + deathflag );
level endon( "updating_deathflag_" + deathflag );
waittillframeend;
spawnerKeys = getarraykeys( level.deathflags[ deathflag ][ "spawners" ] );
if ( spawnerKeys.size > 0 )
{
return;
}
aiKeys = getarraykeys( level.deathflags[ deathflag ][ "ai" ] );
if ( aiKeys.size > 0 )
{
return;
}
flag_set( deathflag );
}
outdoor_think( trigger )
{
assert( trigger has_spawnflag(level.SPAWNFLAG_TRIGGER_AI_AXIS)
|| trigger has_spawnflag(level.SPAWNFLAG_TRIGGER_AI_ALLIES)
|| trigger has_spawnflag(level.SPAWNFLAG_TRIGGER_AI_NEUTRAL),
"trigger_outdoor at " + trigger.origin + " is not set up to trigger AI! Check one of the AI checkboxes on the trigger." );
trigger endon( "death" );
for ( ;; )
{
trigger waittill( "trigger", guy );
if ( !IsAI( guy ) )
{
continue;
}
guy thread ignore_triggers( 0.15 );
guy disable_cqbwalk();
guy.wantShotgun = false;
}
}
indoor_think( trigger )
{
assert( trigger has_spawnflag(level.SPAWNFLAG_TRIGGER_AI_AXIS)
|| trigger has_spawnflag(level.SPAWNFLAG_TRIGGER_AI_ALLIES)
|| trigger has_spawnflag(level.SPAWNFLAG_TRIGGER_AI_NEUTRAL),
"trigger_indoor at " + trigger.origin + " is not set up to trigger AI! Check one of the AI checkboxes on the trigger." );
trigger endon( "death" );
for ( ;; )
{
trigger waittill( "trigger", guy );
if ( !IsAI( guy ) )
{
continue;
}
guy thread ignore_triggers( 0.15 );
guy enable_cqbwalk();
guy.wantShotgun = true;
}
}
trigger_spawner_monitor()
{
println("Trigger spawner monitor running...");
level._numTriggerSpawned = 0;
while(1)
{
wait_network_frame();
wait_network_frame();
level._numTriggerSpawned = 0;
}
}
ok_to_trigger_spawn(forceChoke)
{
if(IsDefined(forceChoke))
{
choked = forceChoke;
}
else
{
choked = false;
}
if(IsDefined(self.script_trigger) && NumRemoteClients())
{
trigger = self.script_trigger;
if(IsDefined(trigger.targetname) && (trigger.targetname == "flood_spawner"))
{
choked = true;
if(IsDefined(trigger.script_choke) && !trigger.script_choke)
{
choked = false;
}
}
else if(trigger has_spawnflag(level.SPAWNFLAG_TRIGGER_SPAWN))
{
if(IsDefined(trigger.script_choke) && trigger.script_choke)
{
choked = true;
}
}
}
if(IsDefined(self.targetname) && (self.targetname == "drone_axis" || self.targetname == "drone_allies"))
{
choked = true;
}
if( IsDefined(level._forcechoke) && level._numTriggerSpawned > 2 )
{
return false;
}
if(choked && NumRemoteClients())
{
if(level._numTriggerSpawned > 2)
{
println("Triggerspawn choke.");
return false;
}
}
return true;
}
trigger_spawner( trigger )
{
assertEx( IsDefined( trigger.target ), "Triggers with flag TRIGGER_SPAWN at " + trigger.origin + " must target at least one spawner." );
trigger endon( "death" );
trigger waittill( "trigger" );
spawners = getentarray( trigger.target, "targetname" );
for(i = 0; i < spawners.size; i++)
{
spawners[i].script_trigger = trigger;
}
array_thread( spawners, ::trigger_spawner_spawns_guys );
}
trigger_spawner_spawns_guys()
{
self endon( "death" );
if ( IsSubStr( self.classname, "actor" ) )
{
self script_delay();
while(!self ok_to_trigger_spawn())
{
wait_network_frame();
}
if ( IsDefined( self.script_drone ) )
{
spawned = dronespawn( self );
level._numTriggerSpawned ++;
assertEx( IsDefined( level.drone_spawn_func ), "You need to put maps\_drone::init(); in your level script!" );
spawned thread [[ level.drone_spawn_func ]]();
return;
}
self spawn_ai();
level._numTriggerSpawned ++;
}
}
flood_spawner_scripted( spawners )
{
assertex( IsDefined( spawners ) && spawners.size, "Script tried to flood spawn without any spawners" );
array_thread( spawners, ::flood_spawner_init );
{
array_thread( spawners, ::flood_spawner_think );
}
}
reincrement_count_if_deleted( spawner )
{
spawner endon( "death" );
self waittill( "death" );
if( !IsDefined( self ) )
{
spawner.count++;
}
}
kill_trigger( trigger )
{
if( !IsDefined( trigger ) )
{
return;
}
if( ( IsDefined( trigger.targetname ) ) &&( trigger.targetname != "flood_spawner" ) )
{
return;
}
trigger Delete();
}
kill_spawner_trigger( trigger )
{
trigger waittill( "trigger" );
kill_spawnernum(trigger.script_killspawner);
}
empty_spawner( trigger )
{
emptyspawner = trigger.script_emptyspawner;
trigger waittill( "trigger" );
spawners = GetSpawnerArray();
for( i = 0; i < spawners.size; i++ )
{
if( !IsDefined( spawners[i].script_emptyspawner ) )
{
continue;
}
if( emptyspawner != spawners[i].script_emptyspawner )
{
continue;
}
if( IsDefined( spawners[i].script_flanker ) )
{
level notify( "stop_flanker_behavior" + spawners[i].script_flanker );
}
spawners[i].count = 0;
spawners[i] notify( "emptied spawner" );
}
trigger notify( "deleted spawners" );
}
waittillDeathOrPainDeath()
{
self endon( "death" );
self waittill( "pain_death" );
}
drop_gear()
{
team = self.team;
waittillDeathOrPainDeath();
if( !IsDefined( self ) )
{
return;
}
self.ignoreForFixedNodeSafeCheck = true;
if( self.grenadeAmmo <= 0 )
{
return;
}
if( IsDefined( self.dropweapon ) && !self.dropweapon )
{
return;
}
level.nextGrenadeDrop--;
if( level.nextGrenadeDrop > 0 )
{
return;
}
level.nextGrenadeDrop = 2 + RandomInt( 2 );
max = 25;
min = 12;
spawn_grenade_bag( self.origin +( RandomInt( max )-min, RandomInt( max )-min, 2 ) +( 0, 0, 42 ), ( 0, RandomInt( 360 ), 0 ), self.team );
}
random_tire( start, end )
{
model = spawn( "script_model", (0,0,0) );
model.angles = ( 0, randomint( 360 ), 0 );
dif = randomfloat( 1 );
model.origin = start * dif + end * ( 1 - dif );
model setmodel( "com_junktire" );
vel = randomvector( 15000 );
vel = ( vel[ 0 ], vel[ 1 ], abs( vel[ 2 ] ) );
model physicslaunch( model.origin, vel );
wait ( randomintrange ( 8, 12 ) );
model delete();
}
spawn_grenade_bag( origin, angles, team )
{
if( !IsDefined( level.grenade_cache ) || !IsDefined( level.grenade_cache[team] ) )
{
level.grenade_cache_index[team] = 0;
level.grenade_cache[team] = [];
}
index = level.grenade_cache_index[team];
grenade = level.grenade_cache[team][index];
if( IsDefined( grenade ) )
{
grenade Delete();
}
count = self.grenadeammo;
grenade = Spawn( "weapon_" + self.grenadeWeapon, origin );
level.grenade_cache[team][index] = grenade;
level.grenade_cache_index[team] = ( index + 1 ) % 16;
grenade.angles = angles;
grenade.count = count;
grenade SetModel( "grenade_bag" );
}
dronespawn_setstruct( spawner )
{
if ( dronespawn_check() )
{
return;
}
guy = spawner stalingradspawn();
if (isDefined(guy) )
{
spawner.count++ ;
dronespawn_setstruct_from_guy( guy );
guy delete();
}
}
dronespawn_check()
{
if(IsDefined(level.dronestruct[self.classname]))
{
return true;
}
return false;
}
dronespawn_setstruct_from_guy ( guy )
{
if (!isDefined(guy))
{
return;
}
if(dronespawn_check())
{
return;
}
struct = spawnstruct();
size = guy getattachsize();
struct.attachedmodels = [];
for( i = 0; i < size; i++ )
{
struct.attachedmodels[i] = guy GetAttachModelName( i );
struct.attachedtags[i] = guy GetAttachTagName( i );
}
struct.model = guy.model;
struct.weapon = guy.weapon;
level.dronestruct[guy.classname] = struct;
}
empty()
{
}
spawn_prethink()
{
assert( self != level );
level.ai_classname_in_level[ self.classname ] = true;
prof_begin( "spawn_prethink" );
if( IsDefined( self.script_drone ) )
{
self thread dronespawn_setstruct(self);
}
if( IsDefined( self.script_aigroup ) )
{
aigroup = self.script_aigroup;
aigroup_init( aigroup, self );
}
if( IsDefined( self.script_delete ) )
{
array_size = 0;
if( IsDefined( level._ai_delete ) )
{
if( IsDefined( level._ai_delete[self.script_delete] ) )
{
array_size = level._ai_delete[self.script_delete].size;
}
}
level._ai_delete[self.script_delete][array_size] = self;
}
deathflag_func = ::empty;
if ( IsDefined( self.script_deathflag ) )
{
deathflag_func = ::deathflag_check_count;
thread spawner_deathflag();
}
if ( IsDefined( self.target ) )
{
crawl_through_targets_to_init_flags();
}
for( ;; )
{
prof_begin( "spawn_prethink" );
self waittill( "spawned", spawn );
[[ deathflag_func ]]();
if( !IsAlive( spawn ) )
{
continue;
}
if( IsDefined( self.script_delete ) )
{
for( i = 0; i < level._ai_delete[self.script_delete].size; i++ )
{
if( level._ai_delete[self.script_delete][i] != self )
{
level._ai_delete[self.script_delete][i] Delete();
}
}
}
spawn.spawn_funcs = self.spawn_funcs;
spawn thread spawn_think( self );
}
}
spawn_think( spawner )
{
assert( self != level );
level.ai_classname_in_level[ self.classname ] = true;
if (IsDefined(spawner))
{
spawn_think_action( spawner.targetname );
}
else
{
spawn_think_action();
}
assert( IsAlive( self ) );
self endon( "death" );
if ( GetDvar( #"zombiemode") != "1" && !IsDefined(self.name) && (self.type != "dog"))
{
self waittill( "set name and rank" );
}
self.finished_spawning = true;
self notify("finished spawning");
self thread run_spawn_functions(spawner);
assert( IsDefined( self.team ) );
}
run_spawn_functions(spawner)
{
self endon( "death" );
waittillframeend;
if( IsDefined(spawner) && IsDefined( level.spawnerCallbackThread ) )
{
spawner thread [[level.spawnerCallbackThread]]( self );
}
for (i = 0; i < level.spawn_funcs[ self.team ].size; i++)
{
func = level.spawn_funcs[ self.team ][ i ];
single_thread(self, func[ "function" ], func[ "param1" ], func[ "param2" ], func[ "param3" ], func[ "param4" ] );
}
self thread maps\_audio::missile_audio_watcher();
if (!IsDefined( self.spawn_funcs ))
{
return;
}
for (i = 0; i < self.spawn_funcs.size; i++)
{
func = self.spawn_funcs[ i ];
single_thread(self, func[ "function" ], func[ "param1" ], func[ "param2" ], func[ "param3" ], func[ "param4" ] );
}
self.spawn_funcs = undefined;
self.spawn_funcs = undefined;
}
living_ai_prethink()
{
if ( IsDefined( self.script_deathflag ) )
{
level.deathflags[ self.script_deathflag ] = true;
}
if ( IsDefined( self.target ) )
{
crawl_through_targets_to_init_flags();
}
}
crawl_through_targets_to_init_flags()
{
array = get_node_funcs_based_on_target();
if ( IsDefined( array ) )
{
targets = array[ "node" ];
get_func = array[ "get_target_func" ];
for ( i = 0; i < targets.size; i++ )
{
crawl_target_and_init_flags( targets[ i ], get_func );
}
}
}
spawn_think_action( spawner_targetname )
{
if ( GetDvar( #"zombiemode" ) == "0" )
{
self thread maps\_serverfaceanim::init_serverfaceanim();
}
if (IsDefined(spawner_targetname) && !IsDefined(self.targetname))
{
self.targetname = spawner_targetname + "_ai";
}
self thread maps\_utility::ent_flag_init_ai_standards();
self thread tanksquish();
self.spawner_number = undefined;
if( !IsDefined( self.ai_number ) )
{
set_ai_number();
}
if ( IsDefined( self.script_dontshootwhilemoving ) )
{
self.dontshootwhilemoving = true;
}
if ( IsDefined( self.script_deathflag ) )
{
thread ai_deathflag();
}
if( IsDefined( self.script_animname ) )
{
self.animname = self.script_animname;
}
if ( IsDefined( self.script_forceColor ) )
{
set_force_color( self.script_forceColor );
if( (!IsDefined( self.script_no_respawn ) || self.script_no_respawn < 1) && !IsDefined(level.no_color_respawners_sm) )
{
self thread replace_on_death();
}
}
if ( IsDefined( self.script_fixednode ) )
{
self.fixednode = ( self.script_fixednode == 1 );
}
else
{
self.fixednode = self.team == "allies";
}
set_default_covering_fire();
if( ( IsDefined( self.script_moveoverride ) ) &&( self.script_moveoverride == 1 ) )
{
override = true;
}
else
{
override = false;
}
if( IsDefined( self.script_noteworthy ) && self.script_noteworthy == "mgpair" )
{
thread maps\_mg_penetration::create_mg_team();
}
if ( GetDvar( #"zombiemode" ) == "0" )
{
level thread maps\_friendlyfire::friendly_fire_think( self );
}
if( IsDefined( self.script_threatbiasgroup ) )
{
self SetThreatBiasGroup( self.script_threatbiasgroup );
}
else if( self.team == "allies" )
{
self SetThreatBiasGroup( "allies" );
}
else
{
self SetThreatBiasGroup( "axis" );
}
set_default_pathenemy_settings();
self.heavy_machine_gunner = IsSubStr( self.classname, "mgportable" );
maps\_gameskill::grenadeAwareness();
self.walkdist = 16;
if( IsDefined( self.script_ignoreme ) )
{
assertEx( self.script_ignoreme == true, "Tried to set self.script_ignoreme to false, not allowed. Just set it to undefined." );
self.ignoreme = true;
}
if ( IsDefined( self.script_ignore_suppression ) )
{
assertEx( self.script_ignore_suppression == true, "Tried to set self.script_ignore_suppresion to false, not allowed. Just set it to undefined." );
self.ignoreSuppression = true;
}
if( IsDefined( self.script_hero ) )
{
AssertEx( self.team == "allies", "Only use script_hero kvp on friendly AI, else use magic_bullet_shield directly." );
AssertEx( self.script_hero == 1, "Tried to set script_hero to something other than 1" );
self make_hero();
}
if ( IsDefined( self.script_ignoreall ) )
{
assertEx( self.script_ignoreall == true, "Tried to set self.script_ignoreme to false, not allowed. Just set it to undefined." );
self.ignoreall = true;
self clearenemy();
}
if( GetDvar( #"zombiemode") != "1" && IsDefined( self.script_disable_bleeder ) )
{
assertEx( self.script_disable_bleeder == true, "self.script_disable_bleeder can only be set to true. To set to true, leave it undefined." );
self disable_ai_bleeder();
}
if( GetDvar( #"zombiemode") != "1" && IsDefined( self.script_disable_reviver ) )
{
assertEx( self.script_disable_reviver == true, "self.script_disable_reviver can only be set to true. To set to true, leave it undefined." );
self disable_ai_reviver();
}
if( IsDefined( self.script_disablereact ) )
{
self disable_react();
}
if( IsDefined( self.script_disablepain ) )
{
self disable_pain();
}
if( IsDefined( self.script_disableturns ) )
{
self.disableTurns = true;
}
if( IsDefined( self.script_sightrange ) )
{
self.maxSightDistSqrd = self.script_sightrange;
}
else if( WeaponClass( self.weapon ) == "gas" )
{
self.maxSightDistSqrd = 1024 * 1024;
}
if( self.team != "axis" )
{
if( IsDefined( self.script_followmin ) )
{
self.followmin = self.script_followmin;
}
if( IsDefined( self.script_followmax ) )
{
self.followmax = self.script_followmax;
}
}
if ( self.team == "axis" )
{
if ( self.type == "human" )
{
self thread drop_gear();
}
self thread maps\_gameskill::auto_adjust_enemy_death_detection();
}
if( IsDefined( self.script_fightdist ) )
{
self.pathenemyfightdist = self.script_fightdist;
}
if( IsDefined( self.script_maxdist ) )
{
self.pathenemylookahead = self.script_maxdist;
}
if ( IsDefined( self.script_longdeath ) )
{
assertex( !self.script_longdeath, "Long death is enabled by default so don't set script_longdeath to true, check ai with export " + self.export );
self.a.disableLongDeath = true;
assertEX( self.team != "allies", "Allies can't do long death, so why disable it on guy with export " + self.export );
}
if( IsDefined( self.script_grenades ) )
{
self.grenadeAmmo = self.script_grenades;
}
if( IsDefined( self.script_pacifist ) )
{
self.pacifist = true;
}
if( IsDefined( self.script_startinghealth ) )
{
self.health = self.script_startinghealth;
}
if( IsDefined(self.script_allowdeath) )
{
self.allowdeath = self.script_allowdeath;
}
if( IsDefined(self.script_nodropweapon) )
{
self.dropweapon = 0;
}
if( IsDefined( self.script_forcegib ) )
{
self.force_gib = 1;
if( call_overloaded_func( "animscripts\death", "isValidGibRef", self.script_forcegib ) )
{
self.custom_gib_refs[0] = self.script_forcegib;
}
}
if( IsDefined( self.script_stealth ) )
{
self thread call_overloaded_func( "maps\_stealth_logic", "stealth_ai" );
}
if( IsDefined( self.script_patroller ) )
{
self thread maps\_patrol::patrol();
return;
}
else if( IsDefined( self.script_contextual_melee ) )
{
self contextual_melee(self.script_contextual_melee);
}
if( IsDefined( self.script_spiderhole ) )
{
self thread maps\_spiderhole::spiderhole();
return;
}
if (is_true(self.script_rusher))
{
self call_overloaded_func( "maps\_rusher", "rush" );
return;
}
if( IsDefined( self.script_enable_cqbwalk ) )
{
self maps\_utility::enable_cqbwalk();
}
if( IsDefined( self.script_enable_heat ) )
{
self maps\_utility::enable_heat();
}
if( IsDefined( self.script_disable_idle_strafe ) && self.script_disable_idle_strafe )
{
self.disableIdleStrafing = true;
}
if( IsDefined( self.script_playerseek ) )
{
if( self.script_playerseek == 1 )
{
self thread player_seek();
return;
}
else
{
self thread player_seek( self.script_playerseek );
}
}
if( IsDefined( self.script_banzai ) )
{
self thread maps\_banzai::spawned_banzai_dynamic();
}
else if( IsDefined( self.script_banzai_spawn ) )
{
self thread maps\_banzai::spawned_banzai_immediate();
}
if( self.heavy_machine_gunner )
{
thread maps\_mgturret::portable_mg_behavior();
}
if( IsDefined( self.used_an_mg42 ) )
{
return;
}
assertEx( (self.goalradius == 8 || self.goalradius == 4), "Changed the goalradius on guy without waiting for spawn_failed. Note that this change will NOT show up by putting a breakpoint on the actors goalradius field because breakpoints don't properly handle the first frame an actor exists." );
if( override )
{
self thread set_goalradius_based_on_settings();
self SetGoalPos( self.origin );
return;
}
if( IsDefined( self.target ) )
{
self thread go_to_node();
}
else
{
self thread set_goalradius_based_on_settings();
if (IsDefined(self.script_spawner_targets))
{
self thread go_to_spawner_target(StrTok(self.script_spawner_targets," "));
}
}
if( IsDefined( self.script_goalvolume ) )
{
thread set_goal_volume();
}
if( IsDefined( self.script_turnrate ) )
{
self.turnrate = self.script_turnrate;
}
self maps\_dds::dds_ai_init();
}
set_default_covering_fire()
{
self.provideCoveringFire = self.team == "allies" && self.fixedNode;
}
flag_turret_for_use( ai )
{
self endon( "death" );
if( !self.flagged_for_use )
{
ai.used_an_mg42 = true;
self.flagged_for_use = true;
ai waittill( "death" );
self.flagged_for_use = false;
self notify( "get new user" );
return;
}
println( "Turret was already flagged for use" );
}
set_goal_volume()
{
self endon( "death" );
waittillframeend;
self SetGoalVolume( level.goalVolumes[self.script_goalvolume] );
}
get_target_ents( target )
{
return getentarray( target, "targetname" );
}
get_target_nodes( target )
{
return getnodearray( target, "targetname" );
}
get_target_structs( target )
{
return getstructarray( target, "targetname" );
}
node_has_radius( node )
{
return IsDefined( node.radius ) && node.radius != 0;
}
go_to_origin( node, optional_arrived_at_node_func )
{
self go_to_node( node, "origin", optional_arrived_at_node_func );
}
go_to_struct( node, optional_arrived_at_node_func )
{
self go_to_node( node, "struct", optional_arrived_at_node_func );
}
go_to_node( node, goal_type, optional_arrived_at_node_func )
{
self endon("death");
if ( IsDefined( self.used_an_mg42 ) )
{
return;
}
array = get_node_funcs_based_on_target( node, goal_type );
if ( !IsDefined( array ) )
{
self notify( "reached_path_end" );
return;
}
if ( !IsDefined( optional_arrived_at_node_func ) )
{
optional_arrived_at_node_func = ::empty_arrived_func;
}
go_to_node_using_funcs( array[ "node" ], array[ "get_target_func" ], array[ "set_goal_func_quits" ], optional_arrived_at_node_func );
}
spawner_targets_init()
{
allnodes = GetAllNodes();
level.script_spawner_targets_nodes = [];
for( i = 0; i < allnodes.size; i++)
{
if(IsDefined(allnodes[i].script_spawner_targets))
{
level.script_spawner_targets_nodes[level.script_spawner_targets_nodes.size] = allnodes[i];
}
}
}
go_to_spawner_target(target_names)
{
self endon("death");
self notify("go_to_spawner_target");
self endon("go_to_spawner_target");
nodes = [];
occupied_nodes = [];
nodesPresent = false;
for ( i = 0; i < target_names.size; i++)
{
target_nodes = get_spawner_target_nodes(target_names[i]);
if( target_nodes.size > 0 )
{
nodesPresent = true;
}
for ( i = 0; i < target_nodes.size; i++)
{
if ( IsNodeOccupied(target_nodes[i]) || is_true(target_nodes[i].node_claimed) )
{
occupied_nodes = array_add(occupied_nodes, target_nodes[i]);
}
else
{
nodes = array_add(nodes, target_nodes[i]);
}
}
}
if( nodes.size == 0 )
{
while( nodes.size == 0 )
{
for ( i = 0; i < occupied_nodes.size; i++)
{
if( !IsNodeOccupied(occupied_nodes[i]) && !is_true(occupied_nodes[i].node_claimed))
{
nodes = array_add(nodes, occupied_nodes[i]);
break;
}
}
wait( 0.1 );
}
}
AssertEx(nodesPresent, "No spawner target nodes for AI.");
goal = undefined;
if( nodes.size > 0 )
{
goal = random(nodes);
}
if (IsDefined(goal))
{
if( IsDefined( self.script_radius ) )
{
self.goalradius = self.script_radius;
}
else
{
self.goalradius = 400;
}
goal.node_claimed = true;
self SetGoalNode(goal);
self thread release_spawner_target_node(goal);
self waittill("goal");
}
self set_goalradius_based_on_settings(goal);
}
release_spawner_target_node(node)
{
self waittill_any("death", "goal_changed");
node.node_claimed = undefined;
}
get_spawner_target_nodes(group)
{
if(group == "")
{
return [];
}
nodes = [];
for ( i = 0; i < level.script_spawner_targets_nodes.size; i++)
{
groups = strtok(level.script_spawner_targets_nodes[i].script_spawner_targets," ");
for ( j = 0; j < groups.size; j++)
{
if (groups[j] == group)
{
nodes[nodes.size] = level.script_spawner_targets_nodes[i];
}
}
}
return nodes;
}
empty_arrived_func( node )
{
}
get_least_used_from_array( array )
{
assertex( array.size > 0, "Somehow array had zero entrees" );
if ( array.size == 1 )
{
return array[ 0 ];
}
targetname = array[ 0 ].targetname;
if ( !IsDefined( level.go_to_node_arrays[ targetname ] ) )
{
level.go_to_node_arrays[ targetname ] = array;
}
array = level.go_to_node_arrays[ targetname ];
first = array[ 0 ];
newarray = [];
for ( i = 0; i < array.size - 1; i++ )
{
newarray[ i ] = array[ i + 1 ];
}
newarray[ array.size - 1 ] = array[ 0 ];
level.go_to_node_arrays[ targetname ] = newarray;
return first;
}
go_to_node_using_funcs( node, get_target_func, set_goal_func_quits, optional_arrived_at_node_func, require_player_dist )
{
self endon( "stop_going_to_node" );
self endon( "death" );
for ( ;; )
{
node = get_least_used_from_array( node );
player_wait_dist = require_player_dist;
if( isdefined( node.script_requires_player ) )
{
if( node.script_requires_player > 1 )
player_wait_dist = node.script_requires_player;
else
player_wait_dist = 256;
node.script_requires_player = false;
}
self set_goalradius_based_on_settings( node );
if ( IsDefined( node.height ) )
{
self.goalheight = node.height;
}
else
{
self.goalheight = level.default_goalheight;
}
[[ set_goal_func_quits ]]( node );
self waittill( "goal" );
[[ optional_arrived_at_node_func ]]( node );
if ( IsDefined( node.script_flag_set ) )
{
flag_set( node.script_flag_set );
}
if ( IsDefined( node.script_flag_clear ) )
{
flag_set( node.script_flag_clear );
}
if ( IsDefined( node.script_ent_flag_set ) )
{
if( !self flag_exists( node.script_ent_flag_set ) )
AssertEx( "Tried to set a ent flag "+ node.script_ent_flag_set +" on a node, but it doesnt exist." );
self ent_flag_set( node.script_ent_flag_set );
}
if ( IsDefined( node.script_ent_flag_clear ) )
{
if( !self flag_exists( node.script_ent_flag_clear ) )
AssertEx( "Tried to clear a ent flag "+ node.script_ent_flag_clear +" on a node, but it doesnt exist." );
self ent_flag_clear( node.script_ent_flag_clear );
}
if ( targets_and_uses_turret( node ) )
{
return true;
}
if( IsDefined( node.script_enable_cqbwalk ) )
{
self enable_cqbwalk();
}
if( IsDefined( node.script_disable_cqbwalk ) )
{
self disable_cqbwalk();
}
if( IsDefined( node.script_enable_heat ) )
{
self enable_heat();
}
if( IsDefined( node.script_disable_heat ) )
{
self disable_heat();
}
if( IsDefined( node.script_sprint ) )
{
if( node.script_sprint )
{
self.sprint = true;
}
else
{
self.sprint = false;
}
}
if( IsDefined( node.script_walk ) )
{
if( node.script_walk )
{
self.walk = true;
}
else
{
self.walk = false;
}
}
if ( IsDefined( node.script_flag_wait ) )
{
flag_wait( node.script_flag_wait );
}
while ( isdefined( node.script_requires_player ) )
{
node.script_requires_player = false;
if ( self go_to_node_wait_for_player( node, get_target_func, player_wait_dist ) )
{
node.script_requires_player = true;
node notify( "script_requires_player" );
break;
}
wait 0.1;
}
if( IsDefined( node.script_aigroup ) )
{
waittill_ai_group_cleared( node.script_aigroup );
}
node script_delay();
if ( !IsDefined( node.target ) )
{
break;
}
nextNode_array = [[ get_target_func ]]( node.target );
if ( !nextNode_array.size )
{
break;
}
node = nextNode_array;
}
if( IsDefined( self.arrived_at_end_node_func ) )
[[ self.arrived_at_end_node_func ]]( node );
self notify( "reached_path_end" );
if( IsDefined( self.delete_on_path_end ) )
self Delete();
self set_goalradius_based_on_settings( node );
}
go_to_node_wait_for_player( node, get_target_func, dist )
{
players = get_players();
for( i=0; i< players.size; i++ )
{
player = players[i];
if ( distancesquared( player.origin, node.origin ) < distancesquared( self.origin, node.origin ) )
return true;
}
vec = anglestoforward( self.angles );
if ( isdefined( node.target ) )
{
temp = [[ get_target_func ]]( node.target );
if ( temp.size == 1 )
vec = vectornormalize( temp[ 0 ].origin - node.origin );
else if ( isdefined( node.angles ) )
vec = anglestoforward( node.angles );
}
else if ( isdefined( node.angles ) )
vec = anglestoforward( node.angles );
vec2 = [];
for( i=0; i< players.size; i++ )
{
player = players[i];
vec2[ vec2.size ] = vectornormalize( ( player.origin - self.origin ) );
}
for( i=0; i< vec2.size; i++ )
{
value = vec2[i];
if ( vectordot( vec, value ) > 0 )
return true;
}
dist2rd = dist * dist;
for( i=0; i< players.size; i++ )
{
player = players[i];
if ( distancesquared( player.origin, self.origin ) < dist2rd )
return true;
}
return false;
}
go_to_node_set_goal_pos( ent )
{
self set_goal_pos( ent.origin );
}
go_to_node_set_goal_node( node )
{
self set_goal_node( node );
}
targets_and_uses_turret( node )
{
if ( !IsDefined( node.target ) )
{
return false;
}
turrets = getentarray( node.target, "targetname" );
if ( !turrets.size )
{
return false;
}
turret = turrets[ 0 ];
if ( turret.classname != "misc_turret" )
{
return false;
}
thread use_a_turret( turret );
return true;
}
remove_crawled( ent )
{
waittillframeend;
if ( IsDefined( ent ) )
{
ent.crawled = undefined;
}
}
crawl_target_and_init_flags( ent, get_func )
{
oldsize = 0;
targets = [];
index = 0;
for ( ;; )
{
if ( !IsDefined( ent.crawled ) )
{
ent.crawled = true;
level thread remove_crawled( ent );
if ( IsDefined( ent.script_flag_set ) )
{
if ( !IsDefined( level.flag[ ent.script_flag_set ] ) )
{
flag_init( ent.script_flag_set );
}
}
if ( IsDefined( ent.script_flag_wait ) )
{
if ( !IsDefined( level.flag[ ent.script_flag_wait ] ) )
{
flag_init( ent.script_flag_wait );
}
}
if ( IsDefined( ent.target ) )
{
new_targets = [[ get_func ]]( ent.target );
targets = add_to_array( targets, new_targets );
}
}
index++ ;
if ( index >= targets.size )
{
break;
}
ent = targets[ index ];
}
}
get_node_funcs_based_on_target( node, goal_type )
{
get_target_func[ "origin" ] = ::get_target_ents;
get_target_func[ "node" ] = ::get_target_nodes;
get_target_func[ "struct" ] = ::get_target_structs;
set_goal_func_quits[ "origin" ] = ::go_to_node_set_goal_pos;
set_goal_func_quits[ "struct" ] = ::go_to_node_set_goal_pos;
set_goal_func_quits[ "node" ] = ::go_to_node_set_goal_node;
if ( !IsDefined( goal_type ) )
{
goal_type = "node";
}
array = [];
if ( IsDefined( node ) )
{
array[ "node" ][ 0 ] = node;
}
else
{
node = getentarray( self.target, "targetname" );
if ( node.size > 0 )
{
goal_type = "origin";
}
if ( goal_type == "node" )
{
node = getnodearray( self.target, "targetname" );
if ( !node.size )
{
node = getstructarray( self.target, "targetname" );
if ( !node.size )
{
return;
}
goal_type = "struct";
}
}
array[ "node" ] = node;
}
array[ "get_target_func" ] = get_target_func[ goal_type ];
array[ "set_goal_func_quits" ] = set_goal_func_quits[ goal_type ];
return array;
}
set_goalradius_based_on_settings( node )
{
self endon( "death" );
waittillframeend;
if( IsDefined( self.script_radius ) )
{
self.goalradius = self.script_radius;
}
else if( IsDefined( self.script_banzai_spawn ) )
{
self.goalradius = 64;
}
else if ( IsDefined( node ) && node_has_radius( node ) )
{
self.goalradius = node.radius;
}
else
{
self.goalradius = level.default_goalradius;
}
if (is_true(self.script_forcegoal))
{
self thread force_goal();
}
}
reachPathEnd()
{
self waittill( "goal" );
self notify( "reached_path_end" );
}
autoTarget( targets )
{
for( ;; )
{
user = self GetTurretOwner();
if( !IsAlive( user ) )
{
wait( 1.5 );
continue;
}
if( !IsDefined( user.enemy ) )
{
self SetTargetEntity( random( targets ) );
self notify( "startfiring" );
self StartFiring();
}
wait( 2 + RandomFloat( 1 ) );
}
}
manualTarget( targets )
{
for( ;; )
{
self SetTargetEntity( random( targets ) );
self notify( "startfiring" );
self StartFiring();
wait( 2 + RandomFloat( 1 ) );
}
}
use_a_turret( turret )
{
if( self.team == "axis" && self.health == 150 )
{
self.health = 100;
self.a.disableLongDeath = true;
}
unmanned = false;
self Useturret( turret );
if( ( IsDefined( turret.target ) ) &&( turret.target != turret.targetname ) )
{
ents = GetEntArray( turret.target, "targetname" );
targets = [];
for( i = 0; i < ents.size; i++ )
{
if( ents[i].classname == "script_origin" )
{
targets[targets.size] = ents[i];
}
}
if( targets.size > 0 )
{
turret.manual_targets = targets;
turret SetMode( "auto_nonai" );
turret thread maps\_mgturret::burst_fire_unmanned();
unmanned = true;
}
}
if( !unmanned )
{
self thread maps\_mgturret::mg42_firing( turret );
}
turret notify( "startfiring" );
}
fallback_spawner_think( num, node_array, ignoreWhileFallingBack )
{
self endon( "death" );
level.max_fallbackers[num]+= self.count;
firstspawn = true;
while( self.count > 0 )
{
self waittill( "spawned", spawn );
if( firstspawn )
{
if( GetDvar( #"fallback" ) == "1" )
{
println( "^a First spawned: ", num );
}
level notify( ( "fallback_firstspawn" + num ) );
firstspawn = false;
}
maps\_spawner::waitframe();
if( spawn_failed( spawn ) )
{
level notify( ( "fallbacker_died" + num ) );
level.max_fallbackers[num]--;
continue;
}
spawn thread fallback_ai_think( num, node_array, "is spawner", ignoreWhileFallingBack );
}
}
fallback_ai_think_death( ai, num )
{
ai waittill( "death" );
level.current_fallbackers[num]--;
level notify( ( "fallbacker_died" + num ) );
}
fallback_ai_think( num, node_array, spawner, ignoreWhileFallingBack )
{
if( ( !IsDefined( self.fallback ) ) ||( !IsDefined( self.fallback[num] ) ) )
{
self.fallback[num] = true;
}
else
{
return;
}
self.script_fallback = num;
if( !IsDefined( spawner ) )
{
level.current_fallbackers[num]++;
}
if( ( IsDefined( node_array ) ) &&( level.fallback_initiated[num] ) )
{
self thread fallback_ai( num, node_array, ignoreWhileFallingBack );
}
level thread fallback_ai_think_death( self, num );
}
fallback_death( ai, num )
{
ai waittill( "death" );
if (IsDefined(ai.fallback_node))
{
ai.fallback_node.fallback_occupied = false;
}
level notify( ( "fallback_reached_goal" + num ) );
}
fallback_goal( ignoreWhileFallingBack )
{
self waittill( "goal" );
self.ignoresuppression = false;
if( IsDefined( ignoreWhileFallingBack ) && ignoreWhileFallingBack )
{
self.ignoreall = false;
}
self notify( "fallback_notify" );
self notify( "stop_coverprint" );
}
fallback_interrupt()
{
self notify( "stop_fallback_interrupt" );
self endon( "stop_fallback_interrupt" );
self endon( "stop_going_to_node" );
self endon ("goto next fallback");
self endon ("fallback_notify");
self endon( "death" );
while(1)
{
origin = self.origin;
wait 2;
if ( self.origin == origin )
{
self.ignoreall = false;
return;
}
}
}
fallback_ai( num, node_array, ignoreWhileFallingBack )
{
self notify( "stop_going_to_node" );
self endon( "stop_going_to_node" );
self endon ("goto next fallback");
self endon( "death" );
node = undefined;
while( 1 )
{
ASSERTEX((node_array.size >= level.current_fallbackers[num]), "Number of fallbackers exceeds number of fallback nodes for fallback # " + num + ". Add more fallback nodes or reduce possible fallbackers.");
node = node_array[RandomInt( node_array.size )];
if (!IsDefined(node.fallback_occupied) || !node.fallback_occupied)
{
node.fallback_occupied = true;
self.fallback_node = node;
break;
}
wait( 0.1 );
}
self StopUseTurret();
self.ignoresuppression = true;
if( self.ignoreall == false && IsDefined( ignoreWhileFallingBack ) && ignoreWhileFallingBack )
{
self.ignoreall = true;
self thread fallback_interrupt();
}
self SetGoalNode( node );
if( node.radius != 0 )
{
self.goalradius = node.radius;
}
self endon( "death" );
level thread fallback_death( self, num );
self thread fallback_goal( ignoreWhileFallingBack );
if( GetDvar( #"fallback" ) == "1" )
{
self thread coverprint( node.origin );
}
self waittill( "fallback_notify" );
level notify( ( "fallback_reached_goal" + num ) );
}
coverprint( org )
{
self endon( "fallback_notify" );
self endon( "stop_coverprint" );
self endon ("death");
while( 1 )
{
line( self.origin +( 0, 0, 35 ), org, ( 0.2, 0.5, 0.8 ), 0.5 );
print3d( ( self.origin +( 0, 0, 70 ) ), "Falling Back", ( 0.98, 0.4, 0.26 ), 0.85 );
maps\_spawner::waitframe();
}
}
fallback_overmind( num, group, ignoreWhileFallingBack, percent )
{
fallback_nodes = undefined;
nodes = GetAllNodes();
for( i = 0; i < nodes.size; i++ )
{
if( ( IsDefined( nodes[i].script_fallback ) ) &&( nodes[i].script_fallback == num ) )
{
fallback_nodes = add_to_array( fallback_nodes, nodes[i] );
}
}
if( IsDefined( fallback_nodes ) )
{
level thread fallback_overmind_internal( num, group, fallback_nodes, ignoreWhileFallingBack, percent );
}
}
fallback_overmind_internal( num, group, fallback_nodes, ignoreWhileFallingBack, percent )
{
level.current_fallbackers[num] = 0;
level.max_fallbackers[num] = 0;
level.spawner_fallbackers[num] = 0;
level.fallback_initiated[num] = false;
spawners = GetSpawnerArray();
for( i = 0; i < spawners.size; i++ )
{
if( ( IsDefined( spawners[i].script_fallback ) ) &&( spawners[i].script_fallback == num ) )
{
if( spawners[i].count > 0 )
{
spawners[i] thread fallback_spawner_think( num, fallback_nodes, ignoreWhileFallingBack );
level.spawner_fallbackers[num]++;
}
}
}
assertex ( level.spawner_fallbackers[num] <= fallback_nodes.size, "There are more fallback spawners than fallback nodes. Add more node or remove spawners from script_fallback: "+ num );
ai = GetAiArray();
for( i = 0; i < ai.size; i++ )
{
if( ( IsDefined( ai[i].script_fallback ) ) &&( ai[i].script_fallback == num ) )
{
ai[i] thread fallback_ai_think( num, undefined, undefined, ignoreWhileFallingBack );
}
}
if( ( !level.current_fallbackers[num] ) &&( !level.spawner_fallbackers[num] ) )
{
return;
}
spawners = undefined;
ai = undefined;
thread fallback_wait( num, group, ignoreWhileFallingBack, percent );
level waittill( ( "fallbacker_trigger" + num ) );
fallback_add_previous_group(num, fallback_nodes);
if( GetDvar( #"fallback" ) == "1" )
{
println( "^a fallback trigger hit: ", num );
}
level.fallback_initiated[num] = true;
fallback_ai = undefined;
ai = GetAiArray();
for( i = 0; i < ai.size; i++ )
{
if( ( ( IsDefined( ai[i].script_fallback ) ) &&( ai[i].script_fallback == num ) ) || ( ( IsDefined( ai[i].script_fallback_group ) ) &&( IsDefined( group ) ) &&( ai[i].script_fallback_group == group ) ) )
{
fallback_ai = add_to_array( fallback_ai, ai[i] );
}
}
ai = undefined;
if( !IsDefined( fallback_ai ) )
{
return;
}
if( !IsDefined( percent ) )
{
percent = 0.4;
}
first_half = fallback_ai.size * percent;
first_half = Int( first_half );
level notify( "fallback initiated " + num );
fallback_text( fallback_ai, 0, first_half );
first_half_ai = [];
for( i = 0; i < first_half; i++ )
{
fallback_ai[i] thread fallback_ai( num, fallback_nodes, ignoreWhileFallingBack );
first_half_ai[i] = fallback_ai[i];
}
for( i = 0; i < first_half; i++ )
{
level waittill( ( "fallback_reached_goal" + num ) );
}
fallback_text( fallback_ai, first_half, fallback_ai.size );
for( i = 0; i < fallback_ai.size; i++ )
{
if( IsAlive( fallback_ai[i] ) )
{
set_fallback = true;
for (p = 0; p < first_half_ai.size; p++)
{
if ( isalive(first_half_ai[p]))
{
if (fallback_ai[i] == first_half_ai[p])
{
set_fallback = false;
}
}
}
if (set_fallback)
{
fallback_ai[i] thread fallback_ai( num, fallback_nodes, ignoreWhileFallingBack );
}
}
}
}
fallback_text( fallbackers, start, end )
{
if( GetTime() <= level._nextcoverprint )
{
return;
}
for( i = start; i < end; i++ )
{
if( !IsAlive( fallbackers[i] ) )
{
continue;
}
level._nextcoverprint = GetTime() + 2500 + RandomInt( 2000 );
return;
}
}
fallback_wait( num, group, ignoreWhileFallingBack, percent )
{
level endon( ( "fallbacker_trigger" + num ) );
if( GetDvar( #"fallback" ) == "1" )
{
println( "^a Fallback wait: ", num );
}
for( i = 0; i < level.spawner_fallbackers[num]; i++ )
{
if( GetDvar( #"fallback" ) == "1" )
{
println( "^a Waiting for spawners to be hit: ", num, " i: ", i );
}
level waittill( ( "fallback_firstspawn" + num ) );
}
if( GetDvar( #"fallback" ) == "1" )
{
println( "^a Waiting for AI to die, fall backers for group ", num, " is ", level.current_fallbackers[num] );
}
ai = GetAiArray();
for( i = 0; i < ai.size; i++ )
{
if( ( ( IsDefined( ai[i].script_fallback ) ) &&( ai[i].script_fallback == num ) ) || ( ( IsDefined( ai[i].script_fallback_group ) ) &&( IsDefined( group ) ) &&( ai[i].script_fallback_group == group ) ) )
{
ai[i] thread fallback_ai_think( num, undefined, undefined, ignoreWhileFallingBack );
}
}
ai = undefined;
deadfallbackers = 0;
while( deadfallbackers < level.max_fallbackers[num] * percent )
{
if( GetDvar( #"fallback" ) == "1" )
{
println( "^cwaiting for " + deadfallbackers + " to be more than " +( level.max_fallbackers[num] * 0.5 ) );
}
level waittill( ( "fallbacker_died" + num ) );
deadfallbackers++;
}
println( deadfallbackers , " fallbackers have died, time to retreat" );
level notify( ( "fallbacker_trigger" + num ) );
}
fallback_think( trigger )
{
ignoreWhileFallingBack = false;
if( IsDefined( trigger.script_ignoreall ) && trigger.script_ignoreall )
{
ignoreWhileFallingBack = true;
}
if( ( !IsDefined( level.fallback ) ) ||( !IsDefined( level.fallback[trigger.script_fallback] ) ) )
{
percent = 0.5;
if( IsDefined( trigger.script_percent ) )
{
percent = trigger.script_percent / 100;
}
level thread fallback_overmind( trigger.script_fallback, trigger.script_fallback_group, ignoreWhileFallingBack, percent );
}
trigger waittill( "trigger" );
level notify( ( "fallbacker_trigger" + trigger.script_fallback ) );
kill_trigger( trigger );
}
fallback_add_previous_group(num, node_array)
{
if (!IsDefined (level.current_fallbackers[num - 1]))
{
return;
}
for (i = 0; i < level.current_fallbackers[num - 1]; i++)
{
level.max_fallbackers[num]++;
}
for (i = 0; i < level.current_fallbackers[num - 1]; i++)
{
level.current_fallbackers[num]++;
}
ai = GetAiArray();
for( i = 0; i < ai.size; i++ )
{
if( ( ( IsDefined( ai[i].script_fallback ) ) && ( ai[i].script_fallback == (num - 1) ) ) )
{
ai[i].script_fallback++;
if (IsDefined (ai[i].fallback_node))
{
ai[i].fallback_node.fallback_occupied = false;
ai[i].fallback_node = undefined;
}
}
}
}
delete_me()
{
maps\_spawner::waitframe();
self Delete();
}
waitframe()
{
wait( 0.05 );
}
friendly_mg42_death_notify( guy, mg42 )
{
mg42 endon( "friendly_finished_using_mg42" );
guy waittill( "death" );
mg42 notify( "friendly_finished_using_mg42" );
println( "^a guy using gun died" );
}
friendly_mg42_wait_for_use( mg42 )
{
mg42 endon( "friendly_finished_using_mg42" );
self.useable = true;
self setcursorhint("HINT_NOICON");
self setHintString(&"PLATFORM_USEAIONMG42");
self waittill( "trigger" );
println( "^a was used by player, stop using turret" );
self.useable = false;
self SetHintString( "" );
self StopUSeturret();
self notify( "stopped_use_turret" );
mg42 notify( "friendly_finished_using_mg42" );
}
friendly_mg42_useable( mg42, node )
{
if( self.useable )
{
return false;
}
if( ( IsDefined( self.turret_use_time ) ) &&( GetTime() < self.turret_use_time ) )
{
return false;
}
players = get_players();
for( q = 0; q < players.size; q++ )
{
if( Distancesquared( players[q].origin, node.origin ) < 100 * 100 )
{
return false;
}
}
if( IsDefined( self.chainnode ) )
{
player_count = 0;
for( q = 0; q < players.size; q++ )
{
if( Distancesquared( players[q].origin, self.chainnode.origin ) > 1100 * 1100 )
{
player_count++;
}
}
if( player_count == players.size )
{
return false;
}
}
return true;
}
friendly_mg42_endtrigger( mg42, guy )
{
mg42 endon( "friendly_finished_using_mg42" );
self waittill( "trigger" );
println( "^a Told friendly to leave the MG42 now" );
mg42 notify( "friendly_finished_using_mg42" );
}
noFour()
{
self endon( "death" );
self waittill( "goal" );
self.goalradius = self.oldradius;
if( self.goalradius < 32 )
{
self.goalradius = 400;
}
}
friendly_mg42_think( mg42, node )
{
self endon( "death" );
mg42 endon( "friendly_finished_using_mg42" );
level thread friendly_mg42_death_notify( self, mg42 );
self.oldradius = self.goalradius;
self.goalradius = 28;
self thread noFour();
self SetGoalNode( node );
self.ignoresuppression = true;
self waittill( "goal" );
self.goalradius = self.oldradius;
if( self.goalradius < 32 )
{
self.goalradius = 400;
}
self.ignoresuppression = false;
self.goalradius = self.oldradius;
players = get_players();
for( q = 0; q < players.size; q++ )
{
if( Distancesquared( players[q].origin, node.origin ) < 32 * 32 )
{
mg42 notify( "friendly_finished_using_mg42" );
return;
}
}
self.friendly_mg42 = mg42;
self thread friendly_mg42_wait_for_use( mg42 );
self thread friendly_mg42_cleanup( mg42 );
self USeturret( mg42 );
if( IsDefined( mg42.target ) )
{
stoptrigger = GetEnt( mg42.target, "targetname" );
if( IsDefined( stoptrigger ) )
{
stoptrigger thread friendly_mg42_endtrigger( mg42, self );
}
}
while( 1 )
{
if( Distance( self.origin, node.origin ) < 32 )
{
self USeturret( mg42 );
}
else
{
break;
}
if( IsDefined( self.chainnode ) )
{
if( Distance( self.origin, self.chainnode.origin ) > 1100 )
{
break;
}
}
wait( 1 );
}
mg42 notify( "friendly_finished_using_mg42" );
}
friendly_mg42_cleanup( mg42 )
{
self endon( "death" );
mg42 waittill( "friendly_finished_using_mg42" );
self friendly_mg42_doneUsingTurret();
}
friendly_mg42_doneUsingTurret()
{
self endon( "death" );
turret = self.friendly_mg42;
self.friendly_mg42 = undefined;
self StopUSeturret();
self notify( "stopped_use_turret" );
self.useable = false;
self.goalradius = self.oldradius;
if( !IsDefined( turret ) )
{
return;
}
if( !IsDefined( turret.target ) )
{
return;
}
node = GetNode( turret.target, "targetname" );
oldradius = self.goalradius;
self.goalradius = 8;
self SetGoalNode( node );
wait( 2 );
self.goalradius = 384;
return;
self waittill( "goal" );
if( IsDefined( self.target ) )
{
node = GetNode( self.target, "targetname" );
if( IsDefined( node.target ) )
{
node = GetNode( node.target, "targetname" );
}
if( IsDefined( node ) )
{
self SetGoalNode( node );
}
}
self.goalradius = oldradius;
}
tanksquish()
{
if ( IsDefined( level.noTankSquish ) )
{
assertex( level.noTankSquish, "level.noTankSquish must be true or undefined" );
return;
}
if ( IsDefined( level.levelHasVehicles ) && !level.levelHasVehicles )
{
return;
}
while ( 1 )
{
self waittill( "damage", amt, who, force, b, mod, d, e );
if ( !isDefined(mod) )
{
continue;
}
if ( mod != "MOD_CRUSH" )
{
continue;
}
if ( !IsDefined( self ) )
{
return;
}
if ( isalive( self ) )
{
continue;
}
if ( !isalive( who ) )
{
return;
}
force = vector_scale( force, 50000 );
force = ( force[ 0 ], force[ 1 ], abs( force[ 2 ] ) );
if(IsDefined( level._effect ) && IsDefined( level._effect["tanksquish"] ) )
{
PlayFX( level._effect["tanksquish"], self.origin + (0, 0, 30));
}
self startRagdoll();
self playsound( "chr_crunch" );
return;
}
}
spawnWaypointFriendlies()
{
self.count = 1;
spawn = self spawn_ai();
if ( spawn_failed( spawn ) )
{
return;
}
spawn.friendlyWaypoint = true;
}
goalVolumes()
{
volumes = GetEntArray( "info_volume", "classname" );
level.deathchain_goalVolume = [];
level.goalVolumes = [];
for( i = 0; i < volumes.size; i++ )
{
volume = volumes[i];
if( IsDefined( volume.script_deathChain ) )
{
level.deathchain_goalVolume[volume.script_deathChain] = volume;
}
if( IsDefined( volume.script_goalvolume ) )
{
level.goalVolumes[volume.script_goalVolume] = volume;
}
}
}
aigroup_init( aigroup, spawner )
{
if( !IsDefined( level._ai_group[aigroup] ) )
{
level._ai_group[aigroup] = SpawnStruct();
level._ai_group[aigroup].aigroup = aigroup;
level._ai_group[aigroup].aicount = 0;
level._ai_group[aigroup].spawnercount = 0;
level._ai_group[aigroup].killed_count = 0;
level._ai_group[aigroup].ai = [];
level._ai_group[aigroup].spawners = [];
level._ai_group[aigroup].cleared_count = 0;
if (!IsDefined(level.flag[aigroup + "_cleared"]))
{
flag_init(aigroup + "_cleared");
}
level thread set_ai_group_cleared_flag(level._ai_group[aigroup]);
}
if (IsDefined(spawner))
{
spawner thread aigroup_spawnerthink( level._ai_group[aigroup] );
}
}
aigroup_spawnerthink( tracker )
{
self endon( "death" );
self.decremented = false;
tracker.spawnercount++;
self thread aigroup_spawnerdeath( tracker );
self thread aigroup_spawnerempty( tracker );
while( self.count )
{
self waittill( "spawned", soldier );
if( spawn_failed( soldier ) )
{
continue;
}
soldier.aigroup = tracker.aigroup;
soldier thread aigroup_soldierthink( tracker );
}
waittillframeend;
if( self.decremented )
{
return;
}
self.decremented = true;
tracker.spawnercount--;
}
aigroup_spawnerdeath( tracker )
{
self waittill( "death" );
if( self.decremented )
{
return;
}
tracker.spawnercount--;
}
aigroup_spawnerempty( tracker )
{
self endon( "death" );
self waittill( "emptied spawner" );
waittillframeend;
if( self.decremented )
{
return;
}
self.decremented = true;
tracker.spawnercount--;
}
aigroup_soldierthink( tracker )
{
tracker.aicount++;
tracker.ai[tracker.ai.size] = self;
if ( IsDefined( self.script_deathflag_longdeath ) )
{
self waittillDeathOrPainDeath();
}
else
{
self waittill( "death" );
}
tracker.aicount--;
tracker.killed_count++;
}
set_ai_group_cleared_flag(tracker)
{
waittillframeend;
while (true)
{
if ((tracker.aicount + tracker.spawnercount) <= tracker.cleared_count)
{
flag_set(tracker.aigroup + "_cleared");
break;
}
wait .05;
}
}
flood_trigger_think( trigger )
{
assertEX( IsDefined( trigger.target ), "flood_spawner at " + trigger.origin + " without target" );
floodSpawners = GetEntArray( trigger.target, "targetname" );
assertex( floodSpawners.size, "flood_spawner at with target " + trigger.target + " without any targets" );
for(i = 0; i < floodSpawners.size; i++)
{
floodSpawners[i].script_trigger = trigger;
}
array_thread( floodSpawners, ::flood_spawner_init );
trigger waittill( "trigger" );
floodSpawners = GetEntArray( trigger.target, "targetname" );
{
array_thread( floodSpawners, ::flood_spawner_think, trigger );
}
}
flood_spawner_init( spawner )
{
assertex(self has_spawnflag(level.SPAWNFLAG_ACTOR_SPAWNER), "Spawner at origin" + self.origin + "/" +( self GetOrigin() ) + " is not a spawner!");
}
trigger_requires_player( trigger )
{
if( !IsDefined( trigger ) )
{
return false;
}
return IsDefined( trigger.script_requires_player );
}
flood_spawner_think( trigger )
{
self endon( "death" );
self notify( "stop current floodspawner" );
self endon( "stop current floodspawner" );
requires_player = trigger_requires_player( trigger );
script_delay();
while( self.count > 0 )
{
if( requires_player )
{
while( !any_player_IsTouching( trigger ) )
{
wait( 0.5 );
}
}
while(!(self ok_to_trigger_spawn()))
{
wait_network_frame();
}
soldier = self spawn_ai();
if( spawn_failed( soldier ) )
{
wait( 2 );
continue;
}
level._numTriggerSpawned ++;
soldier thread reincrement_count_if_deleted( self );
soldier waittill( "death", attacker );
if ( !player_saw_kill( soldier, attacker ) )
{
self.count++;
}
if( !IsDefined( soldier ) )
{
continue;
}
if( !script_wait( true ) )
{
players = get_players();
if (players.size == 1)
{
wait( RandomFloatrange( 5, 9 ) );
}
else if (players.size == 2)
{
wait( RandomFloatrange( 3, 6 ) );
}
else if (players.size == 3)
{
wait( RandomFloatrange( 1, 4 ) );
}
else if (players.size == 4)
{
wait( RandomFloatrange( 0.5, 1.5 ) );
}
}
}
}
player_saw_kill( guy, attacker )
{
if ( IsDefined( self.script_force_count ) )
{
if ( self.script_force_count )
{
return true;
}
}
if ( !IsDefined( guy ) )
{
return false;
}
if ( IsAlive( attacker ) )
{
if ( IsPlayer( attacker ) )
{
return true;
}
players = get_players();
for( q = 0; q < players.size; q++ )
{
if ( DistanceSquared( attacker.origin, players[q].origin ) < 200 * 200 )
{
return true;
}
}
}
else
{
if ( IsDefined( attacker ) )
{
if ( attacker.classname == "worldspawn" )
{
return false;
}
player = get_closest_player( attacker.origin );
if ( IsDefined( player ) && distance( attacker.origin, player.origin ) < 200 )
{
return true;
}
}
}
closest_player = get_closest_player( guy.origin );
if ( IsDefined( closest_player ) && distance( guy.origin, closest_player.origin ) < 200 )
{
return true;
}
return bulletTracePassed( closest_player geteye(), guy geteye(), false, undefined );
}
show_bad_path()
{
}
objective_event_init( trigger )
{
flag = trigger get_trigger_flag();
assertex( IsDefined( flag ), "Objective event at origin " + trigger.origin + " does not have a script_flag. " );
flag_init( flag );
assertex( IsDefined( level.deathSpawner[trigger.script_deathChain] ), "The objective event trigger for deathchain " + trigger.script_deathchain + " is not associated with any AI." );
while( level.deathSpawner[trigger.script_deathChain] > 0 )
{
level waittill( "spawner_expired" + trigger.script_deathChain );
}
flag_set( flag );
}
#using_animtree( "generic_human" );
spawner_dronespawn( spawner )
{
assert( IsDefined( level.dronestruct[ spawner.classname ] ) );
struct = level.dronestruct[ spawner.classname ];
drone = spawn( "script_model", spawner.origin );
drone.angles = spawner.angles;
drone setmodel( struct.model );
drone UseAnimTree( #animtree );
drone makefakeai();
attachedmodels = struct.attachedmodels;
attachedtags = struct.attachedtags;
for ( i = 0;i < attachedmodels.size;i++ )
{
drone attach( attachedmodels[ i ], attachedtags[ i ], true );
}
if ( IsDefined( struct.weapon ) )
{
drone.weapon = struct.weapon;
self call_overloaded_func( "animscripts\init", "initWeapon", drone.weapon );
drone useweaponhidetags( drone.weapon );
}
if ( IsDefined( spawner.script_startingposition ) )
{
drone.script_startingposition = spawner.script_startingposition;
}
if ( IsDefined( spawner.script_noteworthy ) )
{
drone.script_noteworthy = spawner.script_noteworthy;
}
if ( IsDefined( spawner.script_deleteai ) )
{
drone.script_deleteai = spawner.script_deleteai;
}
if ( IsDefined( spawner.script_linkto ) )
{
drone.script_linkto = spawner.script_linkto;
}
if ( IsDefined( spawner.script_moveoverride ) )
{
drone.script_moveoverride = spawner.script_moveoverride;
}
if ( issubstr( spawner.classname, "ally" ) )
{
drone.team = "allies";
}
else if ( issubstr( spawner.classname, "enemy" ) )
{
drone.team = "axis";
}
else
{
drone.team = "neutral";
}
if ( IsDefined( spawner.target ) )
{
drone.target = spawner.target;
}
drone.spawner = spawner;
assert( IsDefined( drone ) );
if ( IsDefined( spawner.script_noteworthy ) && spawner.script_noteworthy == "drone_delete_on_unload" )
{
drone.drone_delete_on_unload = true;
}
else
{
drone.drone_delete_on_unload = false;
}
spawner notify( "drone_spawned", drone );
return drone;
}
spawner_make_real_ai( drone )
{
if(!IsDefined(drone.spawner))
{
println("----failed dronespawned guy info----");
println("drone.classname: "+drone.classname);
println("drone.origin : "+drone.origin);
assertmsg("makerealai called on drone does with no .spawner");
}
orgorg = drone.spawner.origin;
organg = drone.spawner.angles;
drone.spawner.origin = drone.origin;
drone.spawner.angles = drone.angles;
guy = drone.spawner stalingradspawn();
failed = spawn_failed(guy);
if(failed)
{
println("----failed dronespawned guy info----");
println("failed guys spawn position : "+drone.origin);
println("failed guys spawner export key: "+drone.spawner.export);
println("getaiarray size is: "+getaiarray().size);
println("------------------------------------");
assertMSG("failed to make real ai out of drone (see console for more info)");
}
drone.spawner.origin = orgorg;
drone.spawner.angles = organg;
drone Delete();
return guy;
}