#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; }