2319 lines
63 KiB
Plaintext
2319 lines
63 KiB
Plaintext
// IW6 GSC SOURCE
|
|
// Generated by https://github.com/xensik/gsc-tool
|
|
|
|
init()
|
|
{
|
|
if ( !isdefined( level.alien_cycle_table ) )
|
|
level.alien_cycle_table = "mp/alien/default_cycle_spawn.csv";
|
|
|
|
if ( !isdefined( level.alien_cycle_table_hardcore ) )
|
|
level.alien_cycle_table_hardcore = "mp/alien/default_cycle_spawn_hardcore.csv";
|
|
|
|
if ( maps\mp\alien\_utility::is_hardcore_mode() )
|
|
level.alien_cycle_table = level.alien_cycle_table_hardcore;
|
|
|
|
if ( !isdefined( level.base_player_count_multiplier ) )
|
|
{
|
|
level.base_player_count_multiplier = 0.49;
|
|
level.additional_player_count_multiplier = 0.17;
|
|
}
|
|
|
|
if ( !isdefined( level.hardcore_spawn_multiplier ) )
|
|
level.hardcore_spawn_multiplier = 1.0;
|
|
|
|
if ( !isdefined( level.hardcore_damage_scalar ) )
|
|
level.hardcore_damage_scalar = 1.0;
|
|
|
|
if ( !isdefined( level.hardcore_health_scalar ) )
|
|
level.hardcore_health_scalar = 1.0;
|
|
|
|
if ( !isdefined( level.hardcore_reward_scalar ) )
|
|
level.hardcore_reward_scalar = 1.0;
|
|
|
|
if ( !isdefined( level.hardcore_score_scalar ) )
|
|
level.hardcore_score_scalar = 1.0;
|
|
|
|
if ( !isdefined( level.casual_spawn_multiplier ) )
|
|
level.casual_spawn_multiplier = 1.0;
|
|
|
|
if ( !isdefined( level.casual_damage_scalar ) )
|
|
level.casual_damage_scalar = 0.5;
|
|
|
|
if ( !isdefined( level.casual_health_scalar ) )
|
|
level.casual_health_scalar = 0.5;
|
|
|
|
if ( !isdefined( level.casual_reward_scalar ) )
|
|
level.casual_reward_scalar = 1.0;
|
|
|
|
if ( !isdefined( level.casual_score_scalar ) )
|
|
level.casual_score_scalar = 0.5;
|
|
|
|
level.cycle_data = spawnstruct();
|
|
level.lanes = [];
|
|
load_cycles_from_table( level.cycle_data );
|
|
init_spawn_node_info( level.cycle_data );
|
|
build_spawn_zones( level.cycle_data );
|
|
load_spawn_events_from_table( level.cycle_data );
|
|
load_variables_from_table( level.cycle_data );
|
|
load_cycle_scalars_from_table( level.cycle_data );
|
|
load_cycle_drill_layer_from_table( level.cycle_data );
|
|
load_random_hives_from_table();
|
|
load_encounter_lanes_from_table();
|
|
populate_lane_spawners();
|
|
level.cycle_data.current_wave_types = create_wave_types_array();
|
|
level.cycle_data.current_spawn_event_wave_types = create_wave_types_array();
|
|
level thread spawn_type_vo_monitor();
|
|
level thread monitor_meteor_spawn();
|
|
level thread monitor_ground_spawn();
|
|
level.pending_meteor_spawns = 0;
|
|
level.pending_ground_spawns = 0;
|
|
level.pending_custom_spawns = 0;
|
|
level.cycle_spawning_active = 0;
|
|
|
|
if ( maps\mp\alien\_utility::isplayingsolo() )
|
|
level.cycle_data.max_alien_count = int( ceil( 18 * level.base_player_count_multiplier ) );
|
|
else
|
|
level.cycle_data.max_alien_count = 18;
|
|
}
|
|
|
|
load_variables_from_table( var_0 )
|
|
{
|
|
var_0.min_spawn_interval = float( tablelookup( level.alien_cycle_table, 0, 400, 2 ) );
|
|
var_1 = float( tablelookup( level.alien_cycle_table, 0, 401, 2 ) );
|
|
var_0.safe_spawn_distance_sq = var_1 * var_1;
|
|
var_0.spawn_point_last_used_duration = float( tablelookup( level.alien_cycle_table, 0, 402, 2 ) ) * 1000.0;
|
|
var_2 = float( tablelookup( level.alien_cycle_table, 0, 403, 2 ) );
|
|
var_0.group_break_away_distance_sq = var_2 * var_2;
|
|
var_0.player_in_zone_score_modifier = float( tablelookup( level.alien_cycle_table, 0, 404, 2 ) );
|
|
var_0.current_attacker_in_zone_score_modifier = float( tablelookup( level.alien_cycle_table, 0, 405, 2 ) );
|
|
var_0.recently_used_spawn_zone_score_modifier = float( tablelookup( level.alien_cycle_table, 0, 406, 2 ) );
|
|
var_0.max_break_away_zone_score_increase = float( tablelookup( level.alien_cycle_table, 0, 407, 2 ) );
|
|
var_0.spawn_event_min_activation_time = float( tablelookup( level.alien_cycle_table, 0, 408, 2 ) );
|
|
var_0.spawn_event_per_alien_activation_increase = float( tablelookup( level.alien_cycle_table, 0, 409, 2 ) );
|
|
var_0.spawn_event_max_activation_increase = float( tablelookup( level.alien_cycle_table, 0, 410, 2 ) );
|
|
}
|
|
|
|
load_encounter_lanes_from_table()
|
|
{
|
|
level.encounter_lanes = [];
|
|
|
|
for ( var_0 = 700; var_0 <= 799; var_0++ )
|
|
{
|
|
var_1 = tablelookup( level.alien_cycle_table, 0, var_0, 1 );
|
|
|
|
if ( var_1 == "" )
|
|
break;
|
|
|
|
if ( !isdefined( level.encounter_lanes[var_1] ) )
|
|
level.encounter_lanes[var_1] = [];
|
|
|
|
var_2 = strtok( tablelookup( level.alien_cycle_table, 0, var_0, 2 ), ", " );
|
|
var_3 = strtok( tablelookup( level.alien_cycle_table, 0, var_0, 3 ), " ,()" );
|
|
var_4 = get_lanes_from_names( var_3 );
|
|
var_5 = tolower( var_3[0] ) == "random_sequence" && var_3.size > 1;
|
|
var_6 = 0;
|
|
|
|
foreach ( var_8 in var_2 )
|
|
{
|
|
var_9 = [];
|
|
|
|
if ( var_5 )
|
|
{
|
|
var_9[0] = var_4[var_6];
|
|
var_6++;
|
|
|
|
if ( var_6 >= var_4.size )
|
|
var_6 = 0;
|
|
}
|
|
else
|
|
var_9 = var_4;
|
|
|
|
add_new_encounter_lane( var_1, var_9, var_8 );
|
|
}
|
|
|
|
foreach ( var_12 in var_4 )
|
|
{
|
|
if ( isdefined( level.lanes[var_12] ) )
|
|
continue;
|
|
|
|
level.lanes[var_12] = [];
|
|
}
|
|
}
|
|
|
|
foreach ( var_16, var_15 in level.encounter_lanes )
|
|
level.encounter_lanes[var_16] = sort_array( level.encounter_lanes[var_16], ::sort_encounter_level_activation_time_func );
|
|
}
|
|
|
|
add_new_encounter_lane( var_0, var_1, var_2 )
|
|
{
|
|
var_3 = spawnstruct();
|
|
var_3.lanes = var_1;
|
|
var_3.activation_time = int( var_2 ) * 1000.0;
|
|
var_4 = level.encounter_lanes[var_0].size;
|
|
level.encounter_lanes[var_0][var_4] = var_3;
|
|
}
|
|
|
|
get_lanes_from_names( var_0 )
|
|
{
|
|
var_1 = tolower( var_0[0] ) == "random_sequence" && var_0.size > 1;
|
|
var_2 = tolower( var_0[0] ) == "random" && var_0.size > 1;
|
|
var_3 = [];
|
|
|
|
if ( var_1 )
|
|
{
|
|
var_3 = maps\mp\alien\_utility::array_remove_index( var_0, 0 );
|
|
var_3 = common_scripts\utility::array_randomize( var_3 );
|
|
}
|
|
else if ( var_2 )
|
|
{
|
|
var_4 = randomintrange( 1, var_0.size );
|
|
var_3[0] = var_0[var_4];
|
|
}
|
|
else
|
|
var_3 = var_0;
|
|
|
|
return var_3;
|
|
}
|
|
|
|
populate_lane_spawners()
|
|
{
|
|
foreach ( var_8, var_1 in level.lanes )
|
|
{
|
|
var_2 = common_scripts\utility::getstruct( var_8, "targetname" );
|
|
var_3 = var_2 common_scripts\utility::get_links();
|
|
|
|
foreach ( var_5 in var_3 )
|
|
{
|
|
var_6 = find_spawners_by_script_name( var_5 );
|
|
level.lanes[var_8] = common_scripts\utility::array_combine( level.lanes[var_8], var_6 );
|
|
}
|
|
}
|
|
}
|
|
|
|
find_spawners_by_script_name( var_0 )
|
|
{
|
|
var_1 = [];
|
|
|
|
for ( var_2 = 0; var_2 < level.cycle_data.spawner_list.size; var_2++ )
|
|
{
|
|
if ( !isdefined( level.cycle_data.spawner_list[var_2]["location"].script_linkname ) )
|
|
continue;
|
|
|
|
if ( level.cycle_data.spawner_list[var_2]["location"].script_linkname == var_0 )
|
|
var_1[var_1.size] = var_2;
|
|
}
|
|
|
|
return var_1;
|
|
}
|
|
|
|
load_spawn_events_from_table( var_0 )
|
|
{
|
|
var_0.generic_spawn_events = [];
|
|
|
|
for ( var_1 = 2000; var_1 <= 2099; var_1++ )
|
|
{
|
|
var_2 = tablelookup( level.alien_cycle_table, 0, var_1, 1 );
|
|
|
|
if ( var_2 == "" )
|
|
break;
|
|
|
|
var_3 = int( var_2 ) - 1;
|
|
var_4 = spawnstruct();
|
|
var_4.activation_notify = tablelookup( level.alien_cycle_table, 0, var_1, 2 );
|
|
var_4.id = strtok( tablelookup( level.alien_cycle_table, 0, var_1, 3 ), " ," );
|
|
var_4.time_limit = float( tablelookup( level.alien_cycle_table, 0, var_1, 4 ) );
|
|
var_5 = strtok( tablelookup( level.alien_cycle_table, 0, var_1, 5 ), " ," );
|
|
|
|
if ( var_5.size > 0 )
|
|
{
|
|
var_6 = get_lanes_from_names( var_5 );
|
|
var_4.lanes = var_6;
|
|
|
|
foreach ( var_8 in var_6 )
|
|
{
|
|
if ( isdefined( level.lanes[var_8] ) )
|
|
continue;
|
|
|
|
level.lanes[var_8] = [];
|
|
}
|
|
}
|
|
|
|
if ( var_3 == -1 )
|
|
{
|
|
var_4.allow_initial_delay = 0;
|
|
var_10 = var_0.generic_spawn_events.size;
|
|
var_0.generic_spawn_events[var_10] = var_4;
|
|
continue;
|
|
}
|
|
|
|
var_4.allow_initial_delay = 1;
|
|
var_10 = var_0.spawn_cycles[var_3].spawn_events.size;
|
|
var_0.spawn_cycles[var_3].spawn_events[var_10] = var_4;
|
|
}
|
|
|
|
load_spawn_event_waves_from_table();
|
|
}
|
|
|
|
load_spawn_event_waves_from_table()
|
|
{
|
|
level.spawn_event_waves = [];
|
|
|
|
for ( var_0 = 3000; var_0 <= 3099; var_0++ )
|
|
{
|
|
var_1 = tablelookup( level.alien_cycle_table, 0, var_0, 1 );
|
|
|
|
if ( var_1 == "" )
|
|
break;
|
|
|
|
if ( !isdefined( level.spawn_event_waves[var_1] ) )
|
|
level.spawn_event_waves[var_1] = [];
|
|
|
|
var_2 = spawnstruct();
|
|
var_2.blocking = get_spawn_event_wave_blocking_by_index( var_0 );
|
|
var_2.spawn_delay = float( tablelookup( level.alien_cycle_table, 0, var_0, 3 ) );
|
|
var_2.entry_index = var_0;
|
|
var_3 = level.spawn_event_waves[var_1].size;
|
|
level.spawn_event_waves[var_1][var_3] = var_2;
|
|
}
|
|
}
|
|
|
|
get_spawn_event_wave_blocking_by_index( var_0 )
|
|
{
|
|
var_1 = tablelookup( level.alien_cycle_table, 0, var_0, 2 );
|
|
return var_1 == "yes";
|
|
}
|
|
|
|
clear_spawn_event_wave_types()
|
|
{
|
|
foreach ( var_1 in level.cycle_data.current_spawn_event_wave_types )
|
|
{
|
|
var_1.type_name = undefined;
|
|
var_1.min_spawned = undefined;
|
|
var_1.max_spawned = undefined;
|
|
var_1.max_of_type = undefined;
|
|
}
|
|
}
|
|
|
|
get_spawn_event_types_array( var_0 )
|
|
{
|
|
clear_spawn_event_wave_types();
|
|
get_type_data( get_available_type_data( level.cycle_data.current_spawn_event_wave_types ), var_0, 4, 5 );
|
|
get_type_data( get_available_type_data( level.cycle_data.current_spawn_event_wave_types ), var_0, 6, 7 );
|
|
get_type_data( get_available_type_data( level.cycle_data.current_spawn_event_wave_types ), var_0, 8, 9 );
|
|
get_type_data( get_available_type_data( level.cycle_data.current_spawn_event_wave_types ), var_0, 10, 11 );
|
|
get_type_data( get_available_type_data( level.cycle_data.current_spawn_event_wave_types ), var_0, 12, 13 );
|
|
level.cycle_data.current_spawn_event_wave_types = sort_array( level.cycle_data.current_spawn_event_wave_types, ::sort_priority_levels_func );
|
|
return level.cycle_data.current_spawn_event_wave_types;
|
|
}
|
|
|
|
set_intensity( var_0 )
|
|
{
|
|
level.current_intensity = clamp( var_0, 0.0, 1.0 );
|
|
}
|
|
|
|
force_intensity( var_0, var_1 )
|
|
{
|
|
if ( var_0 )
|
|
level.forced_current_intensity = clamp( var_1, 0.0, 1.0 );
|
|
else if ( isdefined( level.forced_current_intensity ) )
|
|
level.forced_current_intensity = undefined;
|
|
}
|
|
|
|
load_cycles_from_table( var_0 )
|
|
{
|
|
var_0.spawn_cycles = [];
|
|
var_1 = 0;
|
|
var_2 = 399;
|
|
|
|
if ( level.script == "mp_alien_last" && !maps\mp\alien\_utility::is_chaos_mode() )
|
|
{
|
|
var_1 = 1000;
|
|
var_2 = 1999;
|
|
}
|
|
|
|
for ( var_3 = var_1; var_3 <= var_2; var_3++ )
|
|
{
|
|
var_4 = get_cycle_by_index( var_3 );
|
|
|
|
if ( var_4 == "" )
|
|
break;
|
|
|
|
var_5 = int( var_4 ) - 1;
|
|
|
|
if ( !isdefined( var_0.spawn_cycles[var_5] ) )
|
|
{
|
|
var_6 = spawnstruct();
|
|
var_6.intensitylevels = [];
|
|
var_6.spawn_events = [];
|
|
var_6.lanes = [];
|
|
var_6.type_max_counts = [];
|
|
var_0.spawn_cycles[var_5] = var_6;
|
|
}
|
|
else
|
|
var_6 = var_0.spawn_cycles[var_5];
|
|
|
|
var_7 = spawnstruct();
|
|
var_7.intensitythreshold = get_intensity_threshold_by_index( var_3 );
|
|
var_7.tableindex = var_3;
|
|
var_6.intensitylevels[var_6.intensitylevels.size] = var_7;
|
|
}
|
|
|
|
foreach ( var_6 in var_0.spawn_cycles )
|
|
{
|
|
var_6.intensitylevels = sort_array( var_6.intensitylevels, ::sort_intensity_levels_func );
|
|
|
|
if ( var_6.intensitylevels.size > 0 )
|
|
{
|
|
var_9 = var_6.intensitylevels[var_6.intensitylevels.size - 1].intensitythreshold;
|
|
|
|
foreach ( var_11 in var_6.intensitylevels )
|
|
{
|
|
if ( var_9 <= 0.0 )
|
|
{
|
|
var_11.intensitythreshold = 0.0;
|
|
continue;
|
|
}
|
|
|
|
var_11.intensitythreshold = var_11.intensitythreshold / var_9;
|
|
}
|
|
|
|
var_6.fullintensitytime = var_9 * 1000.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
sort_array( var_0, var_1, var_2, var_3 )
|
|
{
|
|
if ( !isdefined( var_2 ) )
|
|
var_2 = 0;
|
|
|
|
for ( var_4 = var_2 + 1; var_4 < var_0.size; var_4++ )
|
|
{
|
|
var_5 = var_0[var_4];
|
|
|
|
for ( var_6 = var_4 - 1; var_6 >= var_2 && [[ var_1 ]]( var_0[var_6], var_5, var_3 ); var_6-- )
|
|
var_0[var_6 + 1] = var_0[var_6];
|
|
|
|
var_0[var_6 + 1] = var_5;
|
|
}
|
|
|
|
return var_0;
|
|
}
|
|
|
|
sort_intensity_levels_func( var_0, var_1, var_2 )
|
|
{
|
|
return var_0.intensitythreshold > var_1.intensitythreshold;
|
|
}
|
|
|
|
sort_encounter_level_activation_time_func( var_0, var_1, var_2 )
|
|
{
|
|
return var_0.activation_time > var_1.activation_time;
|
|
}
|
|
|
|
sort_priority_levels_func( var_0, var_1, var_2 )
|
|
{
|
|
if ( !isdefined( var_1.type_name ) )
|
|
return 0;
|
|
|
|
if ( !isdefined( var_0.type_name ) )
|
|
return 1;
|
|
|
|
var_3 = get_translated_ai_type( var_0.type_name );
|
|
var_4 = get_translated_ai_type( var_1.type_name );
|
|
var_5 = level.alien_types[var_3].attributes["attacker_priority"];
|
|
var_6 = level.alien_types[var_4].attributes["attacker_priority"];
|
|
return var_5 > var_6;
|
|
}
|
|
|
|
sort_closest_distance_to_players_func( var_0, var_1, var_2 )
|
|
{
|
|
var_3 = get_average_distance_to_players( var_0["location"].origin );
|
|
var_4 = get_average_distance_to_players( var_1["location"].origin );
|
|
return var_3 > var_4;
|
|
}
|
|
|
|
sort_player_view_direction_func( var_0, var_1, var_2 )
|
|
{
|
|
var_3 = var_2[0];
|
|
var_4 = var_2[1];
|
|
var_5 = get_player_to_node_dot( var_3, var_4, var_1["location"] );
|
|
var_6 = get_player_to_node_dot( var_3, var_4, var_0["location"] );
|
|
return var_6 < var_5;
|
|
}
|
|
|
|
get_player_to_node_dot( var_0, var_1, var_2 )
|
|
{
|
|
var_3 = vectornormalize( var_2.origin - var_0 );
|
|
return vectordot( var_3, var_1 );
|
|
}
|
|
|
|
get_average_distance_to_players( var_0 )
|
|
{
|
|
var_1 = level.players.size;
|
|
|
|
if ( var_1 == 0 )
|
|
return 0;
|
|
|
|
var_2 = 0;
|
|
|
|
foreach ( var_4 in level.players )
|
|
var_2 = var_2 + distancesquared( var_4.origin, var_0 );
|
|
|
|
return var_2 / var_1;
|
|
}
|
|
|
|
build_spawn_zones( var_0 )
|
|
{
|
|
var_1 = common_scripts\utility::getstructarray( "alien_spawn_struct", "targetname" );
|
|
var_2 = getentarray( "spawn_zone", "targetname" );
|
|
var_0.spawn_zones = [];
|
|
|
|
foreach ( var_4 in var_2 )
|
|
{
|
|
var_5 = spawnstruct();
|
|
var_5.zone_name = var_4.script_linkname;
|
|
var_5.volume = var_4;
|
|
var_5.spawn_nodes = [];
|
|
var_0.spawn_zones[var_4.script_linkname] = var_5;
|
|
}
|
|
|
|
var_0.spawner_list = [];
|
|
put_spawnlocations_into_cycle_data( var_1, var_0 );
|
|
}
|
|
|
|
put_spawnlocations_into_cycle_data( var_0, var_1 )
|
|
{
|
|
foreach ( var_3 in var_0 )
|
|
{
|
|
var_4 = [];
|
|
|
|
if ( isdefined( level.adjust_spawnlocation_func ) )
|
|
var_3 = [[ level.adjust_spawnlocation_func ]]( var_3 );
|
|
|
|
if ( isdefined( var_3.script_noteworthy ) )
|
|
var_4 = strtok( var_1.spawn_node_info[var_3.script_noteworthy].validtype, " " );
|
|
|
|
var_5 = [];
|
|
var_5["types"] = var_4;
|
|
var_5["location"] = var_3;
|
|
var_1.spawner_list[var_1.spawner_list.size] = var_5;
|
|
|
|
if ( !isdefined( var_3.script_linkto ) )
|
|
continue;
|
|
|
|
var_6 = var_3 common_scripts\utility::get_links();
|
|
|
|
foreach ( var_8 in var_6 )
|
|
{
|
|
var_9 = var_1.spawn_zones[var_8].spawn_nodes.size;
|
|
var_1.spawn_zones[var_8].spawn_nodes[var_9] = var_5;
|
|
}
|
|
}
|
|
}
|
|
|
|
spawn_zone_exists( var_0, var_1 )
|
|
{
|
|
foreach ( var_4, var_3 in var_1.spawn_zones )
|
|
{
|
|
if ( var_4 == var_0 )
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
can_spawn_type( var_0 )
|
|
{
|
|
if ( !isdefined( level.current_cycle ) || !isdefined( level.current_cycle.type_max_counts[var_0] ) )
|
|
return get_max_alien_count() - get_current_agent_count() > 0;
|
|
|
|
return level.current_cycle.type_max_counts[var_0] - get_current_agent_count_of_type( var_0 ) > 0;
|
|
}
|
|
|
|
reserve_custom_spawn_space( var_0, var_1, var_2 )
|
|
{
|
|
if ( !isdefined( var_1 ) )
|
|
var_1 = 0;
|
|
|
|
var_3 = get_current_agent_count();
|
|
|
|
if ( var_1 )
|
|
{
|
|
if ( isdefined( var_2 ) && isdefined( level.current_cycle ) && isdefined( level.current_cycle.type_max_counts[var_2] ) )
|
|
var_0 = clamp( level.current_cycle.type_max_counts[var_2] - get_current_agent_count_of_type( var_2 ), 0, var_0 );
|
|
|
|
var_4 = clamp( get_max_alien_count() - var_3, 0, var_0 );
|
|
}
|
|
else if ( var_3 + var_0 <= get_max_alien_count() )
|
|
var_4 = var_0;
|
|
else
|
|
var_4 = 0;
|
|
|
|
level.pending_custom_spawns = level.pending_custom_spawns + var_4;
|
|
return var_4;
|
|
}
|
|
|
|
process_custom_spawn( var_0, var_1, var_2 )
|
|
{
|
|
var_3 = get_current_agent_count( 1, 0, 1 );
|
|
|
|
if ( var_3 >= get_max_alien_count() )
|
|
var_4 = undefined;
|
|
else
|
|
var_4 = process_spawn( var_0, var_1, var_2 );
|
|
|
|
level.pending_custom_spawns = max( 0, level.pending_custom_spawns - 1 );
|
|
return var_4;
|
|
}
|
|
|
|
release_custom_spawn_space( var_0 )
|
|
{
|
|
level.pending_custom_spawns = max( 0, level.pending_custom_spawns - var_0 );
|
|
}
|
|
|
|
get_cycle_by_index( var_0 )
|
|
{
|
|
return tablelookup( level.alien_cycle_table, 0, var_0, 1 );
|
|
}
|
|
|
|
get_intensity_level_by_index( var_0 )
|
|
{
|
|
return tablelookup( level.alien_cycle_table, 0, var_0, 2 );
|
|
}
|
|
|
|
get_respawn_threshold_by_index( var_0 )
|
|
{
|
|
var_1 = tablelookup( level.alien_cycle_table, 0, var_0, 4 );
|
|
|
|
if ( var_1 == "" || var_1 == " " )
|
|
return undefined;
|
|
|
|
return int( var_1 );
|
|
}
|
|
|
|
get_respawn_delay_by_index( var_0 )
|
|
{
|
|
var_1 = tablelookup( level.alien_cycle_table, 0, var_0, 5 );
|
|
|
|
if ( var_1 == "" || var_1 == " " )
|
|
return undefined;
|
|
|
|
return float( var_1 );
|
|
}
|
|
|
|
get_intensity_threshold_by_index( var_0 )
|
|
{
|
|
return float( tablelookup( level.alien_cycle_table, 0, var_0, 3 ) );
|
|
}
|
|
|
|
get_types_array( var_0 )
|
|
{
|
|
get_type_data( get_available_type_data( level.cycle_data.current_wave_types ), var_0, 7, 8 );
|
|
get_type_data( get_available_type_data( level.cycle_data.current_wave_types ), var_0, 9, 10 );
|
|
get_type_data( get_available_type_data( level.cycle_data.current_wave_types ), var_0, 11, 12 );
|
|
get_type_data( get_available_type_data( level.cycle_data.current_wave_types ), var_0, 13, 14 );
|
|
get_type_data( get_available_type_data( level.cycle_data.current_wave_types ), var_0, 15, 16 );
|
|
get_type_data( get_available_type_data( level.cycle_data.current_wave_types ), var_0, 17, 18 );
|
|
get_type_data( get_available_type_data( level.cycle_data.current_wave_types ), var_0, 19, 20 );
|
|
get_type_data( get_available_type_data( level.cycle_data.current_wave_types ), var_0, 21, 22 );
|
|
get_type_data( get_available_type_data( level.cycle_data.current_wave_types ), var_0, 23, 24 );
|
|
level.cycle_data.current_wave_types = sort_array( level.cycle_data.current_wave_types, ::sort_priority_levels_func );
|
|
}
|
|
|
|
get_available_type_data( var_0 )
|
|
{
|
|
for ( var_1 = 0; var_1 < var_0.size; var_1++ )
|
|
{
|
|
if ( !isdefined( var_0[var_1].type_name ) )
|
|
return var_0[var_1];
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
get_type_data( var_0, var_1, var_2, var_3 )
|
|
{
|
|
if ( !isdefined( var_0 ) )
|
|
return undefined;
|
|
|
|
var_4 = tablelookup( level.alien_cycle_table, 0, var_1, var_2 );
|
|
|
|
if ( var_4 == "" )
|
|
return undefined;
|
|
|
|
var_5 = strtok( tablelookup( level.alien_cycle_table, 0, var_1, var_3 ), " " );
|
|
var_0.type_name = var_4;
|
|
var_5[0] = int( var_5[0] );
|
|
var_5[1] = int( var_5[1] );
|
|
|
|
if ( var_5.size == 0 )
|
|
var_0.min_spawned = 0;
|
|
else if ( var_5.size == 1 )
|
|
var_0.min_spawned = var_5[0];
|
|
else
|
|
{
|
|
if ( var_5[0] < var_5[1] )
|
|
{
|
|
var_0.min_spawned = var_5[0];
|
|
var_0.max_spawned = var_5[1];
|
|
}
|
|
else if ( var_5[1] > var_5[0] )
|
|
{
|
|
var_0.min_spawned = var_5[1];
|
|
var_0.max_spawned = var_5[0];
|
|
}
|
|
else
|
|
var_0.min_spawned = var_5[0];
|
|
|
|
if ( var_5.size == 3 )
|
|
var_0.max_of_type = int( var_5[2] );
|
|
}
|
|
|
|
return var_0;
|
|
}
|
|
|
|
remove_spawn_location( var_0 )
|
|
{
|
|
foreach ( var_2 in level.cycle_data.spawn_zones )
|
|
{
|
|
for ( var_3 = 0; var_3 < var_2.spawn_nodes.size; var_3++ )
|
|
{
|
|
var_4 = var_2.spawn_nodes[var_3]["location"];
|
|
|
|
if ( !isdefined( var_4.script_linkname ) )
|
|
continue;
|
|
|
|
if ( var_4.script_linkname == var_0 )
|
|
{
|
|
var_2.spawn_nodes = maps\mp\alien\_utility::array_remove_index( var_2.spawn_nodes, var_3 );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
start_cycle( var_0 )
|
|
{
|
|
set_cycle_scalars( var_0 );
|
|
level.cycle_spawning_active = 1;
|
|
level thread spawn_director_loop( var_0 - 1 );
|
|
level notify( "alien_cycle_started" );
|
|
}
|
|
|
|
end_cycle()
|
|
{
|
|
level notify( "end_cycle" );
|
|
level.cycle_spawning_active = 0;
|
|
level notify( "alien_cycle_ended" );
|
|
}
|
|
|
|
pause_cycle( var_0 )
|
|
{
|
|
if ( !level.cycle_spawning_active )
|
|
return;
|
|
|
|
level thread pause_cycle_internal( var_0 );
|
|
}
|
|
|
|
pause_cycle_internal( var_0 )
|
|
{
|
|
level.intensity_spawning_paused_count++;
|
|
wait( var_0 );
|
|
level.intensity_spawning_paused_count = int( max( 0, level.intensity_spawning_paused_count - 1 ) );
|
|
}
|
|
|
|
activate_spawn_event( var_0, var_1 )
|
|
{
|
|
if ( !isdefined( var_1 ) )
|
|
var_1 = 0;
|
|
|
|
var_2 = find_spawn_event( var_0 );
|
|
|
|
if ( !isdefined( var_2 ) )
|
|
{
|
|
if ( isdefined( level.current_cycle_num ) )
|
|
var_3 = level.current_cycle_num + 1;
|
|
else
|
|
var_3 = 0;
|
|
}
|
|
else
|
|
{
|
|
if ( var_1 )
|
|
{
|
|
level run_spawn_event( var_2, var_0 );
|
|
return;
|
|
}
|
|
|
|
level thread run_spawn_event( var_2, var_0 );
|
|
}
|
|
}
|
|
|
|
find_spawn_event( var_0 )
|
|
{
|
|
if ( isdefined( level.current_cycle ) )
|
|
{
|
|
foreach ( var_2 in level.current_cycle.spawn_events )
|
|
{
|
|
if ( var_2.activation_notify == var_0 )
|
|
return var_2;
|
|
}
|
|
}
|
|
|
|
foreach ( var_2 in level.cycle_data.generic_spawn_events )
|
|
{
|
|
if ( var_2.activation_notify == var_0 )
|
|
return var_2;
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
wait_for_spawn_event_delay()
|
|
{
|
|
while ( level.pending_meteor_spawns > 0 || level.pending_ground_spawns > 0 )
|
|
wait 0.05;
|
|
|
|
var_0 = level.cycle_data.spawn_event_min_activation_time + level.cycle_data.spawn_event_per_alien_activation_increase * get_current_agent_count();
|
|
var_0 = min( level.cycle_data.spawn_event_max_activation_increase, var_0 );
|
|
wait( var_0 );
|
|
}
|
|
|
|
run_spawn_event( var_0, var_1 )
|
|
{
|
|
level endon( "end_cycle" );
|
|
level endon( "nuke_went_off" );
|
|
level endon( "game_ended" );
|
|
|
|
if ( level.cycle_spawning_active )
|
|
level.intensity_spawning_paused_count++;
|
|
|
|
if ( var_0.allow_initial_delay )
|
|
wait_for_spawn_event_delay();
|
|
|
|
level thread spawn_event_time_limit_monitor( var_0.time_limit, var_0.activation_notify );
|
|
level thread process_spawn_event_spawning( var_0 );
|
|
common_scripts\utility::waittill_any( "spawn_event_complete" + var_0.activation_notify, "spawn_event_time_limit_reached" + var_0.activation_notify );
|
|
|
|
if ( level.cycle_spawning_active )
|
|
level.intensity_spawning_paused_count = int( max( 0, level.intensity_spawning_paused_count - 1 ) );
|
|
}
|
|
|
|
process_spawn_event_spawning( var_0 )
|
|
{
|
|
var_1 = [];
|
|
var_2 = randomint( var_0.id.size );
|
|
var_3 = var_0.id[var_2];
|
|
level.override_lane_index = 0;
|
|
|
|
foreach ( var_5 in level.spawn_event_waves[var_3] )
|
|
{
|
|
if ( var_5.spawn_delay > 0.0 )
|
|
wait( var_5.spawn_delay );
|
|
|
|
if ( isdefined( var_0.lanes ) )
|
|
var_6 = var_0.lanes;
|
|
else
|
|
var_6 = undefined;
|
|
|
|
var_5.types = get_spawn_event_types_array( var_5.entry_index );
|
|
|
|
if ( wave_has_delayed_spawn_type( var_5 ) )
|
|
var_7 = spawn_event_delayed_wave_spawn( var_5, var_0.activation_notify, var_6 );
|
|
else
|
|
var_7 = spawn_event_wave_spawn( var_5, var_0.activation_notify, var_6 );
|
|
|
|
var_1 = common_scripts\utility::array_combine( var_1, var_7 );
|
|
}
|
|
|
|
wait_for_all_aliens_killed( var_1, var_0.activation_notify );
|
|
level notify( "spawn_event_complete" + var_0.activation_notify );
|
|
}
|
|
|
|
wave_has_delayed_spawn_type( var_0 )
|
|
{
|
|
if ( wave_has_type( var_0, "minion" ) )
|
|
return 1;
|
|
|
|
if ( wave_has_type( var_0, "elite" ) )
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
wave_has_type( var_0, var_1 )
|
|
{
|
|
foreach ( var_3 in var_0.types )
|
|
{
|
|
if ( !isdefined( var_3.type_name ) )
|
|
continue;
|
|
|
|
if ( var_3.type_name == var_1 )
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
spawn_event_wave_spawn( var_0, var_1, var_2 )
|
|
{
|
|
var_3 = spawn_wave( var_0.types, "event", var_2 );
|
|
|
|
if ( var_0.blocking )
|
|
spawn_event_wave_block( var_3, var_1 );
|
|
|
|
return var_3;
|
|
}
|
|
|
|
spawn_event_wave_block( var_0, var_1 )
|
|
{
|
|
wait_for_all_aliens_killed( var_0, var_1 );
|
|
}
|
|
|
|
spawn_event_delayed_wave_spawn( var_0, var_1, var_2 )
|
|
{
|
|
var_3 = spawn_wave( var_0.types, "event", var_2 );
|
|
|
|
if ( level.pending_meteor_spawns > 0 )
|
|
level thread spawn_event_minion_wave_spawn();
|
|
|
|
if ( level.pending_ground_spawns > 0 )
|
|
level thread spawn_event_elite_wave_spawn();
|
|
|
|
while ( level.pending_meteor_spawns > 0 || level.pending_ground_spawns > 0 )
|
|
{
|
|
level waittill( "spawn_event_delayed_spawn_complete", var_4 );
|
|
var_3 = common_scripts\utility::array_combine( var_3, var_4 );
|
|
wait 0.05;
|
|
}
|
|
|
|
if ( var_0.blocking )
|
|
spawn_event_wave_block( var_3, var_1 );
|
|
|
|
return var_3;
|
|
}
|
|
|
|
spawn_event_minion_wave_spawn()
|
|
{
|
|
var_0 = [];
|
|
|
|
while ( level.pending_meteor_spawns > 0 )
|
|
{
|
|
level waittill( "meteor_aliens_spawned", var_1, var_2 );
|
|
var_0 = common_scripts\utility::array_combine( var_0, var_1 );
|
|
wait 0.05;
|
|
}
|
|
|
|
level notify( "spawn_event_delayed_spawn_complete", var_0 );
|
|
}
|
|
|
|
spawn_event_elite_wave_spawn()
|
|
{
|
|
var_0 = [];
|
|
|
|
while ( level.pending_ground_spawns > 0 )
|
|
{
|
|
level waittill( "ground_alien_spawned", var_1 );
|
|
var_0[var_0.size] = var_1;
|
|
wait 0.05;
|
|
}
|
|
|
|
level notify( "spawn_event_delayed_spawn_complete", var_0 );
|
|
}
|
|
|
|
spawn_event_time_limit_monitor( var_0, var_1 )
|
|
{
|
|
level endon( "spawn_event_complete" + var_1 );
|
|
wait( var_0 );
|
|
level notify( "spawn_event_time_limit_reached" + var_1 );
|
|
}
|
|
|
|
wait_for_all_aliens_killed( var_0, var_1 )
|
|
{
|
|
level endon( "spawn_event_complete" + var_1 );
|
|
|
|
for (;;)
|
|
{
|
|
wait 0.05;
|
|
var_2 = 0;
|
|
|
|
foreach ( var_4 in var_0 )
|
|
{
|
|
if ( isalive( var_4 ) )
|
|
{
|
|
var_2 = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( !var_2 )
|
|
break;
|
|
}
|
|
}
|
|
|
|
create_wave_types_array()
|
|
{
|
|
var_0 = 9;
|
|
var_1 = [];
|
|
|
|
for ( var_2 = 0; var_2 < var_0; var_2++ )
|
|
{
|
|
var_3 = spawnstruct();
|
|
var_3.type_name = undefined;
|
|
var_1[var_1.size] = var_3;
|
|
}
|
|
|
|
return var_1;
|
|
}
|
|
|
|
spawn_director_loop( var_0 )
|
|
{
|
|
level endon( "end_cycle" );
|
|
level endon( "nuke_went_off" );
|
|
level endon( "game_ended" );
|
|
level.spawn_node_traces_this_frame = 0;
|
|
level.spawn_node_traces_frame_time = gettime();
|
|
level.intensity_spawning_paused_count = 0;
|
|
level.current_cycle_num = var_0;
|
|
level.current_cycle = level.cycle_data.spawn_cycles[var_0];
|
|
cycle_begin_intensity_monitor();
|
|
level.pending_meteor_spawns = 0;
|
|
level.pending_ground_spawns = 0;
|
|
activate_current_lane_monitor();
|
|
|
|
if ( !isdefined( level.debug_spawn_director_active ) || !level.debug_spawn_director_active )
|
|
initial_spawn();
|
|
|
|
for (;;)
|
|
{
|
|
var_1 = respawn_threshold_monitor();
|
|
respawn( var_1 );
|
|
}
|
|
}
|
|
|
|
activate_current_lane_monitor()
|
|
{
|
|
if ( maps\mp\alien\_utility::is_chaos_mode() )
|
|
return;
|
|
|
|
level thread current_lane_monitor();
|
|
}
|
|
|
|
cycle_begin_intensity_monitor()
|
|
{
|
|
level.current_intensity_level = -1;
|
|
level.current_intensity = 0.0;
|
|
level thread intensity_monitor_update_loop();
|
|
}
|
|
|
|
intensity_monitor_update_loop()
|
|
{
|
|
level endon( "end_cycle" );
|
|
level endon( "nuke_went_off" );
|
|
level endon( "game_ended" );
|
|
var_0 = gettime();
|
|
|
|
for (;;)
|
|
{
|
|
var_1 = gettime();
|
|
|
|
if ( level.intensity_spawning_paused_count == 0 )
|
|
{
|
|
if ( isdefined( level.forced_current_intensity ) )
|
|
level.current_intensity = level.forced_current_intensity;
|
|
else if ( level.current_cycle.fullintensitytime == 0.0 )
|
|
level.current_intensity = 1.0;
|
|
else
|
|
{
|
|
var_2 = ( var_1 - var_0 ) / level.current_cycle.fullintensitytime;
|
|
level.current_intensity = clamp( level.current_intensity + var_2, 0.0, 1.0 );
|
|
}
|
|
|
|
var_0 = var_1;
|
|
var_3 = calculate_current_intensity_level();
|
|
|
|
if ( level.current_intensity_level != var_3 )
|
|
level notify( "intensity_level_changed" );
|
|
|
|
level.current_intensity_level = var_3;
|
|
}
|
|
else
|
|
var_0 = var_1;
|
|
|
|
wait 0.1;
|
|
}
|
|
}
|
|
|
|
current_lane_monitor()
|
|
{
|
|
level endon( "end_cycle" );
|
|
level endon( "nuke_went_off" );
|
|
level endon( "game_ended" );
|
|
level.cycle_data.current_lane = undefined;
|
|
|
|
for ( var_0 = get_current_encounter(); !isdefined( var_0 ); var_0 = get_current_encounter() )
|
|
wait 0.2;
|
|
|
|
if ( !isdefined( level.encounter_lanes[var_0] ) || level.encounter_lanes[var_0].size == 0 )
|
|
return;
|
|
|
|
for (;;)
|
|
{
|
|
var_1 = undefined;
|
|
|
|
foreach ( var_5, var_3 in level.encounter_lanes[var_0] )
|
|
{
|
|
var_4 = var_3.activation_time / level.current_cycle.fullintensitytime;
|
|
|
|
if ( var_4 > level.current_intensity )
|
|
break;
|
|
|
|
var_1 = var_5;
|
|
}
|
|
|
|
if ( isdefined( var_1 ) )
|
|
{
|
|
var_6 = level.encounter_lanes[var_0][var_1];
|
|
|
|
if ( !isdefined( level.cycle_data.current_lane ) || var_6 != level.cycle_data.current_lane )
|
|
{
|
|
level.cycle_data.current_lane = var_6;
|
|
play_lane_change_sound();
|
|
}
|
|
}
|
|
|
|
wait 0.5;
|
|
}
|
|
}
|
|
|
|
play_lane_change_sound()
|
|
{
|
|
var_0 = get_random_entry( level.cycle_data.current_lane.lanes );
|
|
var_1 = level.lanes[var_0][randomint( level.lanes[var_0].size )];
|
|
var_2 = level.cycle_data.spawner_list[var_1]["location"].origin;
|
|
playsoundatpos( var_2, "alien_distant" );
|
|
}
|
|
|
|
calculate_current_intensity_level()
|
|
{
|
|
for ( var_0 = 0; var_0 < level.current_cycle.intensitylevels.size; var_0++ )
|
|
{
|
|
if ( level.current_cycle.intensitylevels[var_0].intensitythreshold > level.current_intensity )
|
|
break;
|
|
}
|
|
|
|
return var_0 - 1;
|
|
}
|
|
|
|
initial_spawn()
|
|
{
|
|
while ( level.current_intensity_level < 0 )
|
|
wait 0.05;
|
|
|
|
var_0 = get_current_wave_ai_types();
|
|
spawn_wave( var_0, "spawn" );
|
|
}
|
|
|
|
get_current_wave_ai_types()
|
|
{
|
|
foreach ( var_1 in level.cycle_data.current_wave_types )
|
|
{
|
|
var_1.type_name = undefined;
|
|
var_1.max_of_type = undefined;
|
|
var_1.min_spawned = undefined;
|
|
var_1.max_spawned = undefined;
|
|
}
|
|
|
|
var_3 = level.current_cycle.intensitylevels[level.current_intensity_level].tableindex;
|
|
get_types_array( var_3 );
|
|
level.cycle_data.current_respawn_threshold = get_respawn_threshold_by_index( var_3 );
|
|
level.cycle_data.current_respawn_delay = get_respawn_delay_by_index( var_3 );
|
|
return level.cycle_data.current_wave_types;
|
|
}
|
|
|
|
respawn( var_0 )
|
|
{
|
|
if ( isdefined( var_0 ) && var_0 )
|
|
{
|
|
var_1 = level.cycle_data.current_wave_types;
|
|
var_2 = "respawn";
|
|
}
|
|
else
|
|
{
|
|
var_1 = get_current_wave_ai_types();
|
|
var_2 = "spawn";
|
|
}
|
|
|
|
spawn_wave( var_1, var_2 );
|
|
}
|
|
|
|
spawn_wave( var_0, var_1, var_2 )
|
|
{
|
|
var_3 = [];
|
|
|
|
for ( var_4 = 0; var_4 < var_0.size; var_4++ )
|
|
{
|
|
if ( isdefined( var_0[var_4].type_name ) )
|
|
var_3 = common_scripts\utility::array_combine( spawn_type( var_0[var_4], var_1, var_2 ), var_3 );
|
|
}
|
|
|
|
return var_3;
|
|
}
|
|
|
|
respawn_threshold_monitor()
|
|
{
|
|
level endon( "end cycle" );
|
|
level endon( "intensity_level_changed" );
|
|
|
|
for (;;)
|
|
{
|
|
if ( level.current_intensity_level >= 0 && level.intensity_spawning_paused_count == 0 )
|
|
{
|
|
if ( isdefined( level.cycle_data.current_respawn_threshold ) && level.cycle_data.current_respawn_threshold >= 0 )
|
|
{
|
|
var_0 = get_current_agent_count();
|
|
var_1 = get_scaled_alien_amount( level.cycle_data.current_respawn_threshold );
|
|
|
|
if ( var_0 <= var_1 )
|
|
break;
|
|
}
|
|
}
|
|
|
|
wait 0.1;
|
|
}
|
|
|
|
if ( isdefined( level.cycle_data.current_respawn_delay ) )
|
|
{
|
|
if ( level.current_intensity_level >= 0 && level.cycle_data.current_respawn_delay >= 0 )
|
|
wait( level.cycle_data.current_respawn_delay * get_current_spawn_count_multiplier() );
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
get_current_spawn_count_multiplier()
|
|
{
|
|
var_0 = level.base_player_count_multiplier + level.additional_player_count_multiplier * ( level.players.size - 1 );
|
|
|
|
if ( maps\mp\alien\_utility::is_hardcore_mode() )
|
|
var_0 = var_0 * level.hardcore_spawn_multiplier;
|
|
|
|
return var_0;
|
|
}
|
|
|
|
spawn_type_vo_monitor()
|
|
{
|
|
level endon( "game_ended" );
|
|
level endon( "nuke_went_off" );
|
|
var_0 = gettime();
|
|
var_1 = var_0;
|
|
var_2 = var_0;
|
|
var_3 = 40000;
|
|
var_4 = 30000;
|
|
|
|
for (;;)
|
|
{
|
|
level waittill( "spawned_alien", var_5 );
|
|
|
|
if ( !isdefined( var_5.alien_type ) )
|
|
continue;
|
|
|
|
if ( common_scripts\utility::flag_exist( "escape_conditions_met" ) && common_scripts\utility::flag( "escape_conditions_met" ) )
|
|
return;
|
|
|
|
switch ( var_5.alien_type )
|
|
{
|
|
case "spitter":
|
|
var_0 = gettime();
|
|
|
|
if ( var_0 >= var_1 )
|
|
{
|
|
level thread maps\mp\alien\_music_and_dialog::playvoforspitterspawn( var_5 );
|
|
var_1 = var_0 + var_3;
|
|
}
|
|
|
|
break;
|
|
case "elite":
|
|
var_0 = gettime();
|
|
|
|
if ( var_0 >= var_2 )
|
|
{
|
|
level thread maps\mp\alien\_music_and_dialog::playvoforqueenspawn( var_5 );
|
|
var_2 = var_0 + var_4;
|
|
}
|
|
|
|
break;
|
|
case "seeder":
|
|
level notify( "dlc_vo_notify", "inbound_seeder", var_5 );
|
|
break;
|
|
case "brute":
|
|
level notify( "dlc_vo_notify", "inbound_brute", var_5 );
|
|
break;
|
|
case "mammoth":
|
|
level notify( "dlc_vo_notify", "inbound_mammoth", var_5 );
|
|
break;
|
|
case "gargoyle":
|
|
level notify( "dlc_vo_notify", "inbound_gargoyle", var_5 );
|
|
break;
|
|
case "bomber":
|
|
level notify( "dlc_vo_notify", "inbound_bomber", var_5 );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
get_scaled_alien_amount( var_0 )
|
|
{
|
|
var_1 = var_0 * get_current_spawn_count_multiplier();
|
|
return max( 1, int( var_1 + 0.5 ) );
|
|
}
|
|
|
|
get_modified_alien_amount( var_0, var_1, var_2 )
|
|
{
|
|
var_3 = get_scaled_alien_amount( var_0 );
|
|
return get_max_type_count( var_1, var_3 );
|
|
}
|
|
|
|
spawn_type( var_0, var_1, var_2 )
|
|
{
|
|
if ( !isdefined( var_0.max_spawned ) )
|
|
var_3 = var_0.min_spawned;
|
|
else
|
|
var_3 = randomintrange( var_0.min_spawned, var_0.max_spawned );
|
|
|
|
var_4 = get_modified_alien_amount( var_3, var_0, var_1 );
|
|
var_5 = [];
|
|
|
|
if ( !isdefined( level.cycle_data.current_lane ) && !isdefined( level.cycle_data.non_lane_spawn_started ) )
|
|
{
|
|
level thread maps\mp\alien\_music_and_dialog::play2dspawnsound();
|
|
level.cycle_data.non_lane_spawn_started = 1;
|
|
}
|
|
|
|
switch ( var_0.type_name )
|
|
{
|
|
case "minion":
|
|
spawn_minions( var_4 );
|
|
break;
|
|
case "elite":
|
|
spawn_elite( var_4 );
|
|
break;
|
|
default:
|
|
var_5 = spawn_aliens( var_4, var_0.type_name, var_2 );
|
|
break;
|
|
}
|
|
|
|
return var_5;
|
|
}
|
|
|
|
get_max_alien_count()
|
|
{
|
|
return level.cycle_data.max_alien_count;
|
|
}
|
|
|
|
get_max_type_count( var_0, var_1 )
|
|
{
|
|
if ( !isdefined( level.current_cycle ) )
|
|
return var_1;
|
|
|
|
var_2 = get_translated_ai_type( var_0.type_name );
|
|
|
|
if ( isdefined( var_0.max_of_type ) )
|
|
{
|
|
if ( var_0.max_of_type <= 0 )
|
|
level.current_cycle.type_max_counts[var_2] = undefined;
|
|
else
|
|
level.current_cycle.type_max_counts[var_2] = var_0.max_of_type;
|
|
}
|
|
|
|
if ( !isdefined( level.current_cycle.type_max_counts[var_2] ) )
|
|
return var_1;
|
|
|
|
var_3 = get_scaled_alien_amount( level.current_cycle.type_max_counts[var_2] );
|
|
var_3 = max( 0, var_3 - get_current_agent_count_of_type( var_2 ) );
|
|
return min( var_1, var_3 );
|
|
}
|
|
|
|
at_max_alien_count()
|
|
{
|
|
return get_current_agent_count() >= get_max_alien_count();
|
|
}
|
|
|
|
get_translated_ai_type( var_0 )
|
|
{
|
|
switch ( var_0 )
|
|
{
|
|
case "minion_nometeor":
|
|
return "minion";
|
|
}
|
|
|
|
return var_0;
|
|
}
|
|
|
|
spawn_aliens( var_0, var_1, var_2 )
|
|
{
|
|
var_1 = get_translated_ai_type( var_1 );
|
|
var_3 = [];
|
|
|
|
for ( var_4 = 0; var_4 < var_0; var_4++ )
|
|
{
|
|
if ( at_max_alien_count() )
|
|
break;
|
|
|
|
var_6 = undefined;
|
|
|
|
if ( maps\mp\alien\_utility::is_chaos_mode() )
|
|
var_6 = ::sort_player_view_direction;
|
|
|
|
var_7 = spawn_alien( var_1, var_2, undefined, var_6 );
|
|
var_3[var_3.size] = var_7;
|
|
wait( level.cycle_data.min_spawn_interval );
|
|
}
|
|
|
|
return var_3;
|
|
}
|
|
|
|
spawn_minions( var_0 )
|
|
{
|
|
level thread spawn_meteor_aliens( var_0, "minion" );
|
|
wait( level.cycle_data.min_spawn_interval );
|
|
}
|
|
|
|
spawn_elite( var_0 )
|
|
{
|
|
level thread spawn_ground_aliens( var_0, "elite", ::elite_monitor );
|
|
wait( level.cycle_data.min_spawn_interval );
|
|
}
|
|
|
|
elite_monitor()
|
|
{
|
|
if ( !isdefined( level.cycle_data.elite_count ) || level.cycle_data.elite_count == 0 )
|
|
{
|
|
level thread maps\mp\alien\_music_and_dialog::handlefirstelitearrival( self );
|
|
level.cycle_data.elite_count = 1;
|
|
}
|
|
else
|
|
level.cycle_data.elite_count++;
|
|
|
|
self waittill( "death" );
|
|
level.cycle_data.elite_count--;
|
|
|
|
if ( level.cycle_data.elite_count == 0 )
|
|
level thread maps\mp\alien\_music_and_dialog::handlelastelitedeath( self );
|
|
}
|
|
|
|
is_spawn_debug_info_requested()
|
|
{
|
|
return getdvarint( "scr_alienspawninfo", 0 ) == 1 || getdvarint( "scr_alienspawneventinfo" ) == 1;
|
|
}
|
|
|
|
spawn_meteor_aliens( var_0, var_1 )
|
|
{
|
|
level endon( "game_ended" );
|
|
level endon( "nuke_went_off" );
|
|
|
|
if ( var_0 >= 9 )
|
|
var_2 = int( var_0 / 3 );
|
|
else
|
|
var_2 = 4;
|
|
|
|
level.pending_meteor_spawns = level.pending_meteor_spawns + var_0;
|
|
|
|
while ( var_0 > 0 )
|
|
{
|
|
var_3 = var_2;
|
|
|
|
if ( var_0 < var_2 )
|
|
var_3 = var_0;
|
|
|
|
var_4 = level thread maps\mp\alien\_spawnlogic::spawn_alien_meteoroid( var_1, var_3 );
|
|
|
|
if ( isdefined( var_4 ) )
|
|
{
|
|
level.pending_meteor_spawns = level.pending_meteor_spawns - var_0;
|
|
return;
|
|
}
|
|
|
|
var_0 = var_0 - var_3;
|
|
wait( randomintrange( 5, 10 ) );
|
|
level thread maps\mp\alien\_music_and_dialog::playvoforminions();
|
|
}
|
|
}
|
|
|
|
spawn_ground_aliens( var_0, var_1, var_2 )
|
|
{
|
|
level endon( "game_ended" );
|
|
level endon( "nuke_went_off" );
|
|
var_3 = 2.0;
|
|
var_4 = 3.5;
|
|
|
|
while ( var_0 > 0 )
|
|
{
|
|
var_5 = level thread spawn_ground_alien( var_1, 1, var_2 );
|
|
|
|
if ( isdefined( var_5 ) )
|
|
return;
|
|
|
|
level.pending_ground_spawns++;
|
|
var_0 = var_0 - 1;
|
|
wait( randomfloatrange( var_3, var_4 ) );
|
|
}
|
|
}
|
|
|
|
spawn_ground_alien( var_0, var_1, var_2 )
|
|
{
|
|
var_3 = 10000;
|
|
var_4 = [];
|
|
var_5 = spawn_alien( var_0, var_4, var_3, ::sort_closest_to_players );
|
|
var_5 thread [[ var_2 ]]();
|
|
level notify( "ground_alien_spawned", var_5 );
|
|
}
|
|
|
|
monitor_meteor_spawn()
|
|
{
|
|
level endon( "game_ended" );
|
|
level endon( "nuke_went_off" );
|
|
|
|
for (;;)
|
|
{
|
|
level waittill( "meteor_aliens_spawned", var_0, var_1 );
|
|
level.pending_meteor_spawns = level.pending_meteor_spawns - var_1;
|
|
|
|
if ( level.pending_meteor_spawns < 0 )
|
|
level.pending_meteor_spawns = 0;
|
|
}
|
|
}
|
|
|
|
monitor_ground_spawn()
|
|
{
|
|
level endon( "game_ended" );
|
|
level endon( "nuke_went_off" );
|
|
|
|
for (;;)
|
|
{
|
|
level waittill( "ground_alien_spawned", var_0 );
|
|
var_1 = var_0 maps\mp\alien\_utility::get_alien_type();
|
|
|
|
if ( !isalive( var_0 ) )
|
|
continue;
|
|
|
|
level.pending_ground_spawns--;
|
|
|
|
if ( level.pending_ground_spawns < 0 )
|
|
level.pending_ground_spawns = 0;
|
|
}
|
|
}
|
|
|
|
get_current_agent_count( var_0, var_1, var_2 )
|
|
{
|
|
var_3 = maps\mp\agents\_agent_utility::getnumactiveagents();
|
|
|
|
if ( !isdefined( var_0 ) || !var_0 )
|
|
var_3 = var_3 + level.pending_meteor_spawns;
|
|
|
|
if ( !isdefined( var_1 ) || !var_1 )
|
|
var_3 = var_3 + level.pending_ground_spawns;
|
|
|
|
if ( !isdefined( var_2 ) || !var_2 )
|
|
var_3 = var_3 + level.pending_custom_spawns;
|
|
|
|
return var_3;
|
|
}
|
|
|
|
get_current_agent_count_of_type( var_0 )
|
|
{
|
|
var_1 = maps\mp\agents\_agent_utility::getactiveagentsoftype( "alien" );
|
|
var_2 = 0;
|
|
|
|
foreach ( var_4 in var_1 )
|
|
{
|
|
if ( isdefined( var_4.pet ) && var_4.pet )
|
|
continue;
|
|
|
|
if ( var_4 maps\mp\alien\_utility::get_alien_type() == var_0 )
|
|
var_2++;
|
|
}
|
|
|
|
return var_2;
|
|
}
|
|
|
|
spawn_alien( var_0, var_1, var_2, var_3 )
|
|
{
|
|
var_4 = find_safe_spawn_point_info( var_0, var_1, var_2, var_3 );
|
|
var_5 = var_4["node"];
|
|
var_6 = 0;
|
|
|
|
if ( var_0 == "spitter" && isdefined( level.hive_heli ) && level.hive_heli.health > 0 && threatbiasgroupexists( "spitters" ) )
|
|
{
|
|
var_7 = 0;
|
|
var_8 = 0;
|
|
|
|
foreach ( var_10 in level.agentarray )
|
|
{
|
|
if ( !isdefined( var_10.isactive ) || !var_10.isactive || !isalive( var_10 ) || !isdefined( var_10.alien_type ) || var_10.alien_type != "spitter" )
|
|
continue;
|
|
|
|
if ( var_10 getthreatbiasgroup() == "spitters" )
|
|
{
|
|
var_8++;
|
|
continue;
|
|
}
|
|
|
|
var_7++;
|
|
}
|
|
|
|
var_12 = int( max( 1, var_8 + var_7 ) );
|
|
level.spitters_against_players_ratio = var_7 / var_12;
|
|
var_13 = 0;
|
|
|
|
foreach ( var_15 in level.players )
|
|
var_13 = var_13 + distance2d( var_15.origin, level.hive_heli.origin );
|
|
|
|
var_17 = var_13 / int( min( 1, level.players.size ) );
|
|
var_18 = 0.32;
|
|
|
|
if ( var_17 > 1500 )
|
|
var_18 = 0.1;
|
|
|
|
if ( level.spitters_against_players_ratio >= var_18 )
|
|
var_6 = 1;
|
|
}
|
|
|
|
var_19 = process_intro_vignette_ai_type( var_0 );
|
|
|
|
if ( isdefined( var_5.script_noteworthy ) )
|
|
var_20 = level.cycle_data.spawn_node_info[var_5.script_noteworthy].vignetteinfo[var_19];
|
|
else
|
|
var_20 = undefined;
|
|
|
|
var_21 = process_spawn( var_0, var_5, var_20 );
|
|
|
|
if ( ( var_0 == "spitter" || var_0 == "seeder" ) && isdefined( level.hive_heli ) && level.hive_heli.health > 0 && threatbiasgroupexists( "spitters" ) )
|
|
{
|
|
if ( var_6 )
|
|
var_21 maps\mp\alien\_spawnlogic::make_spitter_attack_chopper( 1 );
|
|
else
|
|
var_21 maps\mp\alien\_spawnlogic::make_spitter_attack_chopper( 0 );
|
|
}
|
|
|
|
if ( ( var_0 == "spitter" || var_0 == "seeder" || var_0 == "gargoyle" ) && common_scripts\utility::flag_exist( "player_using_vanguard" ) && common_scripts\utility::flag( "player_using_vanguard" ) && threatbiasgroupexists( "spitters" ) )
|
|
{
|
|
var_21 setthreatbiasgroup( "spitters" );
|
|
var_21.favoriteenemy = level.alien_vanguard;
|
|
}
|
|
|
|
if ( isdefined( var_5.script_noteworthy ) )
|
|
{
|
|
if ( issubstr( var_5.script_noteworthy, "vent" ) )
|
|
level notify( "dlc_vo_notify", "direction_vo", "spawn_vent" );
|
|
|
|
if ( issubstr( var_5.script_noteworthy, "duct" ) )
|
|
level notify( "dlc_vo_notify", "direction_vo", "spawn_vent" );
|
|
|
|
if ( issubstr( var_5.script_noteworthy, "grate" ) )
|
|
level notify( "dlc_vo_notify", "direction_vo", "spawn_grate" );
|
|
}
|
|
|
|
level notify( "spawned_alien", var_21 );
|
|
return var_21;
|
|
}
|
|
|
|
process_intro_vignette_ai_type( var_0 )
|
|
{
|
|
switch ( var_0 )
|
|
{
|
|
case "leper":
|
|
case "locust":
|
|
return "brute";
|
|
case "mammoth":
|
|
return "elite";
|
|
}
|
|
|
|
return var_0;
|
|
}
|
|
|
|
process_spawn( var_0, var_1, var_2 )
|
|
{
|
|
var_3 = ( 0, 0, 0 );
|
|
|
|
if ( isdefined( var_1.angles ) )
|
|
var_3 = var_1.angles;
|
|
|
|
var_1.last_used_time = gettime();
|
|
var_4 = "wave " + var_0;
|
|
var_5 = maps\mp\gametypes\aliens::addalienagent( "axis", var_1.origin, var_3, var_4, var_2 );
|
|
return var_5;
|
|
}
|
|
|
|
find_safe_spawn_point_info( var_0, var_1, var_2, var_3 )
|
|
{
|
|
if ( should_lane_spawn( var_1, var_0 ) )
|
|
return find_lane_spawn_node( var_1 );
|
|
|
|
var_4 = get_current_player_volumes();
|
|
|
|
if ( var_4.size == 0 )
|
|
{
|
|
var_5 = find_random_spawn_node( level.cycle_data.spawner_list, var_0, var_2, ::filter_spawn_point_by_distance_from_player, undefined, var_3 );
|
|
return var_5;
|
|
}
|
|
else if ( var_4.size == 1 )
|
|
{
|
|
foreach ( var_8, var_7 in var_4 )
|
|
{
|
|
if ( level.cycle_data.spawn_zones[var_8].spawn_nodes.size == 0 )
|
|
continue;
|
|
|
|
var_5 = find_random_spawn_node( level.cycle_data.spawn_zones[var_8].spawn_nodes, var_0, var_2, undefined, undefined, var_3 );
|
|
return var_5;
|
|
}
|
|
}
|
|
|
|
return find_safe_spawn_spot_with_volumes( var_4, var_0, var_2, var_3 );
|
|
}
|
|
|
|
get_current_encounter()
|
|
{
|
|
return level.encounter_name;
|
|
}
|
|
|
|
should_lane_spawn( var_0, var_1 )
|
|
{
|
|
var_2 = 1024;
|
|
|
|
if ( maps\mp\alien\_utility::is_chaos_mode() )
|
|
return 0;
|
|
|
|
if ( isdefined( var_0 ) && var_0.size == 0 )
|
|
return 0;
|
|
|
|
if ( !can_spawn_at_any_node( var_1 ) )
|
|
return 0;
|
|
|
|
if ( isdefined( level.blocker_hive_active ) && level.blocker_hive_active )
|
|
return 1;
|
|
|
|
var_3 = get_current_drill_state();
|
|
|
|
if ( !isdefined( var_0 ) )
|
|
{
|
|
if ( !isdefined( level.cycle_data.current_lane ) )
|
|
return 0;
|
|
|
|
if ( var_3 == "idle" )
|
|
return 0;
|
|
}
|
|
|
|
if ( var_3 == "offline" )
|
|
{
|
|
var_4 = 0;
|
|
var_5 = 0;
|
|
|
|
foreach ( var_7 in level.players )
|
|
{
|
|
if ( isdefined( var_7 ) && isalive( var_7 ) )
|
|
{
|
|
var_5++;
|
|
var_4 = var_4 + distance2d( var_7.origin, level.drill.origin );
|
|
}
|
|
}
|
|
|
|
if ( var_5 > 0 )
|
|
{
|
|
if ( var_4 / var_5 > var_2 )
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
get_current_drill_state()
|
|
{
|
|
if ( !isdefined( level.drill ) || !isdefined( level.drill.state ) )
|
|
return "undefined";
|
|
|
|
return level.drill.state;
|
|
}
|
|
|
|
get_override_lane_entry( var_0 )
|
|
{
|
|
if ( !isdefined( level.override_lane_index ) )
|
|
return get_random_entry( var_0 );
|
|
|
|
if ( level.override_lane_index >= var_0.size )
|
|
level.override_lane_index = 0;
|
|
|
|
var_1 = level.override_lane_index;
|
|
level.override_lane_index++;
|
|
return var_0[var_1];
|
|
}
|
|
|
|
find_lane_spawn_node( var_0 )
|
|
{
|
|
if ( isdefined( var_0 ) && var_0.size > 0 )
|
|
{
|
|
var_1 = get_random_entry( var_0 );
|
|
var_2 = get_override_lane_entry( level.lanes[var_1] );
|
|
}
|
|
else
|
|
{
|
|
var_1 = get_random_entry( level.cycle_data.current_lane.lanes );
|
|
var_2 = level.lanes[var_1][randomint( level.lanes[var_1].size )];
|
|
}
|
|
|
|
var_3 = [];
|
|
var_3["node"] = level.cycle_data.spawner_list[var_2]["location"];
|
|
var_3["validNode"] = 1;
|
|
return var_3;
|
|
}
|
|
|
|
get_current_encounter_lane_index()
|
|
{
|
|
var_0 = undefined;
|
|
var_1 = get_current_encounter();
|
|
|
|
if ( !isdefined( var_1 ) )
|
|
return undefined;
|
|
|
|
foreach ( var_5, var_3 in level.encounter_lanes[var_1] )
|
|
{
|
|
var_4 = var_3.activation_time / level.current_cycle.fullintensitytime;
|
|
|
|
if ( var_4 > level.current_intensity )
|
|
break;
|
|
|
|
var_0 = var_5;
|
|
}
|
|
|
|
return level.encounter_lanes[var_1][var_0];
|
|
}
|
|
|
|
get_random_entry( var_0 )
|
|
{
|
|
var_1 = -1;
|
|
var_2 = randomint( var_0.size );
|
|
|
|
foreach ( var_5, var_4 in var_0 )
|
|
{
|
|
var_1++;
|
|
|
|
if ( var_1 == var_2 )
|
|
return var_0[var_5];
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
filter_spawn_point_by_distance_from_player( var_0, var_1 )
|
|
{
|
|
if ( var_1 == "elite" )
|
|
return 1;
|
|
|
|
var_2 = level.players[0].origin;
|
|
return distancesquared( var_2, var_0.origin ) > level.cycle_data.safe_spawn_distance_sq;
|
|
}
|
|
|
|
sort_closest_to_players( var_0 )
|
|
{
|
|
return sort_array( var_0, ::sort_closest_distance_to_players_func, 0 );
|
|
}
|
|
|
|
sort_player_view_direction( var_0 )
|
|
{
|
|
var_1 = level.players[randomint( level.players.size )];
|
|
var_2 = anglestoforward( var_1 getplayerangles() );
|
|
return sort_array( var_0, ::sort_player_view_direction_func, 0, [ var_1.origin, var_2 ] );
|
|
}
|
|
|
|
find_random_spawn_node( var_0, var_1, var_2, var_3, var_4, var_5 )
|
|
{
|
|
if ( isdefined( var_2 ) )
|
|
var_6 = var_2;
|
|
else
|
|
var_6 = level.cycle_data.spawn_point_last_used_duration;
|
|
|
|
if ( !isdefined( var_5 ) )
|
|
var_5 = common_scripts\utility::array_randomize;
|
|
|
|
var_0 = [[ var_5 ]]( var_0 );
|
|
var_7 = 0;
|
|
var_8 = randomfloatrange( var_6 * 0.5, var_6 * 0.75 );
|
|
var_9 = 0.0;
|
|
var_10 = 0;
|
|
|
|
for ( var_11 = 0; var_11 < var_0.size; var_11++ )
|
|
{
|
|
var_12 = var_0[var_11]["location"];
|
|
|
|
if ( isdefined( var_3 ) && !passes_spawn_node_filter( var_12, var_1, var_3, var_4 ) )
|
|
continue;
|
|
|
|
if ( isdefined( var_0[var_11]["location"].script_linkname ) )
|
|
var_13 = var_0[var_11]["location"].script_linkname;
|
|
else
|
|
var_13 = undefined;
|
|
|
|
if ( !is_valid_spawn_node_for_type( var_0[var_11]["types"], var_1, var_13 ) )
|
|
continue;
|
|
|
|
if ( !isdefined( var_12.last_used_time ) )
|
|
{
|
|
var_10 = 1;
|
|
var_7 = var_11;
|
|
break;
|
|
}
|
|
|
|
var_14 = gettime() - var_12.last_used_time;
|
|
|
|
if ( var_14 > var_8 )
|
|
{
|
|
var_10 = 1;
|
|
var_7 = var_11;
|
|
break;
|
|
}
|
|
|
|
if ( var_14 > var_9 )
|
|
{
|
|
var_9 = var_14;
|
|
var_7 = var_11;
|
|
}
|
|
}
|
|
|
|
var_15 = [];
|
|
var_15["node"] = var_0[var_7]["location"];
|
|
var_15["validNode"] = var_10;
|
|
return var_15;
|
|
}
|
|
|
|
is_valid_spawn_node_for_type( var_0, var_1, var_2 )
|
|
{
|
|
if ( var_0.size == 0 )
|
|
return can_spawn_at_any_node( var_1 );
|
|
|
|
foreach ( var_4 in var_0 )
|
|
{
|
|
if ( var_4 == var_1 )
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
can_spawn_at_any_node( var_0 )
|
|
{
|
|
if ( isdefined( level.dlc_alien_type_node_match_override_func ) )
|
|
{
|
|
var_1 = self [[ level.dlc_alien_type_node_match_override_func ]]( var_0 );
|
|
|
|
if ( isdefined( var_1 ) )
|
|
return var_1;
|
|
}
|
|
|
|
switch ( var_0 )
|
|
{
|
|
case "elite":
|
|
return 0;
|
|
default:
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
passes_spawn_node_filter( var_0, var_1, var_2, var_3 )
|
|
{
|
|
if ( isdefined( var_3 ) )
|
|
return [[ var_2 ]]( var_0, var_1, var_3 );
|
|
|
|
return [[ var_2 ]]( var_0, var_1 );
|
|
}
|
|
|
|
find_safe_spawn_spot_with_volumes( var_0, var_1, var_2, var_3 )
|
|
{
|
|
var_4 = score_and_sort_spawn_zones( var_0 );
|
|
|
|
foreach ( var_6 in var_4 )
|
|
{
|
|
if ( level.cycle_data.spawn_zones[var_6.name].spawn_nodes.size == 0 )
|
|
continue;
|
|
|
|
var_7 = [];
|
|
|
|
foreach ( var_10, var_9 in var_0 )
|
|
{
|
|
if ( var_10 != var_6.name )
|
|
var_7 = common_scripts\utility::array_combine( var_7, var_9.players );
|
|
}
|
|
|
|
var_11 = find_random_spawn_node( level.cycle_data.spawn_zones[var_6.name].spawn_nodes, var_1, var_2, ::is_safe_spawn_location, var_7, var_3 );
|
|
|
|
if ( var_11["validNode"] )
|
|
return var_11;
|
|
}
|
|
|
|
var_11 = find_random_spawn_node( level.cycle_data.spawner_list, var_1, var_2, ::filter_spawn_point_by_distance_from_player, undefined, var_3 );
|
|
return var_11;
|
|
}
|
|
|
|
score_and_sort_spawn_zones( var_0 )
|
|
{
|
|
var_1 = calculate_player_proximity_scores();
|
|
|
|
foreach ( var_3 in var_0 )
|
|
{
|
|
var_4 = 0.0;
|
|
|
|
foreach ( var_6 in var_3.players )
|
|
{
|
|
var_4 = var_4 + level.cycle_data.player_in_zone_score_modifier;
|
|
|
|
if ( isdefined( var_6.current_attackers ) )
|
|
var_4 = var_4 - var_6.current_attackers.size * level.cycle_data.current_attacker_in_zone_score_modifier;
|
|
|
|
if ( isdefined( var_1[var_6.name] ) && var_1[var_6.name] > level.cycle_data.group_break_away_distance_sq )
|
|
var_4 = var_4 + min( level.cycle_data.max_break_away_zone_score_increase, var_1[var_6.name] / level.cycle_data.group_break_away_distance_sq );
|
|
}
|
|
|
|
var_4 = var_4 - get_number_of_recently_used_spawn_points_in_zone( var_3 ) * level.cycle_data.recently_used_spawn_zone_score_modifier;
|
|
var_3.zone_score = var_4;
|
|
}
|
|
|
|
var_9 = [];
|
|
|
|
foreach ( var_3 in var_0 )
|
|
var_9[var_9.size] = var_3;
|
|
|
|
return sort_array( var_9, ::sort_zone_score_func );
|
|
}
|
|
|
|
calculate_player_proximity_scores()
|
|
{
|
|
var_0 = [];
|
|
|
|
if ( level.players.size <= 2 )
|
|
return var_0;
|
|
|
|
for ( var_1 = 0; var_1 < level.players.size; var_1++ )
|
|
{
|
|
var_2 = level.players[var_1].name;
|
|
|
|
if ( !isdefined( var_0[var_2] ) )
|
|
var_0[var_2] = 100000000.0;
|
|
|
|
for ( var_3 = var_1 + 1; var_3 < level.players.size; var_3++ )
|
|
{
|
|
var_4 = distancesquared( level.players[var_1].origin, level.players[var_3].origin );
|
|
|
|
if ( var_4 < var_0[var_2] )
|
|
var_0[var_2] = var_4;
|
|
|
|
var_5 = level.players[var_3].name;
|
|
|
|
if ( !isdefined( var_0[var_5] ) || var_4 < var_0[var_5] )
|
|
var_0[var_5] = var_4;
|
|
}
|
|
}
|
|
|
|
return var_0;
|
|
}
|
|
|
|
get_number_of_recently_used_spawn_points_in_zone( var_0 )
|
|
{
|
|
var_1 = 0;
|
|
var_2 = gettime();
|
|
|
|
for ( var_3 = 0; var_3 < level.cycle_data.spawn_zones[var_0.name].spawn_nodes.size; var_3++ )
|
|
{
|
|
var_4 = level.cycle_data.spawn_zones[var_0.name].spawn_nodes[var_3]["location"];
|
|
|
|
if ( isdefined( var_4.last_used_time ) )
|
|
{
|
|
var_5 = var_2 - var_4.last_used_time;
|
|
|
|
if ( var_5 < level.cycle_data.spawn_point_last_used_duration )
|
|
var_1++;
|
|
}
|
|
}
|
|
|
|
return var_1;
|
|
}
|
|
|
|
sort_zone_score_func( var_0, var_1, var_2 )
|
|
{
|
|
return var_0.zone_score > var_1.zone_score;
|
|
}
|
|
|
|
is_safe_spawn_location( var_0, var_1, var_2 )
|
|
{
|
|
if ( var_1 == "elite" )
|
|
return 1;
|
|
|
|
foreach ( var_4 in var_2 )
|
|
{
|
|
if ( distancesquared( var_0.origin, var_4.origin ) > level.cycle_data.safe_spawn_distance_sq )
|
|
continue;
|
|
|
|
if ( has_line_of_sight( var_0.origin, var_4.origin ) )
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
has_line_of_sight( var_0, var_1 )
|
|
{
|
|
while ( max_traces_reached() )
|
|
wait 0.05;
|
|
|
|
level.spawn_node_traces_this_frame++;
|
|
return bullettracepassed( var_0, var_1, 0, undefined );
|
|
}
|
|
|
|
get_current_player_volumes()
|
|
{
|
|
if ( isdefined( level.dlc_get_current_player_volumes_override_func ) )
|
|
return level [[ level.dlc_get_current_player_volumes_override_func ]]();
|
|
|
|
var_0 = [];
|
|
var_1 = [];
|
|
|
|
foreach ( var_3 in level.cycle_data.spawn_zones )
|
|
var_0[var_0.size] = var_3.volume;
|
|
|
|
foreach ( var_6 in level.players )
|
|
{
|
|
if ( !isalive( var_6 ) || var_6.sessionstate == "spectator" )
|
|
continue;
|
|
|
|
var_7 = var_6 getistouchingentities( var_0 );
|
|
|
|
foreach ( var_9 in var_7 )
|
|
{
|
|
var_10 = 0;
|
|
|
|
if ( !isdefined( var_1[var_9.script_linkname] ) )
|
|
{
|
|
var_11 = var_9.script_linkname;
|
|
var_1[var_11] = spawnstruct();
|
|
var_1[var_11].players = [];
|
|
var_1[var_11].origin = var_9.origin;
|
|
var_1[var_11].name = var_11;
|
|
}
|
|
|
|
var_10 = var_1[var_9.script_linkname].players.size;
|
|
var_1[var_9.script_linkname].players[var_10] = var_6;
|
|
}
|
|
}
|
|
|
|
return var_1;
|
|
}
|
|
|
|
max_traces_reached()
|
|
{
|
|
var_0 = 5;
|
|
|
|
if ( gettime() > level.spawn_node_traces_frame_time )
|
|
{
|
|
level.spawn_node_traces_frame_time = gettime();
|
|
level.spawn_node_traces_this_frame = 0;
|
|
}
|
|
|
|
return level.spawn_node_traces_this_frame >= var_0;
|
|
}
|
|
|
|
load_cycle_scalars_from_table( var_0 )
|
|
{
|
|
var_0.cycle_scalars = [];
|
|
|
|
if ( maps\mp\alien\_utility::is_casual_mode() )
|
|
{
|
|
level.cycle_health_scalar = level.casual_health_scalar;
|
|
level.cycle_damage_scalar = level.casual_damage_scalar;
|
|
level.cycle_reward_scalar = level.casual_reward_scalar;
|
|
level.cycle_score_scalar = level.casual_score_scalar;
|
|
}
|
|
else if ( maps\mp\alien\_utility::is_hardcore_mode() )
|
|
{
|
|
level.cycle_health_scalar = level.hardcore_health_scalar;
|
|
level.cycle_damage_scalar = level.hardcore_damage_scalar;
|
|
level.cycle_reward_scalar = level.hardcore_reward_scalar;
|
|
level.cycle_score_scalar = level.hardcore_score_scalar;
|
|
}
|
|
else
|
|
{
|
|
level.cycle_health_scalar = 1.0;
|
|
level.cycle_damage_scalar = 1.0;
|
|
level.cycle_reward_scalar = 1.0;
|
|
level.cycle_score_scalar = 1.0;
|
|
}
|
|
|
|
for ( var_1 = 500; var_1 <= 599; var_1++ )
|
|
{
|
|
var_2 = tablelookup( level.alien_cycle_table, 0, var_1, 1 );
|
|
|
|
if ( var_2 == "" )
|
|
break;
|
|
|
|
var_2 = int( var_2 );
|
|
var_3 = spawnstruct();
|
|
var_3.health = float( tablelookup( level.alien_cycle_table, 0, var_1, 2 ) );
|
|
var_3.damage = float( tablelookup( level.alien_cycle_table, 0, var_1, 3 ) );
|
|
var_3.reward = float( tablelookup( level.alien_cycle_table, 0, var_1, 4 ) );
|
|
var_3.score = float( tablelookup( level.alien_cycle_table, 0, var_1, 5 ) );
|
|
add_cycle_scalar( int( var_2 ), var_3, var_0 );
|
|
}
|
|
}
|
|
|
|
add_cycle_scalar( var_0, var_1, var_2 )
|
|
{
|
|
var_2.cycle_scalars[var_0] = var_1;
|
|
}
|
|
|
|
set_cycle_scalars( var_0 )
|
|
{
|
|
if ( maps\mp\alien\_utility::is_hardcore_mode() )
|
|
{
|
|
level.cycle_health_scalar = level.cycle_data.cycle_scalars[var_0].health * level.hardcore_health_scalar;
|
|
level.cycle_damage_scalar = level.cycle_data.cycle_scalars[var_0].damage * level.hardcore_damage_scalar;
|
|
level.cycle_reward_scalar = level.cycle_data.cycle_scalars[var_0].reward * level.hardcore_reward_scalar;
|
|
level.cycle_score_scalar = level.cycle_data.cycle_scalars[var_0].score * level.hardcore_score_scalar;
|
|
}
|
|
else if ( maps\mp\alien\_utility::is_casual_mode() )
|
|
{
|
|
level.cycle_health_scalar = level.cycle_data.cycle_scalars[var_0].health * level.casual_health_scalar;
|
|
level.cycle_damage_scalar = level.cycle_data.cycle_scalars[var_0].damage * level.casual_damage_scalar;
|
|
level.cycle_reward_scalar = level.cycle_data.cycle_scalars[var_0].reward * level.casual_reward_scalar;
|
|
level.cycle_score_scalar = level.cycle_data.cycle_scalars[var_0].score * level.casual_score_scalar;
|
|
}
|
|
else
|
|
{
|
|
level.cycle_health_scalar = level.cycle_data.cycle_scalars[var_0].health;
|
|
level.cycle_damage_scalar = level.cycle_data.cycle_scalars[var_0].damage;
|
|
level.cycle_reward_scalar = level.cycle_data.cycle_scalars[var_0].reward;
|
|
level.cycle_score_scalar = level.cycle_data.cycle_scalars[var_0].score;
|
|
}
|
|
}
|
|
|
|
init_spawn_node_info( var_0 )
|
|
{
|
|
var_0.spawn_node_info = [];
|
|
init_spawn_node_info_from_table( var_0 );
|
|
}
|
|
|
|
init_spawn_node_info_from_table( var_0 )
|
|
{
|
|
if ( !isdefined( level.spawn_node_info_table ) )
|
|
level.spawn_node_info_table = "mp/alien/spawn_node_info.csv";
|
|
|
|
for ( var_1 = 1; var_1 <= 100; var_1++ )
|
|
{
|
|
var_2 = tablelookup( level.spawn_node_info_table, 0, var_1, 1 );
|
|
|
|
if ( var_2 == "" )
|
|
break;
|
|
|
|
var_3 = spawnstruct();
|
|
var_3.validtype = tablelookup( level.spawn_node_info_table, 0, var_1, 2 );
|
|
var_3.scriptablestatus = getscriptablestatus( var_1 );
|
|
var_4 = [];
|
|
var_4["goon"] = grabvignetteinfo( var_2, var_1, 4, 5, 6, 7, 8, 9, 10 );
|
|
var_4["brute"] = grabvignetteinfo( var_2, var_1, 11, 12, 13, 14, 15, 16, 17 );
|
|
var_4["spitter"] = grabvignetteinfo( var_2, var_1, 18, 19, 20, 21, 22, 23, 24 );
|
|
var_4["seeder"] = grabvignetteinfo( var_2, var_1, 18, 19, 20, 21, 22, 23, 24 );
|
|
var_4["elite"] = grabvignetteinfo( var_2, var_1, 25, 26, 27, 28, 29, 30, 31 );
|
|
var_4["minion"] = grabvignetteinfo( var_2, var_1, 32, 33, 34, 35, 36, 37, 38 );
|
|
var_3.vignetteinfo = var_4;
|
|
var_0.spawn_node_info[var_2] = var_3;
|
|
}
|
|
}
|
|
|
|
grabvignetteinfo( var_0, var_1, var_2, var_3, var_4, var_5, var_6, var_7, var_8 )
|
|
{
|
|
var_9 = ";";
|
|
var_10 = replaceemptystringwithnone( tablelookup( level.spawn_node_info_table, 0, var_1, var_2 ) );
|
|
var_11 = replaceemptystringwithnone( tablelookup( level.spawn_node_info_table, 0, var_1, var_3 ) );
|
|
var_12 = replaceemptystringwithnone( tablelookup( level.spawn_node_info_table, 0, var_1, var_4 ) );
|
|
var_13 = replaceemptystringwithnone( tablelookup( level.spawn_node_info_table, 0, var_1, var_5 ) );
|
|
var_6 = replaceemptystringwithnone( tablelookup( level.spawn_node_info_table, 0, var_1, var_6 ) );
|
|
var_7 = replaceemptystringwithnone( tablelookup( level.spawn_node_info_table, 0, var_1, var_7 ) );
|
|
var_8 = replaceemptystringwithnone( tablelookup( level.spawn_node_info_table, 0, var_1, var_8 ) );
|
|
return var_10 + var_9 + var_11 + var_9 + var_12 + var_9 + var_13 + var_9 + var_6 + var_9 + var_7 + var_9 + var_8 + var_9 + var_0;
|
|
}
|
|
|
|
getscriptablestatus( var_0 )
|
|
{
|
|
var_1 = tablelookup( level.spawn_node_info_table, 0, var_0, 3 );
|
|
|
|
if ( maps\mp\agents\alien\_alien_agents::is_empty_string( var_1 ) )
|
|
return "always_on";
|
|
else
|
|
return "one_off";
|
|
}
|
|
|
|
replaceemptystringwithnone( var_0 )
|
|
{
|
|
if ( maps\mp\agents\alien\_alien_agents::is_empty_string( var_0 ) )
|
|
return "NONE";
|
|
|
|
return var_0;
|
|
}
|
|
|
|
load_cycle_drill_layer_from_table( var_0 )
|
|
{
|
|
var_0.cycle_drill_layers = [];
|
|
var_0.cycle_delay_times = [];
|
|
|
|
for ( var_1 = 600; var_1 <= 699; var_1++ )
|
|
{
|
|
var_2 = tablelookup( level.alien_cycle_table, 0, var_1, 1 );
|
|
|
|
if ( var_2 == "" )
|
|
break;
|
|
|
|
var_3 = tablelookup( level.alien_cycle_table, 0, var_1, 2 );
|
|
var_3 = strtok( var_3, " " );
|
|
|
|
for ( var_4 = 0; var_4 < var_3.size; var_4++ )
|
|
var_3[var_4] = int( var_3[var_4] );
|
|
|
|
var_0.cycle_drill_layers[int( var_2 )] = var_3;
|
|
var_5 = tablelookup( level.alien_cycle_table, 0, var_1, 3 );
|
|
var_0.cycle_delay_times[int( var_2 )] = float( var_5 );
|
|
}
|
|
}
|
|
|
|
load_random_hives_from_table()
|
|
{
|
|
var_0 = [];
|
|
|
|
for ( var_1 = 900; var_1 <= 999; var_1++ )
|
|
{
|
|
var_2 = tablelookup( level.alien_cycle_table, 0, var_1, 1 );
|
|
|
|
if ( var_2 == "" )
|
|
break;
|
|
|
|
var_3 = tablelookup( level.alien_cycle_table, 0, var_1, 2 );
|
|
var_3 = strtok( var_3, " " );
|
|
var_0 = common_scripts\utility::array_combine( var_0, get_hives_to_remove( int( var_2 ), var_3 ) );
|
|
}
|
|
|
|
level.removed_hives = var_0;
|
|
}
|
|
|
|
get_hives_to_remove( var_0, var_1 )
|
|
{
|
|
var_2 = var_1.size - var_0;
|
|
|
|
if ( var_2 == 0 )
|
|
return [];
|
|
|
|
var_1 = common_scripts\utility::array_randomize( var_1 );
|
|
var_3 = [];
|
|
|
|
for ( var_4 = 0; var_4 < var_2; var_4++ )
|
|
var_3[var_3.size] = var_1[var_4];
|
|
|
|
return var_3;
|
|
}
|