cod4-sdk/raw/maps/bog_a_code.gsc
2008-01-19 00:00:00 +00:00

3486 lines
79 KiB
Text
Raw Permalink Blame History

#include maps\_utility;
#include maps\_vehicle;
#include common_scripts\utility;
#include maps\_anim;
#include maps\bog_a;
#include animscripts\utility;
start_court()
{
level.player setOrigin ( getnode( "start_leaving_apartment", "targetname" ).origin );
}
start_melee()
{
ai = getaiarray( "axis" );
array_thread( ai, ::delete_me );
thread melee_sequence();
level.player setplayerangles( ( 0, 240, 0) );
level.player setorigin( ( 10181.9, 708.265, 100.567 ) );
}
start_breach()
{
flag_set( "second_floor_door_breach_initiated" );
ai = getaiarray( "axis" );
array_thread( ai, ::delete_me );
thread melee_sequence();
level.player setplayerangles( ( 0, 180, 0) );
level.player setorigin( ( 9976.2, 423.6, 236 ) );
thread second_floor_door_breach_setup();
for ( ;; )
{
second_floor_door_breach_trigger = getent( "second_floor_door_breach_trigger", "script_noteworthy" );
second_floor_door_breach_trigger notify( "trigger" );
wait( 1 );
}
}
second_floor_door_breach_setup()
{
for( ;; )
{
second_floor_door_breach_guys( true );
door = getent( "apartment_second_floor_door_breach", "targetname" );
door connectPaths();
door door_opens(-1);
}
}
start_apart()
{
/*
thread friendlies_arrange_in_hallway_of_apartment();
red = getent( "red_friendly", "targetname" );
green = getent( "green_friendly", "targetname" );
red teleport( ( 10273, 808, 105 ) );
green teleport( ( 10279, 877, 94 ) );
node = getnode( "friendly_destination_node", "targetname" );
red setgoalnode( node );
green setgoalnode( node );
red.goalradius = node.radius;
green.goalradius = node.radius;
level.player setplayerangles( ( 0, 240, 0) );
level.player setorigin( ( 10381, 870, 102 ) );
*/
thread melee_sequence();
level.player setplayerangles( ( 0, 240, 0) );
level.player setorigin( ( 10181.9, 708.265, 100.567 ) );
}
spawn_guys_that_run_away( msg )
{
spawners = getentarray( msg, "targetname" );
array_thread( spawners, ::spawn_guy_that_runs_away );
}
spawn_guy_that_runs_away()
{
self.count = 1;
spawn = self spawn_ai();
if ( spawn_failed( spawn ) )
return;
spawn endon( "death" );
defaultDist = spawn.pathEnemyFightDist;
spawn.pathEnemyFightDist = 0;
spawn waittill( "goal" );
spawn.pathEnemyFightDist = defaultDist;
}
delayed_spawn_and_kill( msg, timer )
{
wait( timer );
spawner = getent( msg, "targetname" );
spawn = spawner spawn_ai();
if ( spawn_failed( spawn ) )
return;
spawn dodamage( spawn.health + 50, ( 0,0,0 ) );
}
ai_walk_trigger()
{
for ( ;; )
{
self waittill( "trigger", other );
if ( other.team == "axis" )
return;
other cqb_walk( "on" );
if ( !flag( "night_vision" ) )
{
flag_set( "night_vision" );
green = getent( "green_friendly", "targetname" );
// <Cpl Black> Switching to night vision" );
green anim_single_solo( green, "night_vision" );
}
}
}
friendlies_wait_for_ambush_then_fight_back()
{
self endon( "death" );
self.pacifist = true;
self.goalheight = 48;
// self.pathenemylookahead = 100;
// self.pathenemyfightdist = 100;
flag_wait( "friendlies_take_fire" );
self.pacifist = false;
}
rooftop_damage_trigger()
{
trigger = getent( "rooftop_damage_trigger", "targetname" );
trigger waittill( "trigger" );
trigger delete();
flag_set( "rooftop_guys_fall_back" );
}
bridge_truck_pauses_then_leaves()
{
truck = spawn_vehicle_from_targetname( "bridge_truck_pause" );
truck drives();
getvehiclenode( "bridge_pause_node", "script_noteworthy" ) waittill( "trigger" );
truck setspeed( 0, 12 );
wait( 10 );
truck setspeed( 25, 10 );
}
bridge_damage_trigger()
{
trigger = getent( "bridge_damage_trigger", "targetname" );
for ( ;; )
{
trigger waittill( "trigger", other );
if ( other == level.player )
break;
if ( !isdefined( other.team ) )
{
println( "Other was " + other.classname );
continue;
}
if ( other.team == "axis" )
flag_set( "bridge_walkers_attack" );
}
flag_set( "bridge_damage_trigger" );
}
bridge_runners()
{
wait( 3 );
spawn = self spawn_ai();
if ( spawn_failed( spawn ) )
return;
spawn endon( "death" );
node = getnode( spawn.target, "targetname" );
spawn setgoalnode( node );
spawn.interval = 0;
spawn.ignoresuppression = true;
spawn.goalradius = 64;
spawn waittill( "goal" );
if ( level.bridge_damage_trigger == "cleared" )
{
level.bridge_damage_trigger = "set";
thread bridge_damage_trigger();
}
wait_for_flag_or_timeout( "bridge_damage_trigger", 13 );
flag_set( "bridge_runners_flee" );
waitSpread( 1, 5 );
node = getnode( "early_bridge_node", "targetname" );
spawn setgoalnode( node );
}
bridge_truck_drives( msg )
{
maps\_vehicle::create_vehicle_from_spawngroup_and_gopath( msg );
}
vehicle_delete_trigger()
{
level endon( "player_enters_laundrymat" );
trigger = getent( "vehicle_delete_trigger", "targetname" );
for (;;)
{
trigger waittill( "trigger", other );
other delete();
}
}
bad_infantry_attack()
{
level.bad_infantry_count = 0;
array = getentarray( "tank_killing_guy", "targetname" );
// array_thread( array, ::bad_infantry_spawner );
}
bad_infantry_spawner()
{
self endon( "death" );
for ( ;; )
{
wait( randomfloatrange( 1, 2 ) );
if ( level.bad_infantry_count >= 10 )
{
level waittill( "bad_infantry_died" );
continue;
}
self.count = 1;
spawn = self stalingradSpawn(); // on a bridge where their heads might be visible or some such
if ( spawn_failed( spawn ) )
continue;
spawn thread bad_infantry_think();
}
}
bad_infantry_think()
{
level.bad_infantry_count++;
node = getnode( "tank_kill_node", "targetname" );
if ( isalive( level.goodTank ) )
self setEntityTarget( level.goodTank );
self setgoalnode( node );
self.goalradius = 384;
thread bad_infantry_reaches_goal_and_deletes();
self waittill( "death" );
level.bad_infantry_count--;
level notify( "bad_infantry_died" );
}
bad_infantry_reaches_goal_and_deletes()
{
self endon( "death" );
self waittill( "goal" );
self delete();
}
stop_at_node( msg )
{
self notify( "new_stop_node" );
thread stop_at_node_thread( msg );
}
stop_at_node_thread( msg )
{
self endon( "new_stop_node" );
self endon( "death" );
getvehiclenode( msg, "script_noteworthy" ) waittill ("trigger");
self setSpeed(0, 100);
}
opens_fire()
{
thread open_fire_thread();
}
open_fire_thread()
{
assertEx( isalive( self.current_target ), "Told tank to target a dead or non existant target" );
self endon( "death" );
self endon( "stop_firing" );
self.current_target endon( "death" );
for ( ;; )
{
self fireWeapon();
wait ( randomfloatrange( 5, 12 ) );
}
}
stop_firing_when_target_dies()
{
thread stop_firing_when_target_dies_thread();
}
stop_firing_when_target_dies_thread()
{
self.current_target waittill( "death" );
stops_firing();
}
stops_firing()
{
self notify( "stop_firing" );
}
targets_tank( tank )
{
thread targets_tank_thread( tank );
}
targets_tank_thread( tank )
{
wait( 0.11 );
self setTurretTargetEnt( tank, (0,0,60) );
self.current_target = tank;
}
becomes_vulnerable()
{
self godOff();
self.health = 1;
}
drives()
{
thread goPath( self );
}
heli_riders_spawn_and_delete()
{
self waittill( "spawned", spawn );
if ( spawn_failed( spawn ) )
return;
spawn endon( "death" );
level waittill( "heli_gone" );
spawn delete();
}
heli_guys_run_in()
{
wait( 3 );
spawners = getentarray( "heli_squad_spawner", "targetname" );
for ( i=0; i<spawners.size; i++ )
{
spawn = spawners[ i ] spawn_ai();
if ( spawn_failed( spawn ) )
continue;
spawn.goalradius = 200;
spawn setGoalPos( ( 8131.3, 2652.8, 87.8 ) );
}
}
helicopter_drops_off_guys()
{
// getent( "guy", "targetname" ) thread testguy();
heli_squad = getentarray( "heli_squad", "targetname" );
array_thread( heli_squad, ::heli_riders_spawn_and_delete );
dest = getent( "heli_path", "targetname" );
// heli = spawnVehicle( "vehicle_blackhawk", "helicopter", "blackhawk", dest.origin, dest.angles );
heli = spawn_vehicle_from_targetname( "heli" );
heli.health = 10000000;
heli setSpeed( 150, 35, 35 );
heli setneargoalnotifydist( 500 );
for ( ;; )
{
if ( !isdefined( dest.target ) )
break;
dest = getent( dest.target, "targetname" );
heli setgoalyaw( dest.angles[ 1 ] );
heli setVehGoalPos( dest.origin, true );
while ( distance( heli.origin, dest.origin ) >= 500 )
wait( 0.05 );
}
heli setneargoalnotifydist( 50 );
heli waittill( "near_goal" );
heli notify( "unload" );
wait( 8 );
thread heli_guys_run_in();
heli setSpeed( 50, 15, 15 );
heli setneargoalnotifydist( 500 );
dest = getent( "heli_retreat_path", "targetname" );
for ( ;; )
{
heli setVehGoalPos( dest.origin, true );
while ( distance( heli.origin, dest.origin ) >= 500 )
wait( 0.05 );
heli setSpeed( 150, 25, 15 );
if ( !isdefined( dest.target ) )
break;
dest = getent( dest.target, "targetname" );
heli setgoalyaw( dest.angles[ 1 ] );
}
heli delete();
level notify( "heli_gone" );
}
draw_dest_line( org )
{
self notify( "new_dest_line" );
self endon( "new_dest_line" );
for ( ;; )
{
line( self.origin, org, (1,1,0) );
wait( 0.05 );
}
}
helicopter_flies_by_overhead( name, delay, maxspeed, accel )
{
if ( isdefined( delay ) )
wait( delay );
heli = spawn_vehicle_from_targetname( name );
heli heli_flies( maxspeed, accel);
}
helicopters_flies_by_overhead( name, delay, maxspeed, accel )
{
if ( isdefined( delay ) )
wait( delay );
helis = spawn_vehicles_from_targetname( name );
assertEx( helis.size > 1, "Tried to spawn multiple helicopters with the plural command, use helicopter_flies_by_overhead" );
helis = array_randomize( helis );
remove = 3;
for ( i=0; i < helis.size - remove; i++ )
{
helis[ i ] thread heli_flies( maxspeed, accel );
}
for ( i=helis.size - remove; i < helis.size; i++ )
{
helis[ i ] delete();
}
}
heli_flies( maxspeed, accel )
{
self endon( "death" );
self.script_turretmg = false;
self.health = 10000000;
self setTurningAbility( 1 );
self helipath( self.target, maxspeed, accel );
self delete();
}
lookatpath( msg )
{
viewTarget = getent( msg, "targetname" );
self setLookAtEnt( viewTarget );
wait( 1.5 );
}
aim_trigger_think()
{
ai = [];
for ( ;; )
{
self waittill( "trigger", other );
if ( isdefined( ai[ other.ai_number ] ) )
continue;
ai[ other.ai_number ] = true;
thread aimsAtSelf( other );
}
}
aimsAtSelf( ent )
{
targ = getent( self.target, "targetname" );
ent endon( "death" );
ent cqb_aim( targ );
while ( ent istouching( self ) )
{
wait( 0.05 );
continue;
}
ent cqb_aim();
// iprintlnbold( "Room clear!" );
}
acquire_ai()
{
// grab ai that touch the trigger and thread off the death notify
ai = [];
for ( ;; )
{
self waittill( "trigger", other );
if ( isdefined( ai[ other.ai_number ] ) )
continue;
ai[ other.ai_number ] = true;
other thread ai_tells_trigger_he_died( self );
}
}
ai_tells_trigger_he_died( trigger )
{
self waittill( "death" );
if ( self isTouching( trigger ) )
{
trigger.deaths++;
trigger notify( "died" );
}
}
street_guys_run_for_it()
{
self endon( "death");
node = getnode( self.target, "targetname" );
self setgoalnode( node );
self.goalradius = 32;
self.ignoresuppression = true;
self setThreatBiasGroup( "street_guys" );
flag_wait( "street_guys_run" );
waitSpread( 0, 3 );
for ( ;; )
{
self waittill( "goal" );
if ( !isdefined( node.target ) )
break;
node = getnode( node.target, "targetname" );
self setgoalnode( node );
}
if ( !( self cansee( level.player ) ) )
{
// poof!
self delete();
}
}
ai_enters_apartment( nodename )
{
level.apartment_reach++;
node = getnode( "right_house_node", "targetname" );
waitSpread( 0.01, 2.5 );
self setgoalnode( node );
self.ignoresuppression = true;
self.goalradius = 32;
self waittill( "goal" );
node = getnode( node.target, "targetname" );
self setgoalnode( node );
self waittill( "goal" );
node = getnode( nodename, "targetname" );
self setgoalnode( node );
self waittill( "goal" );
self.ignoresuppression = false;
level.apartment_reach--;
if ( !level.apartment_reach )
flag_set( "reached_apartment" );
}
door_opens( mod )
{
self playsound ("wood_door_kick");
rotation = -140;
if ( isdefined( mod ) )
rotation *= mod;
self rotateyaw( rotation, .3, 0, .3);
self connectpaths();
}
wave()
{
thread waveProc();
}
waveProc()
{
self notify( "do_a_wave" );
self endon( "do_a_wave" );
self setflaggedanimrestart( "wave", level.scr_anim[ self.animname ][ "wave" ], 1, .1, 1 );
// thread notetrackprinter( "wave" );
// self waittillend( "wave" );
wait( 3 );
self clearanim( level.scr_anim[ self.animname ][ "wave" ], 0.1 );
}
notetrackprinter( msg )
{
self endon( "death" );
self notify( "notetrackprinter" + msg );
self endon( "notetrackprinter" + msg );
for ( ;; )
{
self waittill( msg, notetrack );
println( "Recieved " + msg + " notetrack: " + notetrack );
}
}
target_spot_delayed( org, timer )
{
self endon( "death" );
wait( timer );
self cqb_aim( org );
}
melee_sequence()
{
// first setup all the entities. Notice they all originate from one entree point in the map!
trigger = getent( "start_melee", "targetname" );
sequence_trigger = getent( trigger.target, "targetname" );
friendly_spawner = getent( sequence_trigger.target, "targetname" );
friendly_spawner.script_moveoverride = true;
enemy_spawner = getent( "melee_enemy_spawner", "targetname" );
enemy_spawner.script_moveoverride = true;
start_node = getnode( friendly_spawner.target, "targetname" );
player_break_trigger = getent( "player_breaks_melee_sequence", "targetname" );
ai_trigger = getent( "melee_ai_trigger", "targetname" );
end_node = getnode( enemy_spawner.target, "targetname" );
// wall_blocker = getent( trigger.script_linkto, "script_linkname" );
// wall_blocker connectPaths();
// wall_blocker notsolid();
// spawn_blocker disconnectPaths();
trigger waittill( "trigger" );
// spawn a wall in so ai dont run through here during melee sequence
// wall_blocker disConnectPaths();
// wall_blocker solid();
friendly = friendly_spawner spawn_ai();
if ( spawn_failed( friendly ) )
{
assertEx( 0, "key friendly failed to spawn" );
return;
}
friendly.ignoreall = true;
friendly.ignoreme = true;
friendly.pathenemyfightdist = 0;
friendly.pathenemylookahead = 0;
friendly.goalheight = 64; // don't go running upstairs buddy!
friendly.goalradius = 32;
friendly.IgnoreRandomBulletDamage = true;
enemy = enemy_spawner spawn_ai();
if ( spawn_failed( enemy ) )
{
assertEx( 0, "key enemy failed to spawn" );
return;
}
enemy.ignoreme = true;
enemy.goalradius = 32;
enemy.health = 1;
enemy pushplayer( true );
enemy.dontavoidplayer = true;
enemy setthreatbiasgroup( "melee_struggle_guy" ); // so he doesnt ignore the player when the player is inside
enemy thread achievement( friendly );
sequence_trigger waittill( "trigger" );
if ( level.start_point != "melee" )
assertEx( flag( "friendlies_lead_player" ), "Friendlies were not told to lead the player soon enough." );
flag_set( "melee_sequence_begins" );
autosave_by_name( "melee_sequence" );
// clear_player_threatbias_vs_apartment_enemies_and_autosave();
// wall_blocker connectPaths();
// wall_blocker delete();
friendly setgoalnode( end_node );
friendly.dontshootstraight = true;
friendly.goalradius = 4;
ai_trigger waittill( "trigger", other );
if ( other == friendly && !flag( "player_interupts_melee_struggle" ) )
{
friendly.IgnoreRandomBulletDamage = false;
// if the player hits the trigger then abort the sequence
melee_sequence_plays_out( friendly, enemy );
if ( isdefined( friendly ) )
{
friendly playsound( "bog_scn_melee_struggle_end" );
}
if ( isalive( enemy ) && !( enemy canSee( level.player ) ) )
{
// player ran past sequence so just kill the enemy
enemy dodamage( enemy.health + 50, (0,0,0) );
}
}
else
{
if ( isalive( friendly ) )
friendly.dontshootstraight = false;
}
if ( isalive( enemy ) )
{
enemy.deathanim = undefined;
enemy.ignoreme = false;
// enemy animscripts\shared::placeWeaponOn( enemy.primaryweapon, "right" );
// in case you killed the friendly and the enemy is still playing the sequence
enemy stopAnimScripted();
}
/#
if ( !is_default_start() )
return;
#/
if ( isalive( friendly ) )
{
level.saved_friendly = friendly;
level.saved_friendly thread magic_bullet_shield();
friendly setThreatbiasGroup( "friendlies_under_unreachable_enemies" );
friendly set_default_pathenemy_settings();
friendly set_force_color( "p" );
friendly.a.nodeath = false;
friendly.ignoreall = false;
friendly.IgnoreRandomBulletDamage = false;
friendly.ignoreSuppression = true;
}
else
{
instantly_promote_nearest_friendly( "b", "p" );
}
flag_set( "melee_sequence_complete" );
}
achievement( friendly )
{
self waittill( "death", attacker );
if ( !isalive( friendly ) )
return;
if ( !isalive( attacker ) )
return;
if ( attacker != level.player )
return;
maps\_utility::giveachievement_wrapper( "RESCUE_ROYCEWICZ" );
}
melee_sequence_plays_out( friendly, enemy )
{
level endon( "stop_melee_sequence" );
if ( !isalive( friendly ) )
return;
if ( !isalive( enemy ) )
return;
friendly endon( "death" );
enemy endon( "death" );
friendly.animName = "paulsen";
enemy.animName = "emslie";
enemy.deathanim = enemy getanim( "death" );
animArray = [];
animArray[ 0 ] = friendly;
animArray[ 1 ] = enemy;
// now in notetrack so you cant kill him earlier and have him keep playing the normal anim
// friendly.a.nodeath = true;
//node = getent( "melee_root", "targetname" );
animbase = spawn( "script_origin", (0,0,0) );
// animbase.angles = friendly.angles + (0, 110, 0);
// animbase.origin = friendly.origin + (0,0,0);
animbase.origin = ( 9705, 1207, 112 );
animbase.angles = ( 0, 294, 0 );
// println("animbase origin " + animbase.origin + " and angles " + animbase.angles );
// defender teleport( node.origin );
// attacker teleport( node.origin );
friendly.allowDeath = true;
enemy.allowDeath = true;
friendly.end_melee_animation = "stand_death";
friendly thread saved_from_melee( enemy );
friendly.health = 1;
// gah!
friendly thread anim_single_solo( friendly, "gah" );
animbase anim_single( animArray, "melee" );
}
paulsen_end_standDeath( guy )
{
// called from a notetrack
guy.end_melee_animation = undefined;
}
paulsen_start_backDeath1( guy )
{
// called from a notetrack
guy.end_melee_animation = "back_death1";
guy.a.nodeath = true;
guy notify( "new_end_melee_animation" );
}
paulsen_start_backDeath2( guy )
{
// called from a notetrack
guy.end_melee_animation = "back_death2";
guy.a.nodeath = true;
guy notify( "new_end_melee_animation" );
}
paulsen_end_fire( guy )
{
guy.a.lastShootTime = gettime();
guy thread play_sound_on_tag( "weap_m4carbine_fire_npc", "tag_flash" );
PlayFXOnTag( getfx( "special_fire" ), guy, "tag_flash" );
angles = guy gettagangles( "tag_flash" );
forward = anglestoforward( angles );
vec = vectorscale( forward, 5000 );
start = guy gettagorigin( "tag_flash" );
end = start + vec;
trace = bullettrace( start, end, false, undefined );
playfx( getfx( "flesh_hit" ), trace[ "position" ], ( 0, 0, 1 ) );
thread play_sound_in_space( "bullet_large_flesh", trace[ "position" ] );
pos = trace[ "position" ];
forward = anglestoforward( ( 0, self.angles[ 1 ], 0 ) );
vec = vectorscale( forward, -5 );
pos = pos + vec;
trace = bullettrace( pos + (0,0,5), pos + (0,0,-50 ), false, undefined );
playfx( getfx( "blood_pool" ), trace[ "position" ], ( 0, 0, 1 ) );
}
orient_to_guy( enemy )
{
self endon( "stop_orienting" );
org = enemy.origin;
for ( ;; )
{
if ( isdefined( enemy ) && isdefined( enemy.origin ) )
{
org = enemy.origin;
}
angles = vectortoangles( org - self.origin );
yaw = angles[ 1 ] - 20;
self OrientMode( "face angle", yaw );
wait( 0.05 );
}
}
saved_from_melee( enemy )
{
self endon( "death" );
enemy waittill( "death" );
org = enemy.origin;
if ( !isdefined( self.end_melee_animation ) )
self waittill( "new_end_melee_animation" );
if ( self.end_melee_animation == "stand_death" )
{
self thread anim_custom_animmode_solo( self, "gravity", self.end_melee_animation );
self thread orient_to_guy( enemy );
}
else
{
self thread anim_single_solo( self, self.end_melee_animation );
}
self waittill_either( self.end_melee_animation, "damage" );
self notify( "stop_orienting" );
self.dontshootstraight = false;
}
/*
friendly_rejoins_party()
{
level.saved_friendly = self;
node = getnode( "friendly_saved_node", "targetname" );
self setgoalnode( node );
self.health = 150;
self endon( "death" );
wait( 1.2 );
self anim_single_solo( self, "thanks_carver" );
}
*/
threatbias_lower_trigger()
{
self endon( "death" );
for ( ;; )
{
self waittill( "trigger", other );
assertEx( other == level.player, "Threatbias triggers should only be used on the player." );
if ( !isdefined( other.normal_threatbias ) )
{
other.normal_threatbias = other.threatbias;
}
else
{
// does this guy already have this threatbias lowered?
if ( other.normal_threatbias != other.threatbias )
continue;
}
other.threatbias -= 1500;
wait( 2 );
}
}
threatbias_normal_trigger()
{
self endon( "death" );
for ( ;; )
{
self waittill( "trigger", other );
assertEx( other == level.player, "Threatbias triggers should only be used on the player." );
if ( !isdefined( other.normal_threatbias ) )
continue;
other.threatbias = other.normal_threatbias;
wait( 2 );
}
}
/*
spawn_from_targetname( targetname, optional_func )
{
spawners = getentarray( targetname, "targetname" );
has_optional_func = isdefined( optional_func );
for ( i=0; i < spawners.size; i++ )
{
spawn = spawners[ i ] spawn_ai();
if ( spawn_failed( spawn ) )
continue;
if ( has_optional_func )
spawn [[ optional_func ]]();
}
}
*/
spawn_guy_from_targetname( targetname )
{
guy = spawn_guys_from_targetname( targetname );
assertEx( guy.size == 1, "Tried to spawn a single guy from spawner with targetname " + targetname + " but it had multiple guys." );
assertEx( isalive( guy[ 0 ] ), "Failed to spawn a required guy from targetname " + targetname );
return guy[ 0 ];
}
spawn_guys_from_targetname( targetname )
{
guys = [];
spawners = getentarray( targetname, "targetname" );
for ( i=0; i < spawners.size; i++ )
{
spawner = spawners[i];
spawner.count = 1;
guy = spawner spawn_ai();
spawn_failed( guy );
assertEx( isalive( guy ), "Guy from spawner with targetname " + targetname + " at origin " + spawner.origin + " failed to spawn" );
guys[ guys.size ] = guy;
}
return guys;
}
force_spawn_guys_from_targetname( targetname )
{
guys = [];
spawners = getentarray( targetname, "targetname" );
for ( i=0; i < spawners.size; i++ )
{
spawner = spawners[i];
spawner.count = 1;
guy = spawner stalingradspawn();
spawn_failed( guy );
assertEx( isalive( guy ), "Guy from spawner with targetname " + targetname + " at origin " + spawner.origin + " failed to spawn" );
guys[ guys.size ] = guy;
}
return guys;
}
vis_blocker_waits_for_deletion()
{
vis_blocker_delete_trigger = getent( "vis_blocker_delete_trigger", "targetname" );
vis_blocker_delete_trigger waittill( "trigger" );
vis_blocker = getent( "vis_blocking_brush", "targetname" );
vis_blocker delete();
}
/*
friendly_ignore_upstairs_guys_trigger()
{
self endon( "death" );
for ( ;; )
{
self waittill( "trigger", other );
assertEx( isalive( other ), "Dead guy triggered a trigger! Nos!" );
other setThreatBiasGroup( "friendlies_under_unreachable_enemies" );
}
}
friendly_can_attack_upstairs_guys_trigger()
{
self endon( "death" );
for ( ;; )
{
self waittill( "trigger", other );
assertEx( isalive( other ), "Dead guy triggered a trigger! Nos!" );
other setThreatBiasGroup( "allies" );
}
}
*/
enable_pacifists_to_attack_me()
{
self endon( "death" );
for ( ;; )
{
self waittill( "trigger", other );
if ( other == level.player )
{
// level.player.threatbias = -250;
continue;
}
other setthreatbiasgroup( "friendlies_under_unreachable_enemies" );
}
}
ignores_unreachable_enemies()
{
self setthreatbiasgroup( "friendlies_flanking_apartment" );
self.ignoresuppression = true; // gotta get him to go, can turn it back on later
}
set_threatbias_group( group )
{
assert( threatbiasgroupexists( group ) );
self setthreatbiasgroup( group );
}
wait_until_its_time_to_flank()
{
// if the player hangs back, the friendlies will call for flanking after a few seconds, but if the player rushes
// ahead then they will call for flanking immediately.
trigger = getent( "moveup_trigger", "targetname" );
force_trigger = getent( trigger.target, "targetname" );
force_trigger wait_for_trigger_or_timeout( 10 );
}
waittill_triggered_by_ai( team )
{
for ( ;; )
{
self waittill( "trigger", other );
if ( other == level.player )
continue;
if ( !isdefined( team ) )
return;
if ( other.classname == "worldspawn" )
{
println( "waittill_triggered_by_ai(): hit by worldspawn: ", other.classname );
continue;
}
if ( team == other.team )
return;
}
}
tally_pacifists()
{
waittillframeend;
ai = getaiarray();
tally[ "axis" ] = 0;
tally[ "allies" ] = 0;
for ( i=0; i < ai.size; i++ )
{
guy = ai[ i ];
if ( guy.pacifist )
tally[ guy.team ]++;
}
println( tally[ "allies" ] + " pacifist friendlies of " + getaiarray( "allies" ).size + " friendlies, " + tally[ "axis" ] + " pacifist enemies of " + getaiarray( "axis" ).size + " enemies." );
}
put_function_on_spawners( spawners, function )
{
array_thread( spawners, ::spawner_runs_function_on_spawn, function );
}
spawner_runs_function_on_spawn( function )
{
self endon( "death" );
for ( ;; )
{
self waittill( "spawned", spawn );
if ( spawn_failed( spawn ) )
{
assertEx( 0, "Impossible!" );
continue;
}
spawn [[ function ]]();
}
}
alley_roof_guy()
{
// runs over and shoots the player when he gets on the roof
self endon( "death" );
flag_wait( "player_enters_roof" );
roof_nodes = getnodearray( "roof_node", "targetname" );
roof_nodes = array_randomize( roof_nodes );
for ( i=0; i < roof_nodes.size; i++ )
{
node = roof_nodes[ i ];
if ( isdefined( node.roof_occupied ) )
continue;
node.roof_occupied = true;
self setgoalnode( node );
self.goalradius = 64;
return;
}
}
alley_smg_playerseeker()
{
self setthreatbiasgroup( "player_seeker" );
self setEngagementMinDist( randomintrange( 100, 225 ), 0 );
maxdist = randomintrange( 300, 400 );
self setEngagementMaxDist( maxdist, maxdist + 200 );
self.pathenemyfightdist = 185;
self.pathenemylookahead = 185;
}
alley_sniper_engagementdistance()
{
self setEngagementMinDist( 450, 450 );
self setEngagementMaxDist( 1500, 2500 );
}
alley_smg_engagementdistance()
{
self setEngagementMinDist( 350, 0 );
self setEngagementMaxDist( 450, 550 );
}
alley_close_smg_engagementdistance()
{
self setEngagementMinDist( 0, 0 );
self setEngagementMaxDist( 200, 300 );
}
toggle_alley_badplace()
{
source_ent = getent( "friendly_badplace_arc", "targetname" );
dest_ent = getent( source_ent.target, "targetname" );
origin = source_ent.origin;
direction = origin - dest_ent.origin;
source_ent delete();
dest_ent delete();
for ( ;; )
{
flag_wait( "player_near_alley_building" );
badplace_arc( "alley_badplace", 0, origin, 0, 64, direction, 5, 5, "allies" );
flag_waitopen( "player_near_alley_building" );
badplace_delete( "alley_badplace" );
}
}
ambush_clear()
{
// getent( "apartment_door", "targetname" ) delete();
flag_set( "friendlies_take_fire" );
flag_set( "respawn_friendlies" );
pacifist_rubble_guys = getentarray( "pacifist_rubble_guys", "targetname" );
array_delete( pacifist_rubble_guys );
}
start_bog()
{
ambush_clear();
clear_promotion_order();
set_promotion_order( "r", "y" );
level.respawn_spawner = getent( "auto2840", "targetname" );
level.price = getent( "price", "targetname" );
level.price teleport( ( 6782.4, 336.4, 66 ) );
spawn_failed( level.price );
level.price setgoalpos( level.price.origin );
level.price.animName = "price";
level.price thread magic_bullet_shield();
level.price set_force_color( "y" );
allies = getaiarray( "allies" );
allies = array_remove( allies, level.price );
array_delete( allies );
friendlies = force_spawn_guys_from_targetname( "bog_friendly_start" );
array_thread( friendlies, ::replace_on_death );
level.player setplayerangles( ( 0, 241, 0) );
level.player setorigin( ( 6872.2, 547.4, 93 ) );
bog_is_under_attack();
}
bog_fight_until_flag()
{
// bog fighters are invulnerable until the player enters the bog.
self thread magic_bullet_shield();
flag_wait( "entered_bog" );
stop_magic_bullet_shield();
}
bog_is_under_attack()
{
initial_bog_fighters = getentarray( "initial_bog_fighters", "targetname" );
array_thread( initial_bog_fighters, ::add_spawn_function, ::bog_fight_until_flag );
}
start_alley()
{
ambush_clear();
level.respawn_spawner = getent( "alley_respawn", "targetname" );
level.price = getent( "price", "targetname" );
level.price teleport( ( 9695.2, 372.3, 76 ) );
level.price.animName = "price";
level.price thread magic_bullet_shield();
level.price set_force_color( "c" );
level.price make_hero();
allies = getaiarray( "allies" );
allies = remove_heroes_from_array( allies );
array_delete( allies );
friendlies = force_spawn_guys_from_targetname( "alley_friendly_spawners" );
friendlies = remove_color_from_array( friendlies, "g" );
array_thread( friendlies, ::replace_on_death );
level.player setplayerangles( ( 0, 255, 0) );
level.player setorigin( ( 9838.94, 960.646, 76 ) );
thread open_laundrymat();
flag_set( "alley_enemies_spawn" );
/*
activate_trigger_with_targetname( "alley_friendly_trigger" );
friendly = get_closest_colored_friendly( "y" );
thread laundryroom_saw_gunner();
flag_set( "player_enters_laundrymat" );
flag_set( "laundry_room_price_talks_to_hq" );
player_enters_laundrymat();
*/
}
start_javelin()
{
ambush_clear();
clear_promotion_order();
set_promotion_order( "r", "y" );
level.respawn_spawner = getent( "alley_respawn", "targetname" );
level.price = getent( "price", "targetname" );
level.price teleport( ( 8812.1, -557.4, 212 ) );
level.price.animName = "price";
level.price thread magic_bullet_shield();
level.price set_force_color( "y" );
getent( "playerseeker_spawn_trigger", "script_noteworthy" ) delete();
level.player setplayerangles( ( 0, 255, 0) );
level.player setorigin( ( 8636.5, -578.8, 190.9 ) );
allies = getaiarray( "allies" );
allies = array_remove( allies, level.price );
array_delete( allies );
friendlies = force_spawn_guys_from_targetname( "start_alley_spawn" );
array_thread( friendlies, ::replace_on_death );
promote_nearest_friendly( "y", "r" );
defend_the_roof_with_javelin();
}
announce_backblast()
{
level endon( "bmps_are_dead" );
flag_assert( "bmps_are_dead" );
for ( ;; )
{
while( !player_fires_javelin() )
{
wait( 0.05 );
}
wait( 1.5 );
// Backblast area clear! Fire!
level.javelin_helper thread anim_single_queue( level.javelin_helper, "backblast_clear" );
}
}
set_flag_when_bmps_are_dead()
{
ent = spawnstruct();
ent.count = 0;
level.bmps_killed_by_player = 0;
for ( i=1; i<=4; i++ )
{
thread bridge_bmp_rolls_in( "bridge_bmp" + i, ent );
}
ent waittill( "bmps_are_dead" );
flag_set( "bmps_are_dead" );
}
bmps_target_stuff_until_they_flee()
{
level endon( "overpass_baddies_flee" );
flag_assert( "overpass_baddies_flee" );
for ( ;; )
{
// tank fires at targets based on their distance to the player, getting closer and closer until they nail the player
targets = getentarray( "new_bmp_target", "targetname" );
target = random( targets );
/*
target = level.player;
if ( targets.size )
{
target = getFarthest( level.player.origin, targets );
target.targetname = undefined;
}
*/
self setTurretTargetEnt( target );
wait( randomfloatrange( 2, 3 ) );
self fireWeapon();
wait ( randomfloatrange( 3, 5 ) );
}
}
bmp_drives_for_awhile()
{
self endon( "death" );
self drives();
// self waittillmatch( "noteworthy", "stop_node" );
vehicle_flag_arrived( "bmp_in_position" );
self setspeed( 0, 925 );
if ( !flag( "overpass_baddies_flee" ) )
bmps_target_stuff_until_they_flee();
flag_wait( "overpass_baddies_flee" );
self setspeed( 15, 2 );
}
bridge_bmp_is_shot_at()
{
self endon( "death" );
for ( ;; )
{
if ( !isalive( self ) )
{
break;
}
oldHealth = self.health;
self waittill( "damage", dmg, attacker, one, two, weapType );
if ( isdefined( attacker.classname ) && attacker != level.player )
{
self.health = oldHealth;
continue;
}
if ( weapType != "MOD_PROJECTILE" )
continue;
if ( dmg < 800 )
continue;
// if ( !player_has_javelin() )
// continue;
level.bmps_killed_by_player++;
arcadeMode_kill( self.origin, "explosive", 500 );
// Target destroyed! "hit_target_1"
// Nice one! "hit_target_2"
// Good shot man! "hit_target_3"
// Ok that<61>s the last of <20>em. "hit_target_4"
// level.javelin_helper thread anim_single_queue( level.javelin_helper, "hit_target_" + level.bmps_killed_by_player );
level.javelin_helper delaythread( 1, ::anim_single_queue, level.javelin_helper, "hit_target_" + level.bmps_killed_by_player );
self godoff();
radiusdamage( self.origin, 150, self.health + 500, self.health + 500 );
}
}
bridge_bmp_rolls_in( name, ent )
{
ent.count++;
// waitSpread( 0, 9 );
bmp = spawn_vehicle_from_targetname( name );
OFFSET = ( 0, 0, 60 );
target_set( bmp, OFFSET );
target_setAttackMode( bmp, "top" );
target_setJavelinOnly( bmp, true );
bmp.health = 20000;
bmp godon();
bmp thread bmp_drives_for_awhile();
bmp bridge_bmp_is_shot_at();
flag_set( "bmp_got_killed" );
ent.count--;
if ( ent.count <= 2 )
{
flag_set( "overpass_baddies_flee" );
ent notify( "bmps_are_dead" );
}
if ( ent.count <= 0 )
{
flag_set( "all_bmps_dead" );
}
if ( isdefined( bmp ) )
{
target_remove( bmp );
}
}
/*
start_shanty()
{
alley_clear_trigger = getent( "alley_clear_trigger", "targetname" );
alley_clear_trigger notify( "trigger" );
battlechatter_off( "allies" );
getent( "apartment_door", "targetname" ) delete();
flag_set( "friendlies_take_fire" );
clear_promotion_order();
set_promotion_order( "r", "y" );
level.respawn_spawner = getent( "alley_respawn", "targetname" );
pacifist_rubble_guys = getentarray( "pacifist_rubble_guys", "targetname" );
array_delete( pacifist_rubble_guys );
level.price = getent( "price", "targetname" );
level.price teleport( ( 8812.1, -557.4, 212 ) );
level.price.animName = "price";
level.price thread magic_bullet_shield();
level.price set_force_color( "y" );
getent( "playerseeker_spawn_trigger", "script_noteworthy" ) delete();
level.player setplayerangles( ( 0, 255, 0) );
level.player setorigin( ( 8636.5, -578.8, 190.9 ) );
allies = getaiarray( "allies" );
allies = array_remove( allies, level.price );
array_delete( allies );
friendlies = force_spawn_guys_from_targetname( "start_alley_spawn" );
array_thread( friendlies, ::replace_on_death );
promote_nearest_friendly();
defend_the_roof_with_javelin();
}
*/
wait_until_alley_is_clear_of_enemies()
{
trigger = getent( "alley_enemy_volume", "targetname" );
for ( ;; )
{
axis = getaiarray( "axis" );
touching_axis = [];
for ( i=0; i < axis.size; i++ )
{
guy = axis[ i ];
if ( trigger istouching( guy ) )
touching_axis[ touching_axis.size ] = guy;
}
if ( !touching_axis.size )
break;
ent = spawnstruct();
array_thread( touching_axis, ::toucher_dies, ent );
ent_waits_for_death_or_timeout( ent, 5 );
}
}
ent_waits_for_death_or_timeout( ent, timeout )
{
ent endon( "toucher_died" );
wait( timeout );
ent waittill( "toucher_died" );
}
toucher_dies( ent )
{
self waittill( "death" );
ent notify( "toucher_died" );
}
set_all_ai_ignoreme( val )
{
ai = getaiarray();
for ( i=0; i < ai.size; i++ )
{
ai[ i ].ignoreme = val;
}
}
wait_until_mortars_are_dead()
{
ent = spawnstruct();
ent.count = 0;
mortar_triggers = getentarray( "mortar_trigger", "targetname" );
array_thread( mortar_triggers, ::mortar_trigger, ent );
ent waittill( "mortars_complete" );
objective_state( 5, "done" );
}
mortar_trigger( ent )
{
ent.count++;
self waittill( "trigger" );
self.count = 0;
spawners = getentarray( self.target, "targetname" );
array_thread( spawners, ::add_spawn_function, ::mortar_guys, self );
array_thread( spawners, ::spawn_ai );
self waittill( "mortar_guys_are_dead" );
ent.count--;
if ( !ent.count )
ent notify( "mortars_complete" );
}
mortar_guys( trigger )
{
trigger.count++;
self setgoalpos( self.origin );
self.goalradius = 64;
self waittill( "death" );
trigger.count--;
if ( !trigger.count )
trigger notify( "mortar_guys_are_dead" );
}
wait_until_its_time_to_breach_the_third_floor_room( guy )
{
while ( distance( guy.origin, level.player.origin ) > 250 )
{
wait( 0.05 );
if ( level.player.origin[ 2 ] < guy.origin[ 2 ] - 32 )
{
// player went downstairs
return false;
}
}
return true;
}
verify_that_allies_are_undeletable()
{
/#
ally_spawners = getspawnerteamarray( "allies" );
undeleteable = [];
for ( i=0; i < ally_spawners.size; i++ )
{
spawner = ally_spawners[ i ];
if ( spawner.spawnflags & 4 )
continue;
undeleteable[ undeleteable.size ] = spawner.export;
}
if ( undeleteable.size > 0 )
{
for ( i=0; i < undeleteable.size; i++ )
{
println( "Spawner with export " + undeleteable[ i ] + " was not undeletable." );
}
assertEx( 0, "Friendly spawner wasnt undeletable, see prints above in console." );
}
#/
}
assign_the_two_closest_friendlies_to_the_player()
{
for ( i=0; i < 2; i++ )
{
promote_nearest_friendly( "y", "r" );
}
}
magic_laser_light_show()
{
lasers = getentarray( "magic_laser", "targetname" );
array_thread( lasers, ::magic_laser_lights );
}
magic_laser_lights()
{
targets = getentarray( self.target, "targetname" );
lasers = targets.size - 3;
endTarg = getent( self.script_linkto, "script_linkname" );
for ( i=0; i < lasers; i++ )
{
model = spawn( "script_model", (0,0,0) );
model.origin = self.origin;
model setmodel( "tag_laser" );
model thread laser_targets_points( targets, "lasers_shift_fire", endTarg.origin, 0.75, 1.25 );
}
endTarg delete();
self delete();
}
street_laser_light_show()
{
for ( ;; )
{
flag_wait( "player_nears_first_building" );
flag_clear( "stop_street_lasers" );
lasers = getentarray( "street_laser", "targetname" );
array_thread( lasers, ::street_laser_lights );
flag_waitopen( "player_nears_first_building" );
flag_set( "stop_street_lasers" );
}
}
street_laser_lights()
{
targets = getentarray( self.target, "targetname" );
lasers = 4;
if ( lasers > targets.size )
lasers = targets.size;
for ( i=0; i < lasers; i++ )
{
model = spawn( "script_model", (0,0,0) );
model.origin = self.origin;
model setmodel( "tag_laser" );
model thread laser_targets_points( targets, "stop_street_lasers", undefined, 0.15, 0.9 );
}
}
laser_targets_points( targets, endFlag, endOrg, minspeed, maxspeed )
{
dest = spawn( "script_origin", (0,0,0) );
thread draw_laser_line( dest );
target = undefined;
orgSet = false;
lastNum = -1;
while ( !flag( endFlag ) )
{
// get an unused target
num = randomint( targets.size );
for ( ;; )
{
target = targets[ num ];
if ( num!= lastNum && !isdefined( target.used ) )
{
lastNum = num;
break;
}
num++;
if ( num >= targets.size )
num = 0;
}
assert( !isdefined( target.used ) );
if ( !orgSet )
{
dest.origin = target.origin;
orgset = true;
}
else
{
movetime = distance( dest.origin, target.origin ) * 0.015;
movetime *= randomfloatrange( minspeed, maxspeed );
dest moveto( target.origin, movetime, movetime * 0.3, movetime * 0.3 );
laser_waits( endFlag, movetime );
}
dest thread laser_jitters();
laser_waits( endFlag, randomfloatrange( 1, 5 ) );
dest notify( "stop_jitter" );
target.used = undefined;
}
dest thread laser_jitters();
waitSpread( 2 );
dest notify( "stop_jitter" );
if ( isdefined( endOrg ) )
{
endOrg = endOrg + randomVector( 25 );
endOrg = ( endOrg[ 0 ], endOrg[ 1 ], dest.origin[ 2 ] );
movetime = distance( dest.origin, endOrg ) * 0.002;
movetime *= randomfloatrange( minspeed, maxspeed );
dest moveto( endOrg, movetime, movetime * 0.3, movetime * 0.3 );
wait( moveTime );
}
else
{
// so lasers dont all turn off simultaneously
wait( randomfloat( 0.1, 0.35 ) );
}
self notify( "stop_line" );
self laserOff();
dest delete();
self delete();
}
laser_waits( endFlag, timer )
{
if ( flag( endFlag ) )
return;
level endon( endFlag );
wait( timer );
}
laser_jitters()
{
self endon( "stop_jitter" );
org = self.origin;
for ( ;; )
{
neworg = org + randomvector( 3 );
movetime = randomfloatrange( 0.05, 0.2 );
self moveto( neworg, movetime );
wait( movetime );
}
}
modulate_laser()
{
self.dolaser = false;
self endon( "stop_line" );
for ( ;; )
{
flag_wait( "nightvision_on" );
self.dolaser = true;
self laserOn();
flag_waitopen( "nightvision_on" );
self.dolaser = false;
self laserOff();
}
}
get_laser()
{
model = spawn( "script_model", (0,0,0) );
model.origin = self.origin;
model setmodel( "tag_laser" );
return model;
}
draw_laser_line( dest )
{
self endon( "stop_line" );
thread modulate_laser();
wait( 0.05 );
self.angles = vectortoangles( dest.origin - self.origin );
wait( 0.05 );
for ( ;; )
{
self rotateto( vectortoangles( dest.origin - self.origin ), 0.1 );
if ( self.dolaser )
{
// line( self.origin, dest.origin, (0,1,0) );
}
wait( 0.1 );
}
}
enemies_respond_to_attack( noteworthy, group, msg )
{
flag_clear( msg );
enemies = getentarray( noteworthy, "script_noteworthy" );
array_thread( enemies, ::attack_player_when_attacked, msg );
setIgnoremeGroup( "player", group );
flag_wait( msg );
// clear the threatbias on the entities that are attacking them, so that they can fight back
setThreatBias( "player", group, 50000 );
}
upstairs_enemies_respond_to_attack()
{
enemies_respond_to_attack( "upper_floor_enemies", "upstairs_unreachable_enemies", "unreachable_enemies_under_attack" );
if ( flag( "lasers_have_moved" ) )
{
setThreatBias( "player", "upstairs_unreachable_enemies", 0 );
setThreatBias( "friendlies_under_unreachable_enemies", "upstairs_unreachable_enemies", 0 );
}
}
window_enemies_respond_to_attack()
{
enemies_respond_to_attack( "window_enemies", "upstairs_window_enemies", "window_enemies_under_attack" );
}
second_floor_laser_light_show()
{
flag_wait( "magic_lasers_turn_on" );
// turn the lasers on
thread magic_laser_light_show();
wait_until_its_time_to_move_lasers();
// make the lasers move
flag_set( "lasers_shift_fire" );
wait( 2 );
flag_set( "lasers_have_moved" );
}
attack_player_when_attacked( msg )
{
if ( flag( msg ) )
return;
if ( isSpawner() )
{
// a spawner. Spawner should run this on guys that spawn
self add_spawn_function( ::attack_player_when_attacked, msg );
return;
}
level endon( msg );
self waittill( "death", enemy );
// was deleted
if ( !isdefined( self ) )
return;
if ( enemy == level.player )
{
flag_set( msg );
}
}
wait_until_its_time_to_move_lasers()
{
// the lasers move when the dialogue elapses, time elapses (if paulsen is dead) or the player advances prematurely
level endon( "magic_lasers_turn_off" );
// We're on the second floor! Watch your fire!
level.price anim_single_queue( level.price, "watch_your_fire" );
// roger that! Shifting fire!
radio_dialogue( "shifting_fire" );
}
set_talker()
{
// increment the next guy to talk, based on who is alive.
for ( ;; )
{
self.index++;
if ( self.index >= self.guys.size )
self.index = 0;
if ( isalive( self.guys[ self.index ] ) )
{
self.talker = self.guys[ self.index ];
return;
}
}
}
wait_until_player_goes_into_second_floor_or_melee_sequence_completes()
{
level endon( "melee_sequence_complete" );
// spawn a guy down the hall that runs out, so we notice that there's stuff at the end of the hall
wait_for_targetname_trigger( "hint_guy_trigger" );
}
wait_then_go()
{
self setgoalpos( self.origin );
self.goalheight = 64;
self.goalradius = 32;
wait( 0.5 );
node = getnode( self.target, "targetname" );
self setgoalnode( node );
}
die_shortly()
{
// spawner?
if ( !isalive( self ) )
return;
self endon( "death" );
waitspread( 0, 8 );
// if ( distance( self.origin, level.player.origin ) < 240 )
// return;
self dodamage( self.health + 50, (0,0,0) );
}
wait_while_enemies_are_alive_near_player()
{
for ( ;; )
{
enemy_near_player = false;
enemies = getaiarray( "axis" );
if ( !enemies.size )
return;
for ( i=0; i < enemies.size; i++ )
{
enemy = enemies[ i ];
if ( distance( enemy.origin, level.player.origin ) < 240 )
{
enemy_near_player = true;
break;
}
}
if ( !enemy_near_player )
return;
wait( 0.05 );
}
}
aim_at_target()
{
self endon( "death" );
targetting_origin = false;
for ( ;; )
{
if ( isdefined( self.enemy ) )
{
// clear it
if ( targetting_origin )
{
self clearenemy();
targetting_origin = false;
}
wait( 1 );
continue;
}
targetting_origin = true;
// target a random origin
self setEntityTarget( random( level.aim_targets ) );
wait randomfloatrange( 1, 4.5 );
}
}
clear_player_threatbias_vs_apartment_enemies()
{
// the player is no longer ignored by the apartment's inhabitants
setThreatBias( "player", "upstairs_unreachable_enemies", 0 );
setThreatBias( "player", "upstairs_window_enemies", 0 );
}
stick_me_to_my_spot()
{
self.maxsightdistsqrd = 0;
self setgoalpos( self.origin );
self.goalradius = 16;
}
ignore_suppression_until_ambush()
{
self endon( "death" );
self.ignoreSuppression = true;
self.pacifist = true;
flag_wait( "friendlies_take_fire" );
self.pacifist = false;
self.ignoreSuppression = false;
}
increase_goal_radius_when_friendlies_flank()
{
self endon( "death" );
self.goalheight = 60;
self.goalradius = 128;
flag_wait( "pacifist_guys_move_up" );
self.goalradius = 3050;
self setEngagementMinDist( randomintrange( 0, 125 ), 0 );
maxdist = randomintrange( 250, 350 );
self setEngagementMaxDist( maxdist, maxdist + 100 );
self setThreatbiasGroup( "pacifist_lower_level_enemies" );
self.ignoreSuppression = true;
}
debug_player_damage()
{
for ( ;; )
{
level.player waittill( "damage", a, b, c, d, e, f, g, h );
level.hitenemy = b;
i=5;
}
}
initial_friendly_setup()
{
spawn_failed( self );
// self set_force_color( "r" );
self.animname = "generic";
self.moveplaybackrate = 1;
self.goalradius = 16;
self setgoalpos( self.origin );
self.pacifist = true;
}
bridge_friendly_spawns()
{
self endon( "death" );
if ( !isdefined( self.script_forceColor ) )
{
self set_force_color( "y" );
}
set_engagement_to_closer();
self.ignoresuppression = true;
self.IgnoreRandomBulletDamage = true;
self.pacifist = true;
flag_wait( "friendlies_move_up_the_bridge" );
self.pacifist = false;
}
small_pathenemy()
{
self.pathenemyfightdist = 50;
self.pathenemylookahead = 50;
}
magic_rpgs_fire()
{
targets = getentarray( self.target, "targetname" );
for ( i=0; i < targets.size; i++ )
{
magicbullet( "rpg_straight", self.origin, targets[ i ].origin );
wait( randomfloatrange( 1.5, 5 ) );
}
}
magic_rpg_fires( name )
{
rpg = getent( name, "targetname" );
rpg magic_rpgs_fire();
}
delete_me()
{
self delete();
}
set_engagement_to_closer()
{
self setEngagementMinDist( 0, 0 );
self setEngagementMaxDist( 1000, 3000 );
}
set_min_engagement_distance( min, min_falloff )
{
self setEngagementMinDist( min, min_falloff );
}
set_max_engagement_distance( max, max_falloff )
{
self setEngagementmaxDist( max, max_falloff );
}
incoming_rpg()
{
magic_rpg_fires( "magic_rpg1" );
wait( 2.5 );
magic_rpg_fires( "magic_rpg2" );
/*
wait( 0.4 );
// add some extra kick to the rocket
explosion_point = getent( "explosion_point", "targetname" );
radiusDamage( explosion_point.origin, explosion_point.radius, 9000, 9000 );
explosion_point delete();
*/
}
ambushed_guys_die()
{
wait( 1.5 );
ai = getentarray( "ambushed_guy", "targetname" );
array_thread( ai, ::killme );
}
killme()
{
self dodamage( 5000, ( 0,0,0 ) );
}
waitspread_death( timer )
{
if ( !isalive( self ) )
return;
self endon( "death" );
waitspread( timer );
killme();
}
slowdown()
{
self endon( "death" );
self.walkdist = 5000;
wait( 0.4 );
self setgoalpos( self.origin );
}
set_ignore_suppression( val )
{
self.ignoreSuppression = val;
}
wait_until_price_triggers_or_player_reaches_bridge_end()
{
level endon( "player_reaches_end_of_bridge" );
if ( flag( "player_reaches_end_of_bridge" ) )
return;
for ( ;; )
{
self waittill( "trigger", other );
if ( !isalive( other ) )
continue;
if ( other != level.price )
continue;
break;
}
}
promoted_cyan_guy_leads_player_to_apartment( null )
{
if ( self.script_forceColor != "c" )
return;
thread cyan_guys_lead_player_to_apartment();
}
wait_until_player_gets_close_or_enters_apartment()
{
level endon( "friendlies_move_into_apartment" );
while ( distance( self.origin, level.player.origin ) > 128 )
{
if ( self cansee( level.player ) )
{
// if the player is looking at me I can lead the way!
player_angles = level.player GetPlayerAngles();
player_forward = anglesToForward( player_angles );
normal = vectorNormalize( self.origin - level.player.origin );
dot = vectorDot( player_forward, normal );
if ( dot > 0.80 )
return;
}
wait( 1 );
}
}
cyan_guys_lead_player_to_apartment()
{
self endon( "death" );
self endon( "damage_notdone" );
wait_until_player_gets_close_or_enters_apartment();
// becomes a dark blue guy and gets magic bullet shield
// leads player to the apartment
self set_force_color( "b" );
if ( self == level.price )
{
self thread price_signals_player_into_apartment();
}
if ( !is_hero() )
{
self thread magic_bullet_shield();
}
flag_wait( "pit_guys_cleared" );
self.ignoreall = true;
flag_wait( "friendlies_storm_second_floor" );
self.ignoreall = false;
}
price_signals_player_into_apartment()
{
if ( flag( "friendlies_storm_second_floor" ) )
return;
level endon( "friendlies_storm_second_floor" );
node = getnode( "price_underground_node", "targetname" );
for ( ;; )
{
node anim_reach_solo( level.price, "wait_approach" );
if ( distance( node.origin, level.price.origin ) < 16 )
break;
}
node anim_single_solo( level.price, "wait_approach" );
thread price_waits_at_node_and_waves( node, "vas_stops_leading" );
thread price_recovers_from_waving( node );
}
price_recovers_from_waving( node )
{
flag_wait( "friendlies_storm_second_floor" );
level notify( "vas_stops_leading" );
node notify( "stop_idle" );
level.price stopanimscripted();
level.price notify( "single anim", "end" );
level.price notify( "looping anim", "end" );
//update_underground_obj_trigger
}
wait_for_player_to_disrupt_second_floor_or_leave()
{
level endon( "player_leaves_second_floor" );
flag_wait( "player_disrupts_second_floor" );
}
manual_mg_fire()
{
self endon( "stop_firing" );
self.turret_fires = true;
for ( ;; )
{
timer = randomfloatrange( 0.2, 0.7 ) * 20;
if ( self.turret_fires )
{
for ( i = 0; i < timer; i++ )
{
self shootturret();
wait( 0.05 );
}
}
wait( randomfloat( 0.5, 2 ) );
}
}
wait_for_death( guy )
{
if ( !isalive( guy ) )
return;
guy waittill( "death" );
}
scr_setmode( mode )
{
self setmode( mode );
}
flank_guy()
{
// guy that spawns up ahead and down the stairs on the first flank
level.flank_guy = getent( "flank_guy", "targetname" );
spawn_failed( level.flank_guy );
level.flank_guy.goalradius = 8;
level.flank_guy.pacifist = true;
level.flank_guy allowedstances( "crouch" );
level.flank_guy thread magic_bullet_shield();
level.flank_guy.ignoreme = true;
level.flank_guy make_hero();
level.flank_guy.ignoreSuppression = true;
}
rooftop_guys_attack()
{
self endon( "death" );
waitSpread(5);
for ( i=0; i < self.count; i++ )
{
spawn = self spawn_ai();
if ( spawn_failed( spawn ) )
return;
spawn waittill( "death" );
}
}
hint_guy_gets_the_players_attention()
{
self.ignoreme = true;
self.ignoresuppression = true;
self endon( "death" );
wait( 2.5 ); // give player a chance to shoot the guys in the hallway
self maps\_spawner::go_to_node();
wait( 3 );
self.ignoreme = false;
self.goalradius = 2048; // now he can go and hide and draw the player in
}
upstairs_unreachable_enemies()
{
self add_spawn_function( ::ignore_suppression_until_ambush );
self add_spawn_function( ::small_pathenemy );
self add_spawn_function( ::set_threatbias_group, "upstairs_unreachable_enemies" );
}
upstairs_window_enemies()
{
self add_spawn_function( ::ignore_suppression_until_ambush );
// self add_spawn_function( ::small_pathenemy );
self add_spawn_function( ::set_threatbias_group, "upstairs_window_enemies" );
}
teleport_purple_guys_closer()
{
purple_guys = get_force_color_guys( "allies", "p" );
points = getentarray( "purple_teleport_org", "targetname" );
for ( i=0; i < purple_guys.size; i++ )
{
guy = purple_guys[ i ];
// saved friendly is already hanging with us
if ( isalive( level.saved_friendly ) && guy == level.saved_friendly )
continue;
// dont teleport down
if ( guy.origin[ 2 ] + 37 > points[ i ].origin[ 2 ] )
continue;
guy teleport( points[ i ].origin );
}
}
remove_corner_ai_blocker()
{
corner_ai_blocker = getent( "corner_ai_blocker", "targetname" );
if ( isdefined( corner_ai_blocker ) )
{
corner_ai_blocker connectPaths();
corner_ai_blocker delete();
}
}
wait_until_price_nears_balcony()
{
trigger = getent( "price_gap_trigger", "targetname" );
for ( ;; )
{
trigger waittill( "trigger", other );
if ( other == level.price )
return;
other thread ignore_triggers();
}
}
wait_until_player_nears_balcony()
{
level.balcony_objective_org = ( 10216.3, 174.7, 239.5 );
org = ( level.balcony_objective_org[ 0 ], level.balcony_objective_org[ 1 ], 0 );
while ( distance( org, ( level.player.origin[ 0 ], level.player.origin[ 1 ], 0 ) ) > 200 )
{
wait( 0.25 );
}
}
price_congrates()
{
self waittill( "death", other );
if ( isalive( other ) && other == level.player )
{
wait( 2.5 );
// Good job!
level.price thread anim_single_queue( level.price, "good_job" );
}
}
player_is_on_mg()
{
turret = getent( "apartment_window_mg_1", "targetname" );
owner = turret getTurretOwner();
if ( !isalive( owner ) )
return false;
return owner == level.player;
}
debug_pain()
{
self endon( "death" );
for ( ;; )
{
self waittill( "pain", attacker, one, two, three, four, five );
tookpain = undefined;
}
}
shoot_mg_targets()
{
thread do_in_order( ::flag_wait, "player_enters_apartment_rubble_area", ::send_notify, "stop_firing" );
thread stop_firing_when_shot();
targets = getentarray( self.target, "targetname" );
for ( ;; )
{
target = random( targets );
self settargetentity( target );
wait( randomfloatrange( 1, 5 ) );
}
}
explosive_damage( type )
{
return issubstr( type, "GRENADE" );
}
stop_firing_when_shot()
{
level endon( "player_enters_apartment_rubble_area" );
trigger = getent( self.script_linkto, "script_linkname" );
shots_until_stop = randomintrange( 2, 3 );
for ( ;; )
{
trigger waittill( "damage", damage, other, direction, origin, damage_type );
if ( other != level.player )
continue;
if ( explosive_damage( damage_type ) )
{
self.turret_fires = false;
return;
}
shots_until_stop--;
if ( shots_until_stop > 0 )
continue;
shots_until_stop = randomintrange( 3, 4 );
self.turret_fires = false;
wait( randomfloatrange( 7, 10 ) );
self.turret_fires = true;
}
}
price_waits_at_node_and_waves( node, ender )
{
level endon( ender );
flag_assert( ender );
odd = true;
for ( ;; )
{
node thread anim_loop_solo( level.price, "wait_idle", undefined, "stop_idle" );
wait( randomfloat( 0.1, 2.5 ) );
node notify( "stop_idle" );
if ( odd )
{
node anim_single_solo( level.price, "wave1" );
}
else
{
if ( flag( "friendlies_move_up_the_bridge" ) )
Objective_Ring( 2 );
node anim_single_solo( level.price, "wave2" );
}
odd = !odd;
}
}
#using_animtree ("vehicles");
cobra_crash()
{
for ( ;; )
{
self waittill( "trigger", other );
// if ( other.vehicleType != "cobra" )
// continue;
if ( other.targetname != "heli_crash" )
continue;
/*
dummy = other maps\_vehicle::vehicle_to_dummy();
dummy useAnimTree( #animtree );
dummy animscripted( "single_anim", dummy.origin, dummy.angles, %cobra_crash );
//dummy setanimknob( %cobra_crash, 1, 0.25, 1 );
*/
ent = spawn( "script_model", (0,0,0) );
ent.origin = other.origin;
ent.angles = other.angles;
ent setmodel( other.model );
ent useAnimTree( #animtree );
ent animScripted( "blah", ent.origin, ent.angles, %cobra_crash );
other delete();
playfxontag( getfx( "heli_aerial_explosion_large" ), ent, "tag_body" );
ent playsound( "helicopter_hit" );
delaythread( 0.1, ::_Earthquake, 0.4, 1.2, ent.origin, 6000 );
ent playloopsound( "helicopter_dying_loop" );
ent thread tailfx();
// ent waittillmatch( "blah", "end" );
wait( 2 );
playfxontag( getfx( "heli_aerial_explosion" ), ent, "tail_rotor_jnt" );
ent playsound( "helicopter_hit" );
wait( 1 );
playfxontag( getfx( "heli_aerial_explosion" ), ent, "tag_deathfx" );
ent playsound( "helicopter_hit" );
wait( 3 );
exploder( 2 );
ent notify( "stop_tail_fx" );
ent delete();
// ent setanimknob( %cobra_crash_additive, 1, 0.25, 1 );
wait( 5 );
}
}
tailfx()
{
self endon( "stop_tail_fx" );
tags = [];
// tags[ tags.size ] = "tag_gunner";
tags[ tags.size ] = "tail_rotor_jnt";
//tags[ tags.size ] = "tag_engine_rear_left";
// tags[ tags.size ] = "tag_engine_rear_right";
tagsKeys = getarraykeys( tags );
fx = undefined;
for ( ;; )
{
for ( i=0; i < tagsKeys.size; i++ )
{
org = self GetTagOrigin( tags[ tagsKeys[ i ] ] );
playfx( getfx( "smoke_trail_heli" ), org );
// fx = spawnFx( getfx( "smoke_trail_heli" ), org );
// delayThread( ::deleteEnt, 30, fx );
// triggerFx( fx, 0 );
// playfxontag( getfx( "smoke_trail_heli" ), self, tags[ tagsKeys[ i ] ] );
// playfxontag( getfx( "fire_trail_heli" ), self, tags[ tagsKeys[ i ] ] );
}
wait( 0.05 );
}
}
helis_ambient()
{
thread helicopter_flies_by_overhead( "intro_heli", 5, 95, 95 );
thread helicopter_flies_by_overhead( "intro_helib", 5.85, 95, 95 );
thread helicopter_flies_by_overhead( "intro_heli2", 9, 95, 95 );
thread helicopter_flies_by_overhead( "intro_heli2b", 9.95, 95, 95 );
thread helicopter_flies_by_overhead( "intro_heli3", 14, 135, 95 );
thread helicopter_flies_by_overhead( "intro_heli3b", 14.95, 135, 95 );
// thread helicopter_flies_by_overhead( "intro_heli4", 22, 135, 95 );
// thread helicopter_flies_by_overhead( "intro_heli4b", 22.95, 165, 95 );
flag_wait( "armada_passes_by" );
helisets = [];
helisets = add_heli_set( "intro_heli", 95, 95 );
helisets = add_heli_set( "intro_heli2", 95, 95 );
helisets = add_heli_set( "intro_heli3", 135, 95 );
helisets = add_heli_set( "intro_heli4", 165, 95 );
for ( ;; )
{
helisets = array_randomize( helisets );
for ( i=0; i < helisets.size; i++ )
{
set = helisets[ i ];
thread helicopter_flies_by_overhead( set[ "heli1" ], 0, set[ "maxspeed" ], set[ "accell" ] );
thread helicopter_flies_by_overhead( set[ "heli2" ], 0.8, set[ "maxspeed" ], set[ "accell" ] );
wait( randomfloatrange( 8, 12 ) );
}
}
}
add_heli_set( name, maxspeed, accell )
{
array = [];
array[ "heli1" ] = name;
array[ "heli2" ] = name + "b";
array[ "maxspeed" ] = maxspeed;
array[ "accell" ] = accell;
return array;
}
die_soon( when )
{
if ( !isalive( self ) )
return;
self endon( "death" );
wait( when );
self dodamage( self.health + 50, (0,0,0) );
}
player_has_javelin()
{
weaponList = level.player GetWeaponsListPrimaries();
for ( i=0; i < weaponList.size; i++ )
{
if ( issubstr( weaponList[ i ], "avelin" ) )
{
return true;
}
}
return false;
}
player_using_javelin()
{
return issubstr( level.player getcurrentweapon(), "avelin" );
}
player_fires_javelin()
{
return level.player isFiring() && issubstr( level.player getcurrentweapon(), "avelin" );
}
overpass_baddies_attack()
{
level endon( "overpass_baddies_flee" );
assertEx( !flag( "overpass_baddies_flee" ), "flag was set too soon" );
wait( 5 );
spawners = getentarray( "bridge_spawner", "targetname" );
for ( ;; )
{
if ( getaiarray( "axis" ).size >= 18 )
{
wait( 180 );
continue;
}
spawner = random( spawners );
spawner.count = 3;
// pyramid spawns 3 guys
spawner thread maps\_spawner::flood_spawner_think();
wait( 5 );
}
}
die_asap()
{
self endon( "death" );
while ( self canSee( level.player ) )
{
wait( 0.2 );
}
self delete();
}
shanty_run()
{
if ( isdefined( self.target ) )
{
trigger = getent( self.target, "targetname" );
trigger.trigger_num = self.trigger_num + 1;
trigger thread shanty_run();
}
for ( ;; )
{
self waittill( "trigger", other );
if ( !isalive( other ) )
continue;
other.trigger_num = self.trigger_num;
if ( other == level.player )
{
level notify( "new_player_trigger_num" );
}
else
{
other notify( "new_trigger_num" );
}
}
}
waittill_new_trigger_num()
{
self endon( "new_trigger_num" );
level waittill( "new_player_trigger_num" );
}
shanty_allies_cqb_through()
{
self endon( "death" );
flag_wait( "start_shanty_run" );
// pick one of two paths through
dests = getentarray( "shanty_destination", "targetname" );
dest = random( dests );
self.goalradius = 128;
self.interval = 0;
self disable_ai_color();
self maps\_spawner::go_to_origin( dest );
self.interval = 96;
if ( self == level.price )
{
backhalf_price = getent( "price_spawner", "targetname" );
level.price set_force_color( backhalf_price.script_forceColor );
return;
}
if ( self == level.mark )
{
backhalf_mark = getent( "mark_spawner", "targetname" );
level.mark set_force_color( backhalf_mark.script_forceColor );
return;
}
if ( level.ending_bog_redshirts >= 2 )
{
// extra guys run in and die in the bog
org = getent( "ally_charge_bog_org", "targetname" ).origin;
self setgoalpos( org );
if ( isdefined( self.magic_bullet_shield ) )
self stop_magic_bullet_shield();
self.health = 1;
return;
}
// steve wants 2 redshirts, one red, one blue
level.ending_bog_redshirts++;
if ( level.ending_bog_redshirts == 1 )
{
self set_force_color( "r" );
}
else
{
self set_force_color( "b" );
}
// self thread replace_on_death();
}
shanty_ai_think()
{
self disable_ai_color();
self.trigger_num = 0;
self endon( "death" );
self.interval = 0;
self endon( "reached_shanty_end" );
if ( self != level.price )
{
self.animname = "generic";
}
// thread run_to_end_of_shanty();
// actionBind = getActionBind( "sprint2" );
//thread showPlaybackRate();
for ( ;; )
{
waittill_new_trigger_num();
if ( level.player.trigger_num - self.trigger_num >= 2 )
{
self.moveplaybackrate = 1.21;
// self set_run_anim( "sprint" );
}
else
if ( level.player.trigger_num - self.trigger_num == 1 )
{
self.moveplaybackrate = 1.1;
// self set_run_anim( "sprint" );
}
else
if ( level.player.trigger_num - self.trigger_num == 0 )
{
self.moveplaybackrate = 1.0;
// self set_run_anim( "sprint" );
}
else
if ( level.player.trigger_num - self.trigger_num == -1 )
{
self.moveplaybackrate = 1.0;
}
else
if ( level.player.trigger_num - self.trigger_num == -2 )
{
self.moveplaybackrate = 1.0;
}
else
if ( level.player.trigger_num - self.trigger_num <= -3 )
{
time_since_last_stopper = ( gettime() - level.shanty_timer ) * 0.001;
next_stop_time = time_since_last_stopper + randomfloatrange( 2, 3 );
level.shanty_timer = gettime();
if ( next_stop_time > 0 )
{
wait( next_stop_time );
}
if ( level.player.trigger_num - self.trigger_num <= -3 )
{
// is it still true?
self setgoalpos( self.origin );
}
// self.moveplaybackrate = 0.7;
}
}
}
shanty_ai_sprint()
{
self disable_ai_color();
self.trigger_num = 0;
if ( self != level.price )
{
self.animname = "generic";
}
self set_run_anim( "sprint" );
// thread run_to_end_of_shanty();
}
showPlaybackRate()
{
self endon( "death" );
for ( ;; )
{
print3d( self.origin + (0,0,64), self.moveplaybackrate, (1,1,1), 1, 1 );
wait( 0.05 );
}
}
magic_rpgs_fire_randomly()
{
waitSpread( 1, 6 );
magic_rpgs_fire();
}
magic_rpg_trigger()
{
level endon( "stop_shanty_rockets" );
self waittill( "trigger" );
targets = getentarray( self.target, "targetname" );
for ( i=0; i < targets.size; i++ )
{
targets[ i ] magic_rpgs_fire();
wait( randomfloatrange( 1.5, 5 ) );
}
}
bog_ambient_fighting()
{
self endon( "death" );
thread magic_bullet_shield();
self.goalradius = 1450;
flag_wait( "kill_bog_ambient_fighting" );
self stop_magic_bullet_shield();
self delete();
}
take_cover_against_overpass()
{
if ( isdefined( self.fence_guy ) )
return;
self endon( "death" );
self disable_ai_color();
self setgoalpos( self.origin );
waitspread( 2 );
self.fixednode = false;
self.goalradius = 2048;
}
alley_balcony_guy()
{
// price "throws a grenade" at this guy if he doesnt die soon enough
self endon( "death" );
flag_wait( "price_in_alley_position" );
magicbullet( "rpg_straight", self.origin + (0,0,10), self.origin );
}
lose_goal_volume()
{
for ( ;; )
{
self waittill( "trigger", other );
if ( !isalive( other ) )
continue;
other thread ignore_triggers();
other.dont_use_goal_volume = true;
}
}
wait_until_javelin_guy_died_or_must_die()
{
if ( !isalive( self ) )
return;
self waittill( "death" );
}
die_after_spawn( timer )
{
self endon( "death" );
wait( timer );
self dodamage( self.health + 150, (0,0,0) );
}
wait_until_price_reaches_his_trigger()
{
trigger = getent( "price_alley_trig", "targetname" );
for ( ;; )
{
trigger waittill( "trigger", other );
if ( !isalive( other ) )
continue;
if ( other != level.price )
continue;
return;
}
}
wait_for_friendlies_to_reach_alley_goal()
{
maxtime = gettime() + 15000;
for ( ;; )
{
if ( check_allies_in_position() )
return;
if ( gettime() > maxtime )
return;
wait( 0.1 );
}
}
check_allies_in_position()
{
yellow = get_force_color_guys( "allies", "y" );
orange = get_force_color_guys( "allies", "o" );
allies = array_combine( yellow, orange );
// check most of them
count = allies.size - 2;
for ( i = 0; i < allies.size; i++ )
{
guy = allies[ i ];
if ( !isdefined( guy.goalpos ) )
continue;
if ( distance( guy.origin, guy.goalpos ) > 60 )
continue;
count--;
if ( count <= 0 )
return true;
}
return false;
}
shanty_fence_cut_setup()
{
shanty_fence = spawn_anim_model( "fence" );
shanty_fence_org = getent( "shanty_fence_org", "targetname" );
shanty_fence_org thread anim_first_frame_solo( shanty_fence, "fence_cut" );
level.shanty_fence = shanty_fence;
}
shanty_fence_cut()
{
shanty_fence = level.shanty_fence;
shanty_fence_org = getent( "shanty_fence_org", "targetname" );
shanty_fence_clip = getent( "shanty_fence_clip", "targetname" );
shanty_fence_clip connectPaths();
shanty_fence.animname = "fence";
shanty_fence assign_animtree();
assertex( isalive( level.fence_guys[ 0 ] ), "Fence guy 1 was not alive" );
assertex( isalive( level.fence_guys[ 1 ] ), "Fence guy 1 was not alive" );
guy1 = level.fence_guys[ 0 ];
guy2 = level.fence_guys[ 1 ];
guy1.animname = "fence_guy1";
guy2.animname = "fence_guy2";
fence_cutters = [];
fence_cutters[ fence_cutters.size ] = guy1;
fence_cutters[ fence_cutters.size ] = guy2;
shanty_fence_org anim_reach_and_plant( fence_cutters, "fence_cut" );
array_thread( fence_cutters, ::set_allowpain, false );
shanty_fence_org thread anim_single_solo( shanty_fence, "fence_cut" );
shanty_fence_clip delaythread( 12.45, ::self_delete );
delaythread( 12.45, ::activate_trigger_with_targetname, "shanty_after_fence" );
guy1 pushPlayer( true );
shanty_fence_org thread anim_custom_animmode( fence_cutters, "gravity", "fence_cut" );
array_thread( fence_cutters, ::set_force_color, "r" );
shanty_fence_org waittill( "fence_cut" );
guy1 pushPlayer( false );
array_thread( fence_cutters, ::stop_magic_bullet_shield );
array_thread( fence_cutters, ::set_allowpain, true );
}
set_allowpain( val )
{
self.allowPain = val;
}
wait_until_deathflag_enemies_remaining( deathflag, num )
{
ai = getaiarray( "axis" );
for ( ;; )
{
count = 0;
spawners = level.deathflags[ deathflag ][ "spawners" ];
keys = getarraykeys( spawners );
for ( i = 0; i < keys.size; i++ )
{
if ( isdefined( spawners[ keys[ i ] ] ) )
count += spawners[ keys[ i ] ].count;
}
count += level.deathflags[ deathflag ][ "ai" ].size;
level.temp_deathflagcount = count;
if ( count <= num )
break;
wait( 1 );
}
}
friendlies_charge_alley_early()
{
wait_until_deathflag_enemies_remaining( "alley_cleared", 6 );
flag_set( "friendlies_charge_alley" );
}
second_floor_door_breach_guys( debugmode )
{
door = getent( "apartment_second_floor_door_breach", "targetname" );
door_model = spawn_anim_model( "door" );
door hide();
door linkto( door_model, "door_jnt", (0,0,0), (0,0,0) );
node = getnode( "second_floor_door_breach_node", "targetname" );
level.door_mod = ( -20, -5.35, 0 );
door_ent = spawn( "script_origin", node.origin + level.door_mod );
level.door_ent = door_ent;
// door_model thread maps\_debug::drawtagforever( "door_jnt" );
// door_ent = spawn( "script_origin", node.origin + ( -20, -13, 0 ));
door_ent.angles = node.angles + (0,270,0);
door_ent thread anim_first_frame_solo( door_model, "door_breach" );
ent = spawn( "script_origin", node.origin + ( -20, -13, 0 ));
ent.angles = node.angles;
flag_wait( "second_floor_door_breach_initiated" );
// keeps the corner free from traffic
remove_corner_ai_blocker();
if ( debugmode )
{
right_guy = get_guy_with_script_noteworthy_from_spawner( "second_floor_right_door_breach_guy" );
left_guy = get_guy_with_script_noteworthy_from_spawner( "second_floor_left_door_breach_guy" );
}
else
{
// one blue guy and one purple guy become the door breachers
// right_guy = get_closest_colored_friendly( "b" );
left_guy = get_closest_colored_friendly( "p" );
left_guy make_hero();
left_guy clear_force_color();
right_guy = get_closest_colored_friendly_with_classname( "b", "shotgun" );
if ( !isalive( right_guy ) )
{
right_guy = get_closest_colored_friendly_with_classname( "p", "shotgun" );
}
if ( !isalive( right_guy ) )
{
trigger = getent( "player_sees_breach_spawner", "targetname" );
while ( level.player istouching( trigger ) )
{
wait( 0.1 );
}
right_guy = get_guy_with_script_noteworthy_from_spawner( "second_floor_left_door_breach_guy" );
}
assertEx( isalive( right_guy ), "right_guy didnt spawn" );
right_guy make_hero();
right_guy clear_force_color();
}
left_guy.goalHeight = 64;
right_guy.goalHeight = 64;
left_guy.animName = "second_floor_left_guy";
right_guy.animName = "second_floor_right_guy";
if ( !isdefined( left_guy.magic_bullet_shield ) )
left_guy thread magic_bullet_shield();
if ( !isdefined( right_guy.magic_bullet_shield ) )
right_guy thread magic_bullet_shield();
guyArray = [];
guyArray[ guyArray.size ] = left_guy;
guyArray[ guyArray.size ] = right_guy;
// if ( !isdefined( level.tweakOffset ) )
// level.tweakOffset = ( 0,0,0 );
ent anim_reach_and_idle( guyArray, "door_breach_setup", "door_breach_setup_idle", "stop_door_breach_idle" );
// left_guy.ignoreme = true;
// right_guy.ignoreme = true;
ent notify( "stop_door_breach_idle" );
ent anim_single( guyArray, "door_breach_setup" );
ent thread anim_loop( guyArray, "door_breach_idle", undefined, "stop_loop" );
second_floor_waittill_breach( guyArray );
if ( flag( "player_enters_laundrymat" ) )
{
array_thread( guyArray, ::stop_magic_bullet_shield );
array_thread( guyArray, ::_delete );
return;
}
ent notify( "stop_loop" );
ent thread anim_single( guyArray, "door_breach" );
right_guy waittillmatch( "single anim", "kick" );
door_ent thread anim_single_solo( door_model, "door_breach" );
door connectPaths();
door playsound ("wood_door_kick");
left_guy.goalradius = 32;
right_guy.goalradius = 32;
left_guy.threatbias = 5500;
left_guy.baseAccuracy = 1000;
right_guy.baseAccuracy = 1000;
badGuys = spawn_guys_from_targetname( node.target );
// door door_opens();
for ( i=0; i < badGuys.size; i++ )
{
// badGuys[ i ] setFlashBanged( true, 1 );
badguy = badGuys[ i ];
badguy.baseAccuracy = 0;
badguy.goalradius = 8;
badguy.health = 1;
badguy.pathenemyfightdist = 0;
badguy.pathenemylookahead = 0;
badguy allowedstances( "stand" );
if ( isdefined( badguy.target ) )
badguy thread wait_then_go_to_target();
}
wait( 2 );
left_guy setgoalpos( left_guy.origin );
ent waittill( "door_breach" );
for ( i = 0; i < badGuys.size; i++ )
{
if ( isalive( badGuys[ i ] ) )
badGuys[ i ] waittill( "death" );
}
right_guy.baseAccuracy = 1;
left_guy_node = getnode( "left_guy_breach_node", "targetname" );
right_guy_node = getnode( "right_guy_breach_node", "targetname" );
left_guy.baseAccuracy = 1;
left_guy setgoalpos( left_guy.origin );
left_guy.goalradius = 64;
left_guy setgoalnode( left_guy_node );
right_guy anim_single_solo( right_guy, "clear" );
node = getnode( "second_floor_clear_node", "targetname" );
left_guy setgoalnode( node );
left_guy.goalradius = 32;
left_guy waittill( "goal" );
left_guy.threatbias = 0;
left_guy anim_single_solo( left_guy, "clear" );
if ( debugmode )
{
for ( i=0; i < guyArray.size; i++ )
{
guy = guyArray[ i ];
guy stop_magic_bullet_shield();
guy delete();
}
return;
}
// Three coming out!
left_guy anim_single_solo( left_guy, "three_coming_out" );
wait( 1 );
left_guy scrub();
left_guy setgoalnode( left_guy_node );
left_guy.goalradius = 32;
// Roger that!
level.price thread anim_single_queue( level.price, "roger_that" );
// clear!
right_guy anim_single_solo( right_guy, "clear" );
right_guy scrub();
right_guy setgoalnode( right_guy_node );
right_guy.goalradius = 32;
flag_wait( "alley_enemies_spawn" );
right_guy thread door_breach_guy_leaves( "right_leave_node" );
left_guy thread door_breach_guy_leaves( "left_leave_node" );
}
door_breach_guy_leaves( msg )
{
self endon( "death" );
node = getnode( msg, "targetname" );
self setgoalnode( node );
self add_wait( ::waittill_player_lookat );
add_wait( ::flag_wait, "player_enters_laundrymat" );
do_wait_any();
wait( randomfloat( 2, 3 ) );
self set_force_color( "g" );
self.ignoreall = true;
}
second_floor_waittill_breach( guys )
{
add_wait( ::wait_for_targetname_trigger, "second_floor_door_breach_trigger" );
add_wait( ::flag_wait, "player_enters_laundrymat" );
for ( i = 0; i < guys.size; i++ )
{
guys[ i ] add_wait( ::waittill_player_lookat_for_time, 0.3 );
}
do_wait_any();
}
waittill_player_not_looking( org )
{
for ( ;; )
{
if ( !player_looking_at( org, 0.7 ) )
break;
wait( 0.1 );
}
}
update_obj_on_dropped_jav( org )
{
level endon( "overpass_baddies_flee" );
flag_assert( "overpass_baddies_flee" );
for ( ;; )
{
weapons = getentarray( "weapon_javelin", "classname" );
assertex( weapons.size < 2, "Somehow level had 2 javelins" );
if ( !weapons.size )
{
wait( 0.05 );
continue;
}
jav = weapons[ 0 ];
jav thread add_jav_glow( "overpass_baddies_flee" );
objective_position( 4, jav.origin );
for ( ;; )
{
weapons = getentarray( "weapon_javelin", "classname" );
if ( !weapons.size )
break;
wait( 0.05 );
}
objective_position( 4, org );
}
}
wait_for_fence_guys_to_be_drafted()
{
if ( !isdefined( level.fence_guys ) )
level.fence_guys = [];
if ( level.fence_guys.size >= 2 )
return;
level notify( "drafting_fence_guys" );
level endon( "drafting_fence_guys" );
for ( ;; )
{
// kill off excess friendlies
allies = getaiarray( "allies" );
allies = remove_heroes_from_array( allies );
if ( !allies.size )
{
wait( 0.5 );
continue;
}
guy = allies[ 0 ];
guy thread magic_bullet_shield();
guy make_hero();
guy set_force_color( "r" );
guy.fence_guy = true;
level.fence_guys[ level.fence_guys.size ] = guy;
if ( level.fence_guys.size >= 2 )
break;
}
}
disable_nvg()
{
flag_wait( "player_enters_laundrymat" );
wait( 4.0 );
display_hint( "disable_nvg" );
}
update_apartment_objective_position()
{
// baby baby baby STEP
self waittill( "trigger" );
targ = getent( self.target, "targetname" );
objective_position( 2, targ.origin );
}