IW4-Dump-Files/maps/so_rooftop_contingency.gsc

1120 lines
27 KiB
Plaintext

#include maps\_utility;
#include common_scripts\utility;
#include maps\_anim;
#include maps\_specialops;
#include maps\_hud_util;
#include maps\_vehicle;
#include maps\so_rooftop_contingency_code;
// Fend off three waves of enemy reinforcements.
CONST_regular_obj = &"SO_ROOFTOP_CONTINGENCY_OBJ_REGULAR";
// Fend off four waves of enemy reinforcements.
CONST_hardened_obj = &"SO_ROOFTOP_CONTINGENCY_OBJ_HARDENED";
// Fend off five waves of enemy reinforcements.
CONST_veteran_obj = &"SO_ROOFTOP_CONTINGENCY_OBJ_VETERAN";
main()
{
level.so_compass_zoom = "far";
// Optimization
SetSavedDvar( "sm_sunShadowScale", 0.5 );
SetSavedDvar( "r_lightGridEnableTweaks", 1 );
SetSavedDvar( "r_lightGridIntensity", 1.5 );
SetSavedDvar( "r_lightGridContrast", 0 );
// LevelVars from contigency.gsc
//level.ai_dont_glow_in_thermal = true;
level.min_btr_fighting_range = 400;
level.explosion_dist_sense = 1500;
level.default_goalradius = 7200;
level.goodFriendlyDistanceFromPlayerSquared = 250 * 250;
PreCacheItem( "remote_missile_snow" );
level.remote_missile_snow = true;
level.cosine[ "60" ] = Cos( 60 );
level.cosine[ "70" ] = Cos( 70 );
// UAV Settings
// min time for UAV reload
level.min_time_between_uav_launches = 20 * 1000;
level.visionThermalDefault = "contingency_thermal_inverted";
level.VISION_UAV = "contingency_thermal_inverted";
// Thermal FX Overrides
SetThermalBodyMaterial( "thermalbody_snowlevel" );
level.friendly_thermal_Reflector_Effect = LoadFX( "misc/thermal_tapereflect" );
PreCacheItem( "remote_missile_not_player" );
PreCacheModel( "com_computer_keyboard_obj" );
PrecacheNightvisionCodeAssets();
flag_init( "challenge_success" );
flag_init( "wave_wiped_out" );
flag_init( "waves_start" );
flag_init( "wave_1_started" );
flag_init( "wave_2_started" );
flag_init( "wave_3_started" );
flag_init( "wave_4_started" );
flag_init( "wave_5_started" );
flag_init( "uav_in_use" );
flag_init( "wave_spawned" );
flag_init( "start_countdown" );
// Press^3 [{+actionslot 4}] ^7to control the Predator Drone.
add_hint_string( "use_uav_4", &"HELLFIRE_USE_DRONE", maps\_remotemissile::should_break_use_drone );
add_hint_string( "use_uav_2", &"HELLFIRE_USE_DRONE_2", maps\_remotemissile::should_break_use_drone );
// delete certain non special ops entities
so_delete_all_by_type( ::type_vehicle_special, ::type_spawners, ::type_spawn_trigger );
default_start( ::start_so_rooftop );
add_start( "start_so_rooftop", ::start_so_rooftop );
precache_strings();
// init stuff
maps\_bm21_troops::main( "vehicle_bm21_mobile_cover_snow" );
maps\_uaz::main( "vehicle_uaz_winter_destructible", "uaz_physics" );
maps\_uaz::main( "vehicle_uaz_winter_destructible" );
maps\_ucav::main( "vehicle_ucav" );
maps\contingency_precache::main();
maps\createart\contingency_fog::main();
maps\contingency_fx::main();
maps\contingency_anim::main_anim();
maps\_load::main();
maps\_load::set_player_viewhand_model( "viewhands_player_arctic_wind" );
thread maps\contingency_amb::main();
maps\createart\contingency_art::main();
init_radio();
// finite amount of UAV
// level.remote_detonator_weapon = "remote_missile_detonator_finite";
level.remote_detonator_weapon = "remote_missile_detonator";
PreCacheItem( level.remote_detonator_weapon );
maps\_remotemissile::init();
maps\_remotemissile::init_radio_dialogue();
maps\_compass::setupMiniMap( "compass_map_contingency" );
vehicles = GetEntArray( "destructible_vehicle", "targetname" );
foreach ( vehicle in vehicles )
{
vehicle thread destructible_damage_monitor();
}
deadquotes = [];
deadquotes[ deadquotes.size ] = "@DEADQUOTE_SO_CLAYMORE_POINT_ENEMY";
deadquotes[ deadquotes.size ] = "@DEADQUOTE_SO_CLAYMORE_ENEMIES_SHOOT";
so_include_deadquote_array( deadquotes );
level.so_deadquotes_chance = 0.33;
/#
// thread player_input();
#/
}
init_radio()
{
// Use the weapon caches and set up you claymores if you got any left. Defensive positions, let's go.
level.scr_radio[ "so_intro" ] = "so_roof_cont_def_pos";
// Take control of the predator drone.
level.scr_radio[ "so_pickup_uav_reminder" ] = "so_roof_cont_mct_control_rig";
}
precache_strings()
{
PrecacheString( &"SO_ROOFTOP_CONTINGENCY_HOSTILES_COUNT" );
PrecacheString( &"SO_ROOFTOP_CONTINGENCY_UAZ_COUNT_SINGLE" );
PrecacheString( &"SO_ROOFTOP_CONTINGENCY_UAZ_COUNT" );
PrecacheString( &"SO_ROOFTOP_CONTINGENCY_BM21_COUNT" );
PrecacheString( &"SO_ROOFTOP_CONTINGENCY_BM21_COUNT_SINGLE" );
PrecacheString( &"SO_ROOFTOP_CONTINGENCY_DRONE_PICKUP" );
PrecacheString( CONST_regular_obj );
PrecacheString( CONST_hardened_obj );
PrecacheString( CONST_veteran_obj );
PrecacheString( &"SO_ROOFTOP_CONTINGENCY_WAVE_SECOND_STARTS" );
PrecacheString( &"SO_ROOFTOP_CONTINGENCY_WAVE_THIRD_STARTS" );
PrecacheString( &"SO_ROOFTOP_CONTINGENCY_WAVE_FOURTH_STARTS" );
PrecacheString( &"SO_ROOFTOP_CONTINGENCY_WAVE_FINAL_STARTS" );
PrecacheString( &"SO_ROOFTOP_CONTINGENCY_WAVE_STARTS" );
PrecacheString( &"SO_ROOFTOP_CONTINGENCY_CLAYMORE_KILLS" );
PrecacheString( &"SO_ROOFTOP_CONTINGENCY_HELLFIRE_KILLS" );
}
type_vehicle_special()
{
// keep all collmaps
if ( IsDefined( self.code_classname ) && self.code_classname == "script_vehicle_collmap" )
{
return false;
}
special_case = !( self transform_vehicle_by_targetname( "base_troop_transport2", "truck_1", "truck_1_guys" ) );
special_case2 = !( self transform_vehicle_by_targetname( "base_troop_transport1", "truck_2", "truck_2_guys" ) );
special_case3 = !( self transform_vehicle_by_targetname( "base_truck1", "jeep_1", "jeep_1_guys" ) );
special_case4 = !( self transform_vehicle_by_targetname( "second_uav", "second_uav", "uav_path" ) );
original_case = self type_vehicle();
test = 0;
if ( original_case )
{
test = 0;
}
special_result = special_case && special_case2 && special_case3 && special_case4;
result = special_result && original_case;
/#
if ( !special_result )
{
thread so_debug_print( "vehicle[" + self.targetname + "] saved", 5 );
}
#/
return result;
}
transform_vehicle_by_targetname( vehicle_name, targetname_string, target_string )
{
result = IsDefined( self.targetname ) && self.targetname == vehicle_name;
if ( result )
{
self.targetname = targetname_string;
self.target = target_string;
}
return result;
}
init_wave( wave_num, count )
{
if ( !IsDefined( level.wave_spawn_structs ) )
{
level.wave_spawn_structs = [];
}
temp = SpawnStruct();
temp.hostile_count = count;
temp.vehicles = [];
level.wave_spawn_structs[ wave_num ] = temp;
}
add_wave_vehicle( wave_num, targetname, type, alt_node, delay )
{
if ( !IsDefined( level.wave_spawn_structs ) )
{
level.wave_spawn_structs = [];
}
if ( !IsDefined( level.wave_spawn_structs[ wave_num ].vehicles ) )
{
level.wave_spawn_structs[ wave_num ].vehicles = [];
}
temp = SpawnStruct();
temp.targetname = targetname;
temp.ent = GetEnt( targetname, "targetname" );
temp.type = type;
temp.delay = undefined;
if ( IsDefined( delay ) )
{
temp.delay = delay;
}
temp.alt_node = undefined;
if ( IsDefined( alt_node ) )
{
temp.alt_node = alt_node;
}
size = level.wave_spawn_structs[ wave_num ].vehicles.size;
level.wave_spawn_structs[ wave_num ].vehicles[ size ] = temp;
}
so_setup_regular()
{
// Wave 1
init_wave( 1, 15 );
// Wave 2
init_wave( 2, 17 );
add_wave_vehicle( 2, "jeep_1", "uaz" );
// Wave 3
init_wave( 3, 19 );
add_wave_vehicle( 3, "truck_1", "bm21" );
level.challenge_objective = CONST_regular_obj;
level.new_hostile_accuracy = 1;
// level.hostile_wave_size = 17;
// level.hostile_waves = 3;
level.wiped_out_requirement = 2;
level.wave_delay = 10;
level.allowed_uav_ammo = 5;
level.uav_spawn_delay = 15;
level.UAV_pickup_respawn = false;
}
so_setup_hardened()
{
// Wave 1
init_wave( 1, 15 );
// Wave 2
init_wave( 2, 16 );
add_wave_vehicle( 2, "jeep_1", "uaz" );
// Wave 3
init_wave( 3, 17 );
add_wave_vehicle( 3, "truck_1", "bm21" );
// Wave 4
init_wave( 4, 18 );
add_wave_vehicle( 4, "jeep_1", "uaz", GetVehicleNode( "jeep_1_guys_alt", "targetname" ) );
level.challenge_objective = CONST_hardened_obj;
level.new_hostile_accuracy = 1;
level.wiped_out_requirement = 3;
level.wave_delay = 10;
level.allowed_uav_ammo = 4;
level.uav_spawn_delay = 15;
level.UAV_pickup_respawn = false;
}
so_setup_veteran()
{
// Wave 1
init_wave( 1, 15 );
// Wave 2
init_wave( 2, 16 );
add_wave_vehicle( 2, "jeep_1", "uaz" );
// Wave 3
init_wave( 3, 17 );
add_wave_vehicle( 3, "truck_1", "bm21" );
// Wave 4
init_wave( 4, 20 );
add_wave_vehicle( 4, "jeep_1", "uaz", GetVehicleNode( "jeep_1_guys_alt", "targetname" ) );
// Wave 5
init_wave( 5, 20 );
add_wave_vehicle( 5, "truck_2", "bm21" );
add_wave_vehicle( 5, "jeep_1", "uaz", GetVehicleNode( "jeep_1_guys_alt2", "targetname" ) );
level.challenge_objective = CONST_veteran_obj;
level.new_hostile_accuracy = 1;
level.wiped_out_requirement = 3;
level.wave_delay = 10;
level.allowed_uav_ammo = 3;
level.uav_spawn_delay = 20;
level.UAV_pickup_respawn = false;
}
so_rooftop_init()
{
level.so_uav_picked_up = false;
level.hostile_count = 0;
level.wave_spawn_structs = [];
Assert( IsDefined( level.gameskill ) );
switch( level.gameSkill )
{
case 0: // Easy
case 1: so_setup_Regular(); break; // Regular
case 2: so_setup_hardened();break; // Hardened
case 3: so_setup_veteran(); break; // Veteran
}
// wave move in delay time multiplier depending on if player is on roof or not
level.roof_factor = 1;
// setup all attack line script origins
all_attack_lines = GetEntArray( "attack_line", "targetname" );
foreach ( attack_line in all_attack_lines )
{
attack_line.times_used = 0;
}
spawner_setup();
spawn_functions();
level.custom_eog_no_kills = true;
level.custom_eog_no_partner = true;
level.eog_summary_callback = ::custom_eog_summary;
thread enable_escape_warning();
thread enable_escape_failure();
thread fade_challenge_out( "challenge_success" );
thread player_on_roof_think();
// thread vehicles_think();
// thread challenge_complete();
thread wave_wiped_out();
thread wave_spawn_think();
thread uav_pickup_setup();
thread uav();
// Add the players to the remotemissled targets, but as friendly.
foreach ( player in level.players )
{
player.claymore_kills = 0;
player.hellfire_kills = 0;
player thread maps\_remotemissile::setup_remote_missile_target();
player thread threat_priority_thread();
}
// HOLD HERE TILL PLAYERS READY IN ONLINE COOP
so_wait_for_players_ready();
Objective_Add( 1, "current", level.challenge_objective );
}
spawner_setup()
{
// Setup the Spawners
wave_size = get_wave_count();
for ( i = 1; i < wave_size + 1; i++ )
{
new_array = [];
foreach ( member in GetEntArray( "wave_guys", "script_noteworthy" ) )
{
new_array[ new_array.size ] = member;
if ( new_array.size >= get_wave_ai_count( i ) )
{
break;
}
}
level.wave_spawn_structs[ i ].spawners = array_randomize( new_array );
}
// We don't want the failsafe spawners to be included in the Setting up of spawners.
foreach ( spawner in GetEntArray( "failsafe_spawners", "targetname" ) )
{
spawner.script_noteworthy = "wave_guys";
}
}
spawn_functions()
{
level.current_wave = 1;
add_global_spawn_function( "axis", ::so_rooftop_ai_postspawn );
array_spawn_function_noteworthy( "wave_guys", ::wave_closing_in );
array_spawn_function_targetname( "truck_1_guys", ::wave_closing_in, "attack_line_med" );
array_spawn_function_targetname( "truck_2_guys", ::wave_closing_in, "attack_line_med" );
array_spawn_function_targetname( "jeep_1_guys", ::wave_closing_in, "attack_line_close" );
array_spawn_function_targetname( "jeep_1_guys_alt", ::wave_closing_in, "attack_line_close" );
array_spawn_function_targetname( "jeep_1_guys_alt2", ::wave_closing_in, "attack_line_med" );
GetEnt( "truck_1", "targetname" ) add_spawn_function( ::setup_base_vehicles );
GetEnt( "truck_2", "targetname" ) add_spawn_function( ::setup_base_vehicles );
GetEnt( "jeep_1", "targetname" ) add_spawn_function( ::setup_base_vehicles );
}
// AI -----------------------------------------------------
so_rooftop_ai_postspawn()
{
level.hostile_count++;
self thread hostile_nerf();
self thread set_wave_id();
self thread maps\contingency::setup_remote_missile_target_guy();
self thread death_think();
}
death_think()
{
self waittill_any( "death", "pain_death" );
level.hostile_count--;
if ( !IsDefined( self ) )
{
return;
}
damage_weapon = undefined;
attacker = undefined;
if ( IsDefined( self.damageweapon ) )
{
damage_weapon = self.damageweapon;
}
if ( IsDefined( self.lastattacker ) )
{
attacker = self.lastattacker;
}
// Assume destructible
destructible_killed = false;
if ( IsDefined( attacker.damageOwner ) )
{
if ( IsDefined( attacker.hellfired ) && attacker.hellfired )
{
damage_weapon = "remote_missile_snow";
}
else if ( IsDefined( attacker.claymored ) && attacker.claymored )
{
damage_weapon = "claymore";
}
attacker = attacker.damageOwner;
destructible_killed = true;
}
if ( !IsDefined( attacker ) || !IsPlayer( attacker ) || !IsDefined( damage_weapon ) )
{
return;
}
// To compensate for negative kills we need to make sure we count these guys as standard kills
// deathFunctions() does not check if the player caused the destructible to blow up and kill the AI.
if ( destructible_killed )
{
attacker.stats[ "kills" ]++;
}
// Claymore check
if ( damage_weapon == "claymore" )
{
attacker.claymore_kills++;
}
// Hellfire check
if ( damage_weapon == "remote_missile_snow" )
{
attacker.hellfire_kills++;
}
}
destructible_damage_monitor()
{
self endon( "exploded" );
while ( 1 )
{
self waittill( "damage", dmg, attacker, dir, point, mod, model, tagname, partname, dflags, weapon );
if ( IsPlayer( attacker ) )
{
if ( IsDefined( weapon ) )
{
if ( weapon == "remote_missile_snow" )
{
self.hellfired = true;
}
else if ( weapon == "claymore" )
{
self.claymored = true;
}
}
}
}
}
hostile_nerf()
{
self.baseaccuracy = level.new_hostile_accuracy;
}
set_wave_id()
{
if ( !isdefined( level.wave_spawn_structs[ level.current_wave ].wave_members ) )
{
level.wave_spawn_structs[ level.current_wave ].wave_members = [];
}
members_size = level.wave_spawn_structs[ level.current_wave ].wave_members.size;
level.wave_spawn_structs[ level.current_wave ].wave_members[ members_size ] = self;
}
getaiarray_by_wave_id()
{
Assert( IsDefined( level.current_wave ) );
Assert( IsDefined( level.wave_spawn_structs ) );
members = level.wave_spawn_structs[ level.current_wave1 ].wave_members;
Assert( IsDefined( members ) );
return members;
}
custom_eog_summary()
{
foreach ( player in level.players )
{
standard_kills = player.stats[ "kills" ];
standard_kills -= player.hellfire_kills;
standard_kills -= player.claymore_kills;
player add_custom_eog_summary_line( "@SO_ROOFTOP_CONTINGENCY_STANDARD_KILLS", standard_kills );
player add_custom_eog_summary_line( "@SO_ROOFTOP_CONTINGENCY_HELLFIRE_KILLS", player.hellfire_kills );
player add_custom_eog_summary_line( "@SO_ROOFTOP_CONTINGENCY_CLAYMORE_KILLS", player.claymore_kills );
if ( is_coop_online() )
player maps\_endmission::use_custom_eog_default_kills( get_other_player( player ) );
}
}
challenge_complete()
{
flag_set( "challenge_success" );
}
start_so_rooftop()
{
so_rooftop_init();
thread fade_challenge_in( undefined, false );
thread so_intro_dialogue();
/#
test_vehicles();
#/
wait so_standard_wait();
enable_challenge_timer( "waves_start", "challenge_success" );
thread enable_countdown_timer( level.wave_delay );
flag_set( "start_countdown" );
wait( 2 );
hud_wave_splash( 1, level.wave_delay - 2 );
flag_set( "waves_start" );
}
so_intro_dialogue()
{
wait( 1 );
radio_dialogue( "so_intro" );
}
// Waves --------------------------------------------------
wave_wiped_out()
{
level endon( "special_op_terminated" );
flag_wait( "waves_start" );
while ( 1 )
{
flag_wait( "wave_spawned" );
population = 0;
ai_wave = GetAIArray( "axis" );
foreach ( guy in ai_wave )
{
if ( IsAlive( guy ) )
{
population++;
}
}
if ( population <= level.wiped_out_requirement )
{
// send the remaining guys back to med attack line
array_thread( ai_wave, ::wave_closing_in, "attack_line_med" );
//foreach ( guy in ai_wave ) { guy ignore_all_till_goal(); }
// Wait for everyone to be dead before starting next wave.
// enemies = GetAIArray( "bad_guys" );
while ( level.hostile_count > 0 )
{
wait( 0.5 );
// enemies = GetAIArray( "bad_guys" );
}
//level.wave_spawn_structs[level.current_wave].wave_members = undefined;
/# so_debug_print( "wave [" + level.current_wave + "] wiped out" ); #/
flag_clear( "wave_spawned" );
flag_set( "wave_wiped_out" );
// sounds
level.player PlaySound( "arcademode_kill_streak_won" );
}
wait( 1 );
}
}
ignore_all_till_goal()
{
self endon( "death" );
self.pathenemyfightdist = 32;
self waittill( "goal" );
self.pathenemyfightdist = 192;
}
wave_spawn_think()
{
level endon( "special_op_terminated" );
array_thread( level.players, ::hud_hostile_count );
array_thread( level.players, ::hud_wave_num );
flag_wait( "waves_start" );
for ( i = 1; i < level.wave_spawn_structs.size + 1; i++ )
{
flag_clear( "wave_wiped_out" );
level.current_wave = i;
// Spawn in AI
// We may want to think of a better mechanism of spawning AI in.
// Rather than all at once, do something of a short period of time
// If we do, we'll have to address how the Hostiles counter logic is done.
spawn_failed_count = 0;
foreach ( spawner in level.wave_spawn_structs[ i ].spawners )
{
spawner set_count( 1 );
guy = spawner spawn_ai();
if ( !IsDefined( guy ) )
{
spawn_failed_count++;
so_debug_print( "wave_spawn_think() -- SPAWN FAILED COUNT = " + spawn_failed_count );
}
}
// If an AI does not spawn, try again until one does.
failsafe_spawners = GetEntArray( "failsafe_spawners", "targetname" );
for ( q = 0; q < spawn_failed_count; q++ )
{
spawner = failsafe_spawners[ RandomInt( failsafe_spawners.size ) ];
spawner set_count( 1 );
guy = spawner spawn_ai();
if ( !IsDefined( guy ) )
{
q--;
}
}
so_debug_print( "wave_spawn_think(), Current wave = " + level.current_wave );
// Spawn in Vehicles
vehicles = get_wave_vehicles( level.current_wave );
foreach ( vehicle in vehicles )
{
thread spawn_vehicle_and_go( vehicle );
}
flag_set( "wave_" + ( level.current_wave ) + "_started" );
level notify( "new_wave_started" );
if ( IsDefined( level.so_uav_player ) )
{
// Also re-enable if reloading... Just so the player can expect to use it right away.
level notify( "stop_uav_reload" );
flag_clear( "uav_reloading" );
level.so_uav_player maps\_remotemissile::enable_uav( level.so_uav_picked_up, level.remote_detonator_weapon );
level.so_uav_player thread maps\_remotemissile::remotemissile_radio_reminder();
}
wait( 1 );// give some time for all AI to spawn into map before monitoring population
flag_set( "wave_spawned" );
/# so_debug_print( "wave [" + ( level.current_wave + 1 ) + "] spawn complete" ); #/
flag_wait( "wave_wiped_out" );
if ( i == level.wave_spawn_structs.size )
{
thread challenge_complete();
return;
}
if ( IsDefined( level.so_uav_player ) )
{
level.so_uav_player maps\_remotemissile::disable_uav( level.so_uav_picked_up, true );
}
foreach ( player in level.players )
{
player notify( "force_out_of_uav" );
}
hud_new_wave();
}
}
wave_closing_in( start_with )
{
self endon( "death" );
if ( !isalive( self ) )
{
return;
}
self notify( "wave_closing_in_called" );
self endon( "wave_closing_in_called" );
// vehicle riders are to wait till they have unloaded to continue this spawn function
if ( IsDefined( self.script_noteworthy ) && self.script_noteworthy == "vehicle_guys" )
{
self waittill( "jumpedout" );
}
far_delay = 0;
med_delay = RandomFloatRange( 15, 20 );
close_delay = RandomFloatRange( 30, 35 );
player_delay = RandomFloatRange( 15, 25 );
factor = ( 100 - ( ( level.current_wave - 1 ) * 10 ) ) / 100 * level.roof_factor;
if ( self.classname != "actor_enemy_arctic_SNIPER" )
{
factor *= 0.75;
}
// shotgun dudes rushes towards player
if ( self.classname == "actor_enemy_arctic_SHOTGUN" )
{
factor *= 0.25;
}
if ( IsDefined( start_with ) && start_with != "attack_line_far" )
{
AssertEx( start_with == "attack_line_med" || start_with == "attack_line_close", "wave_closing_in() is misused, " + start_with + " attack line does not exist." );
if ( start_with == "attack_line_med" )
{
self wave_closing_in_at_line( factor * med_delay, "attack_line_med" );
}
self wave_closing_in_at_line( factor * close_delay, "attack_line_close" );
}
else
{
self wave_closing_in_at_line( factor * far_delay, "attack_line_far" );
self wave_closing_in_at_line( factor * med_delay, "attack_line_med" );
self wave_closing_in_at_line( factor * close_delay, "attack_line_close" );
}
self wave_goto_player( factor * player_delay );
}
threat_priority_thread()
{
self endon( "death" );
roof_point = getstruct( "so_roof_point", "targetname" );
while ( 1 )
{
weight = 0;
dist = Distance( roof_point.origin, self.origin );
// See if the player is away from the roof
// Then add more weight to him
if ( dist > 400 )
{
weight = dist / 2000;
}
self.so_priority = weight;
wait( 1 );
}
}
get_higher_priority_player( min_weight )
{
combined_weight = 1; // Start with 1 to give some more randomness
if ( min_weight < 0 )
{
combined_weight = 0;
}
player_array = [];
foreach ( player in level.players )
{
if ( player.so_priority > min_weight )
{
player_array[ player_array.size ] = player;
priority = player.so_priority;
dist2d = Distance2D( self.origin, player.origin );
priority += 1 - ( dist2d / 800 );
if ( priority < 0 )
{
priority = 0;
}
combined_weight += priority;
}
}
target_ent = undefined;
if ( player_array.size > 0 )
{
random_weight = RandomFloat( combined_weight );
curr_weight = 0;
foreach( player in player_array )
{
curr_weight += player.so_priority;
if ( random_weight < curr_weight )
{
target_ent = player;
}
}
}
return target_ent;
}
wave_goto_player( delay )
{
self endon( "death" );
wait( delay );
self thread seek_player();
}
seek_player( target_ent )
{
self endon( "death" );
level endon( "special_op_terminated" );
if ( !IsDefined( target_ent ) )
{
target_ent = get_higher_priority_player( -1 );
}
self.goalradius = 2000;
while ( 1 )
{
goalradius = self.goalradius;
if ( goalradius > 300 )
{
goalradius -= RandomIntRange( 200, 600 );
}
if ( goalradius < 300 )
{
goalradius = RandomIntRange( 250, 500 );
}
self.goalradius = goalradius;
if ( !IsDefined( target_ent ) )
{
target_ent = level.player;
if ( level.players.size > 1 )
{
if ( cointoss() )
{
target_ent = level.player2;
}
}
}
// Incase the player is downed already, go seek out the other player
if ( IsDefined( target_ent.coop_downed ) && target_ent.coop_downed )
{
count = 0;
foreach ( player in level.players )
{
if ( IsDefined( player.coop_downed ) && player.coop_downed )
{
count++;
}
}
// Get out if both are downed
if ( count == level.players.size )
{
return;
}
if ( level.player == target_ent )
{
self.goalradius = 800;
self thread seek_player( level.player2 );
return;
}
else if ( IsDefined( level.player2 ) && level.player2 == target_ent )
{
self.goalradius = 800;
self thread seek_player( level.player );
return;
}
}
self SetGoalEntity( target_ent );
self waittill( "goal" );
wait( RandomFloatRange( 5, 9 ) );
}
}
player_on_roof_think()
{
// if player on roof, challenge is easier
while ( 1 )
{
level waittill( "player_on_roof" );
if ( flag( "player_on_roof" ) )
{
foreach ( guy in GetAIArray( "axis" ) )
{
// guy set_goal_radius( 512 );
level.roof_factor = 1;
guy hostile_nerf();
}
set_grenade_frequency( 1 );
/# so_debug_print( "player on roof" ); #/
}
else
{
foreach ( guy in GetAIArray( "axis" ) )
{
// guy set_goal_radius( 220 );
level.roof_factor = 0.7;// waves move in faster when player on ground
guy.baseaccuracy = 2;
}
set_grenade_frequency( 0.5 );
/# so_debug_print( "player off roof" ); #/
}
wait( 2 );
}
}
set_grenade_frequency( fraction )
{
if ( !isdefined( fraction ) )
fraction = 1;
maps\_gameskill::add_fractional_data_point( "playerGrenadeBaseTime", 0.25, 40000 * fraction );// original easy
maps\_gameskill::add_fractional_data_point( "playerGrenadeBaseTime", 0.75, 35000 * fraction );// original normal
level.difficultySettings[ "playerGrenadeBaseTime" ][ "hardened" ] = 25000 * fraction;
level.difficultySettings[ "playerGrenadeBaseTime" ][ "veteran" ] = 25000 * fraction;
maps\_gameskill::updateGameSkill();
maps\_gameskill::updateAllDifficulty();
}
wave_closing_in_at_line( delay, attack_line )
{
self endon( "death" );
wait delay;
// Get higher priority
if ( attack_line == "attack_line_far" )
{
min_weight = 0.75;
}
else if ( attack_line == "attack_line_med" )
{
min_weight = 0.5;
}
else
{
min_weight = 0.25;
}
target_ent = get_higher_priority_player( min_weight );
if ( IsDefined( target_ent ) )
{
self seek_player( target_ent );
}
else
{
self set_attack_line( attack_line );
self waittill( "goal" );
}
}
set_attack_line( line_position )
{
attack_line = GetEntArray( line_position, "script_noteworthy" );
AssertEx( IsDefined( attack_line ), "There is no " + line_position + " attack line in level." );
// use all attack lines evenly
to_ent = attack_line[ RandomInt( attack_line.size ) ];
foreach ( ent in attack_line )
{
if ( ent.times_used < to_ent.times_used )
{
to_ent = ent;
}
}
self set_goal_radius( to_ent.radius );
self set_goal_pos( to_ent.origin );
to_ent.times_used++;
/#
so_debug_print( "AI[" + self GetEntNum() + "] going to [" + line_position + "]" );
#/
}
test_vehicles()
{
// TESTING!!!
// add_wave_vehicle( 2, "jeep_1", "uaz" );
// add_wave_vehicle( 3, "truck_1", "bm21" );
// add_wave_vehicle( 4, "jeep_1", "uaz", GetVehicleNode( "jeep_1_guys_alt", "targetname" ) );
// add_wave_vehicle( 5, "truck_2", "bm21" );
// add_wave_vehicle( 5, "jeep_1", "uaz", GetVehicleNode( "jeep_1_guys_alt2", "targetname" ) );
// wait( 5 );
// temp = SpawnStruct();
// temp.alt_node = undefined;
// JEEP 1
// temp.ent = GetEnt( "jeep_1", "targetname" );
// JEEP 1 ALT
// temp.ent = GetEnt( "jeep_1", "targetname" );
// temp.alt_node = GetVehicleNode( "jeep_1_guys_alt", "targetname" );
// TRUCK 1
// temp.ent = GetEnt( "truck_1", "targetname" );
// TRUCK 2
// temp.ent = GetEnt( "truck_2", "targetname" );
// JEEP 1 ALT2
// temp.ent = GetEnt( "jeep_1", "targetname" );
// temp.alt_node = GetVehicleNode( "jeep_1_guys_alt2", "targetname" );
// spawn_vehicle_and_go( temp );
// level waittill( "never" );
}