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

1265 lines
36 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

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

#include common_scripts\utility;
#include animscripts\utility;
#include maps\_utility;
dds_init()
{
level.dds = spawnstruct();
level.dds.heartbeat = 0.25;
level.dds.variant_limit = 18;
level.dds.category_backoff_limit = 6;
level.dds.scripted_line_delay = 2;
level.dds.response_distance_min = 500;
level.dds.history = [];
level.dds.history_count = 15;
level.dds.history_index = 0;
level.dds.player_character_name = "mas";
level.dds.event_override_name = undefined;
level.dds.event_override_probability = .5;
level.dds.response_wait = 0.25;
level.dds.response_wait_axis = 0.25;
init_dds_countryIDs();
init_dds_flags();
init_dds_categories();
init_dds_categories_axis();
init_dds_active_events();
}
init_dds_countryIDs( voice, dds_label )
{
level.dds.characterID_count = 0;
level.dds.character_names = [];
level.dds.character_names["allies"] = array( "american", "russian", "russian_english" );
level.dds.character_names["axis"] = array( "russian", "vietnamese", "cuban", "british", "german" );
level.dds.character_names["default"] = array_combine( level.dds.character_names["allies"], level.dds.character_names["axis"] );
level.dds.countryIDs = [];
add_dds_countryID( "american", "us", 5 );
add_dds_countryID( "russian", "ru", 4 );
add_dds_countryID( "vietnamese", "vc", 4 );
add_dds_countryID( "cuban", "cb", 4 );
add_dds_countryID( "german", "ge", 3 );
add_dds_countryID( "british", "br", 2 );
add_dds_countryID( "russian_english", "rn", 3 );
}
add_dds_countryID( voice, dds_label, max_voices )
{
level.dds.countryIDs[voice] = SpawnStruct();
level.dds.countryIDs[voice].label = dds_label;
level.dds.countryIDs[voice].count = 0;
level.dds.countryIDs[voice].max_voices = max_voices;
}
init_dds_flags()
{
flag_init( "dds_running_allies" );
level thread dds_send_team_notify_on_disable( "allies" );
flag_init( "dds_running_axis" );
level thread dds_send_team_notify_on_disable( "axis" );
}
init_dds_categories()
{
level.dds.categories = [];
add_dds_category( "low_health", "health_low", 1.0, "", true, ::dds_sort_ent_dist, ::get_nearest_not_plr, 5000, 8, 1, true );
add_dds_category( "react_grenade", "react_grenade", 1.25, "grenade_rspns",true, ::dds_sort_ent_dist, ::get_nearest, 5000, .8, 0.5, false );
add_dds_category( "thrt", "thrt", 3, "thrt_rspns", true, ::dds_sort_ent_dist, ::get_nearest_not_plr, 5000, .75, 2, true );
add_dds_category( "thrt_rspns", "rspns_lm", 3, "", true, ::dds_sort_ent_dist, ::get_nearest, 5000, .7, 0.5, true );
add_dds_category( "multikill", "multkill", 1.5, "kill_rspns", true, ::dds_sort_ent_dist, ::get_nearest_not_plr, 5000, 1, 0.5, true );
add_dds_category( "fragout", "act_fragout", 0.5, "action_rspns", true, ::dds_sort_ent_dist, ::get_self_ent, 5000, .8, 0.5, true );
add_dds_category( "kill_confirm", "killfirm", 2, "kill_rspns", true, ::dds_sort_ent_dist, ::get_nearest, 5000, .3, 0.5, true );
add_dds_category( "kill_rspns", "rspns_killfirm", 2, "", true, ::dds_sort_ent_dist, ::get_nearest, 5000, .7, 0, true );
add_dds_category( "action_rspns", "rspns_act", 3, "", true, ::dds_sort_ent_dist, ::get_nearest, 5000, .6, 0.5, true );
add_dds_category( "casualty", "casualty", .75, "", true, ::dds_sort_ent_dist, ::get_nearest_not_plr, 800, .9, 1, true );
add_dds_category( "reload", "act_reload", 2, "action_rspns", true, ::dds_sort_ent_dist, ::get_self_ent, 5000, .2, 0.5, false );
add_dds_category( "smokeout", "act_smokeout", 1.25, "action_rspns", true, ::dds_sort_ent_dist, ::get_self_ent, 5000, 1, 1, true );
add_dds_category( "headshot", "hs", .75, "kill_rspns", true, ::dds_sort_ent_dist, ::get_attacker, 1000, 1, 1, true );
add_dds_category( "friendly_fire", "frndly_fire", 1.25, "", true, ::dds_sort_ent_dist, ::get_self_ent, 5000, .9, 1, true );
add_dds_category( "civ_fire", "frndly_fire", 1, "", true, ::dds_sort_ent_dist, ::get_nearest_not_plr, 5000, .9, 1, true );
add_dds_category( "kill_melee", "kill_melee", .75, "", true, ::dds_sort_ent_dist, ::get_attacker, 400, 1, 0.5, false );
}
init_dds_categories_axis()
{
level.dds.categories_axis = [];
add_dds_category_axis( "react_grenade", "react_grenade", 1, "grenade_rspns",true, ::dds_sort_ent_dist, ::get_nearest, 5000, 1, 0.5 );
add_dds_category_axis( "fragout", "act_fragout", .5, "action_rspns", true, ::dds_sort_ent_dist, ::get_self_ent, 5000, .7, 2 );
add_dds_category_axis( "kill_confirm", "killfirm", 1, "kill_rspns", true, ::dds_sort_ent_dist, ::get_nearest, 5000, .9, 0.5 );
add_dds_category_axis( "kill_rspns", "rspns_killfirm", 1, "", true, ::dds_sort_ent_dist, ::get_nearest, 5000, .7, 0.5 );
add_dds_category_axis( "thrt", "rspns_lm", 2, "thrt_rspns", true, ::dds_sort_ent_dist, ::get_nearest, 5000, 1, 0.5 );
add_dds_category_axis( "thrt_rspns", "rspns_lm", 2, "", true, ::dds_sort_ent_dist, ::get_nearest, 5000, .9, 0.75 );
add_dds_category_axis( "action_rspns", "rspns_act", .75, "", true, ::dds_sort_ent_dist, ::get_nearest, 5000, .8, 1 );
add_dds_category_axis( "casualty", "casualty", 1, "", true, ::dds_sort_ent_dist, ::get_nearest_not_plr, 1500, 1, 3 );
add_dds_category_axis( "low_health", "health_low", 1, "", true, ::dds_sort_ent_dist, ::get_nearest_not_plr, 3500, 1, 1 );
add_dds_category_axis( "reload", "act_reload", .50, "action_rspns", true, ::dds_sort_ent_dist, ::get_self_ent, 2400, .3, 3 );
add_dds_category_axis( "smokeout", "act_smokeout", .5, "action_rspns", true, ::dds_sort_ent_dist, ::get_self_ent, 2600, 1, 1 );
add_dds_category_axis( "headshot", "hs", .75, "kill_rspns", true, ::dds_sort_ent_dist, ::get_attacker, 2000, .8, 1 );
add_dds_category_axis( "kill_melee", "kill_melee", .25, "", true, ::dds_sort_ent_dist, ::get_attacker, 400, 1, 3 );
}
add_dds_category( name, alias_name, duration, rspns_cat_name, clear_category_on_action_success, priority_sort, get_talker_func, distance, probability, timeout_reset, should_squelch )
{
new_category = spawnStruct();
new_category.name = name;
new_category.alias_name = alias_name;
new_category.duration = duration;
new_category.priority_sort = priority_sort;
new_category.probability = probability;
new_category.get_talker_func = get_talker_func;
new_category.speaker_distance = distance;
new_category.last_time = GetTime();
new_category.backoff_count = 0;
new_category.timeout = randomInt( 10 );
new_category.last_timeout = new_category.timeout;
new_category.timeout_reset = timeout_reset;
new_category.rspns_cat_name = rspns_cat_name;
new_category.clear_on_action_success = clear_category_on_action_success;
new_category.should_squelch = should_squelch;
level.dds.categories[level.dds.categories.size] = new_category;
}
add_dds_category_axis( name, alias_name, duration, rspns_cat_name, clear_category_on_action_success, priority_sort, get_talker_func, distance, probability, timeout_reset )
{
new_category_axis = spawnStruct();
new_category_axis.name = name;
new_category_axis.alias_name = alias_name;
new_category_axis.duration = duration;
new_category_axis.priority_sort = priority_sort;
new_category_axis.probability = probability;
new_category_axis.get_talker_func = get_talker_func;
new_category_axis.speaker_distance = distance;
new_category_axis.last_time = GetTime();
new_category_axis.backoff_count = 0;
new_category_axis.timeout = randomInt( 10 );
new_category_axis.last_timeout = new_category_axis.timeout;
new_category_axis.timeout_reset = timeout_reset;
new_category_axis.rspns_cat_name = rspns_cat_name;
new_category_axis.clear_on_action_success = clear_category_on_action_success;
level.dds.categories_axis[level.dds.categories_axis.size] = new_category_axis;
}
init_dds_active_events()
{
level.dds.active_events = [];
level.dds.active_events_axis = [];
for( i = 0; i < level.dds.categories.size; i++ )
{
level.dds.active_events[level.dds.categories[i].name] = [];
}
for( i = 0; i < level.dds.categories_axis.size; i++ )
{
level.dds.active_events_axis[level.dds.categories_axis[i].name] = [];
}
}
dds_clear_old_expired_events()
{
for( i = 0; i < level.dds.categories.size; i ++)
{
category = level.dds.categories[i];
for( j = 0; j < level.dds.active_events[category.name].size; j++ )
{
level.dds.active_events[category.name][j].duration -= level.dds.heartbeat;
if( level.dds.active_events[category.name][j].duration <= 0 ||
level.dds.active_events[category.name][j].clear_event_on_prob )
{
level.dds.active_events[category.name] = array_remove( level.dds.active_events[category.name], level.dds.active_events[category.name][j] );
}
}
}
}
dds_clear_old_expired_events_axis()
{
for( i = 0; i < level.dds.categories_axis.size; i ++)
{
category = level.dds.categories_axis[i];
for( j = 0; j < level.dds.active_events_axis[category.name].size; j++ )
{
level.dds.active_events_axis[category.name][j].duration -= level.dds.heartbeat;
if( level.dds.active_events_axis[category.name][j].duration <= 0 ||
level.dds.active_events_axis[category.name][j].clear_event_on_prob )
{
level.dds.active_events_axis[category.name] = array_remove( level.dds.active_events_axis[category.name], level.dds.active_events_axis[category.name][j] );
}
}
}
}
dds_clear_all_queued_events()
{
for( i = 0; i < level.dds.categories.size; i ++)
{
for( j = 0; j < level.dds.active_events[level.dds.categories[i].name].size; j++ )
{
level.dds.active_events[level.dds.categories[i].name] = [];
}
}
}
dds_clear_all_queued_events_axis()
{
for( i = 0; i < level.dds.categories_axis.size; i ++)
{
for( j = 0; j < level.dds.active_events_axis[level.dds.categories_axis[i].name].size; j++ )
{
level.dds.active_events_axis[level.dds.categories_axis[i].name] = [];
}
}
}
dds_main_process()
{
if( flag( "dds_running_allies" ) )
return;
flag_set( "dds_running_allies" );
dds_find_threats( "allies", "axis" );
should_delay_dds = false;
while( flag( "dds_running_allies" ) )
{
dds_clear_old_expired_events();
if( IsDefined( level.NumberOfImportantPeopleTalking ) && level.NumberOfImportantPeopleTalking > 0 )
{
should_delay_dds = true;
wait( level.dds.heartbeat );
continue;
}
if( should_delay_dds )
{
wait( level.dds.scripted_line_delay );
dds_clear_all_queued_events();
should_delay_dds = false;
}
if( !dds_process_active_events() )
{
wait( level.dds.heartbeat );
}
else
{
wait( 0.1 );
}
}
}
dds_main_process_axis()
{
if( flag( "dds_running_axis" ) )
return;
flag_set( "dds_running_axis" );
dds_find_threats( "axis", "allies" );
should_delay_dds = false;
while( flag( "dds_running_axis" ) )
{
dds_clear_old_expired_events_axis();
if( IsDefined( level.NumberOfImportantPeopleTalking ) && level.NumberOfImportantPeopleTalking > 0 )
{
should_delay_dds = true;
wait( level.dds.heartbeat );
continue;
}
if( should_delay_dds )
{
wait( level.dds.scripted_line_delay );
dds_clear_all_queued_events_axis();
should_delay_dds = false;
}
if( dds_process_active_events_axis() )
{
wait( level.dds.heartbeat );
}
else
{
wait( 0.1 );
}
}
}
dds_find_threats( us, them )
{
level thread dds_find_infantry_threat( us, them );
}
dds_enable( team )
{
if( !IsDefined( team ) )
{
level thread dds_main_process();
level thread dds_main_process_axis();
}
else
{
if( team == "allies" )
{
level thread dds_main_process();
}
else if( team == "axis" )
{
level thread dds_main_process_axis();
}
}
}
dds_disable( team )
{
if( !IsDefined( team ) )
{
dds_clear_all_queued_events();
flag_clear( "dds_running_allies" );
dds_clear_all_queued_events_axis();
flag_clear( "dds_running_axis" );
}
else
{
switch( team )
{
case "axis":
dds_clear_all_queued_events_axis();
flag_clear( "dds_running_axis" );
break;
case "allies":
dds_clear_all_queued_events();
flag_clear( "dds_running_allies" );
break;
default:
break;
}
}
}
dds_send_team_notify_on_disable( team )
{
while( 1 )
{
flag_waitopen( "dds_running_" + team );
level notify( "dds_running_" + team );
flag_wait( "dds_running_" + team );
}
}
is_dds_enabled()
{
if( level.createFX_enabled || (!flag( "dds_running_allies" ) && !flag( "dds_running_axis" )) )
{
return false;
}
return true;
}
exponent( base, power )
{
assert( power >= 0 );
if( power == 0 )
return 1;
return base * exponent( base, ( power - 1 ) );
}
dds_process_active_events()
{
for( i = 0; i < level.dds.categories.size; i ++ )
{
category = level.dds.categories[i];
if( category.timeout > 0 )
{
category.timeout -= level.dds.heartbeat;
continue;
}
if( level.dds.active_events[category.name].size != 0 )
{
level.dds.active_events[category.name] = [[category.priority_sort]] ( level.dds.active_events[category.name] );
for( j = 0; j < level.dds.active_events[category.name].size; j ++ )
{
if( randomFloat( 1 ) >= category.probability )
{
level.dds.active_events[category.name][j].clear_event_on_prob = true;
continue;
}
if( level.dds.active_events[category.name][j].processed )
{
continue;
}
if( dds_event_activate( level.dds.active_events[category.name][j], category.get_talker_func, category.speaker_distance,
category.rspns_cat_name, category.should_squelch ) )
{
if( !category.timeout_reset )
{
category.timeout = category.timeout_reset;
}
else
{
if( ( GetTime() - category.last_time ) < ( category.last_timeout * 1.5 * 1000 ) )
{
category.backoff_count++;
if( category.backoff_count > level.dds.category_backoff_limit )
{
category.backoff_count = level.dds.category_backoff_limit;
}
}
else
{
category.backoff_count--;
if( category.backoff_count < 0 )
{
category.backoff_count = 0;
}
}
category.timeout = category.timeout_reset * ( exponent( 2, category.backoff_count ) ) + randomInt( 2 );
category.last_timeout = category.timeout;
category.last_time = GetTime();
}
if( category.clear_on_action_success )
{
level.dds.active_events[category.name] = [];
}
return true;
}
else
{
wait( level.dds.heartbeat );
}
}
}
}
return false;
}
dds_process_active_events_axis()
{
for( i = 0; i < level.dds.categories_axis.size; i ++ )
{
category = level.dds.categories_axis[i];
if( category.timeout > 0 )
{
category.timeout -= level.dds.heartbeat;
continue;
}
if( level.dds.active_events_axis[category.name].size != 0 )
{
level.dds.active_events_axis[category.name] = [[category.priority_sort]] ( level.dds.active_events_axis[category.name] );
for( j = 0; j < level.dds.active_events_axis[category.name].size; j ++ )
{
if( randomFloat( 1 ) >= category.probability )
{
level.dds.active_events_axis[category.name][j].clear_event_on_prob = true;
continue;
}
if( level.dds.active_events_axis[category.name][j].processed )
{
continue;
}
if( dds_event_activate( level.dds.active_events_axis[category.name][j], category.get_talker_func, category.speaker_distance,
category.rspns_cat_name, false ) )
{
if( !category.timeout_reset )
{
category.timeout = category.timeout_reset;
}
else
{
if( ( GetTime() - category.last_time ) < ( category.last_timeout * 1.5 * 1000 ) )
{
category.backoff_count++;
if( category.backoff_count > level.dds.category_backoff_limit )
{
category.backoff_count = level.dds.category_backoff_limit;
}
}
else
{
category.backoff_count--;
if( category.backoff_count < 0 )
{
category.backoff_count = 0;
}
}
category.timeout = category.timeout_reset * ( exponent( 2, category.backoff_count ) ) + randomInt( 2 );
category.last_timeout = category.timeout;
category.last_time = GetTime();
}
if( category.clear_on_action_success )
{
level.dds.active_events_axis[category.name] = [];
}
return true;
}
else
{
wait( level.dds.heartbeat );
}
}
}
}
return false;
}
dds_event_activate( event, get_talker_func, distance, rspns_cat_name, should_squelch )
{
if( !IsDefined( event ) )
{
return false;
}
category_name = event.category_name;
if( IsDefined( event.category_response_name ) )
{
category_name = event.category_response_name;
}
talker = event [[get_talker_func]] ( IsDefined( event.category_response_name ), distance );
if( !IsDefined( talker ) || !isAlive( talker ) )
{
event.processed = true;
return false;
}
phrase = dds_get_alias_from_event( talker, event.category_alias_name, event.ent );
if( !IsDefined( phrase ) )
{
return false;
}
if( IsDefined( event.category_response_name ) )
{
if( event.isAlliesLine )
{
wait( level.dds.response_wait );
}
else
{
wait( level.dds.response_wait_axis );
}
}
if(!getdvarint("snd_dsp_futz"))
{
should_squelch = false;
}
if( IsAlive( talker ) )
{
if( should_squelch && !IsPlayer( talker ) && ( talker.voice != "russian_english" ) )
{
talker animscripts\face::PlayFaceThread( undefined, "dds_squelch_strt", .5, "dds_squelch_strt" );
}
talker animscripts\face::PlayFaceThread( undefined, phrase, .5, phrase );
}
if( should_squelch && !IsPlayer( talker ) && IsAlive( talker ) && ( talker.voice != "russian_english" ) )
{
talker animscripts\face::PlayFaceThread( undefined, "dds_squelch_end", .5, "dds_squelch_end" );
}
event.talker = talker;
event.talker_origin = talker.origin;
event.phrase = phrase;
event.processed = true;
add_phrase_to_history( phrase );
if( rspns_cat_name != "" )
{
dds_notify_response( event, talker, phrase, rspns_cat_name );
}
return true;
}
add_phrase_to_history( phrase )
{
level.dds.history[level.dds.history_index] = phrase;
level.dds.history_index = ( level.dds.history_index + 1 ) % level.dds.history_count;
}
get_nearest_common( response, player_can_say_line, distance )
{
player = get_players()[0];
if( self.isAlliesLine )
{
ai_array = GetAIArray( "allies" );
if( player_can_say_line )
{
ai_array[ai_array.size] = player;
}
}
else
{
ai_array = GetAIArray( "axis" );
}
if( ai_array.size <= 0 )
return undefined;
if( response && IsDefined( self.talker ) )
{
ai_array = remove_all_actors_with_same_characterID( ai_array, self.talker.dds_characterID );
closest_ent = get_closest_living( self.talker.origin, ai_array );
}
else
{
closest_ent = get_closest_living( self.ent_origin, ai_array );
}
if( !IsDefined( closest_ent ) )
return undefined;
dis_from_player = distance( player.origin, closest_ent.origin );
if( dis_from_player > distance )
{
return undefined;
}
if( response && ( dis_from_player < level.dds.response_distance_min ) )
{
return undefined;
}
return closest_ent;
}
remove_all_actors_with_same_characterID( ai_array, talker_characterID )
{
for( i = 0; i < ai_array.size; )
{
if( !IsDefined( ai_array[i].dds_characterID ) )
{
ai_array = array_remove( ai_array, ai_array[i] );
continue;
}
if( ai_array[i].dds_characterID == talker_characterID )
{
ai_array = array_remove( ai_array, ai_array[i] );
continue;
}
i++;
}
return ai_array;
}
get_nearest( response, distance )
{
return get_nearest_common( response, true, distance );
}
get_nearest_not_plr( response, distance )
{
return get_nearest_common( response, false, distance );
}
get_attacker( response, distance )
{
if( IsDefined( self.ent_attacker ) && IsAlive( self.ent_attacker ) )
{
if( IsDefined( self.ent_team ) )
{
if( IsDefined( self.ent_attacker.team ) && self.ent_team == self.ent_attacker.team )
{
return undefined;
}
if( IsDefined( self.ent_attacker.vteam ) && self.ent_team == self.ent_attacker.vteam )
{
return undefined;
}
}
return self.ent_attacker;
}
return undefined;
}
get_self_ent( response, distance )
{
if( IsDefined( self.ent ) && isAlive( self.ent ) )
{
return self.ent;
}
return undefined;
}
dds_get_alias_from_event( talker, category_alias_name, event_ent )
{
if( !IsAlive( talker ) )
{
return undefined;
}
if( !IsDefined( talker.dds_characterID ) )
{
return undefined;
}
alias = "dds_" + talker.dds_characterID + "_" + category_alias_name + "_";
if( IsDefined( event_ent ) && category_alias_name == "thrt" )
{
qualifier = event_ent get_landmark_qualifier( alias );
if( IsDefined( qualifier ) )
{
alias += qualifier + "_";
}
}
variant_num = 0;
variant_count_array = dds_variant_count_for_alias( alias );
if( variant_count_array.size > 0 )
{
for( i = 0; i < variant_count_array.size; i++ )
{
variant_num = random( variant_count_array );
temp_alias = alias;
if( variant_num < 10 )
temp_alias += "0";
temp_alias += variant_num;
if( !is_phrase_in_history( temp_alias ) )
return temp_alias;
}
}
else
{
return undefined;
}
return undefined;
}
is_phrase_in_history( phrase )
{
for( i = 0; i < level.dds.history.size; i++ )
{
if( level.dds.history[i] == phrase )
{
return true;
}
}
return false;
}
dds_variant_count_for_alias( alias )
{
variant_count_array = [];
for( i = 0; i < level.dds.variant_limit; i++ )
{
prefix = "";
if( i < 10 )
prefix = "0";
if( SoundExists( alias + prefix + i ) )
{
variant_count_array[variant_count_array.size] = i;
}
}
return variant_count_array;
}
get_landmark_qualifier( alias )
{
lm_script_area = undefined;
lm_script_area_origin = undefined;
if( !IsDefined( self.node ) )
{
nodeArray = GetAnyNodeArray( self.origin, 100 );
for( i = 0; (i < nodeArray.size && i < 3); i++ )
{
if( IsDefined( nodeArray[i].script_area ) )
{
lm_script_area = nodeArray[i].script_area;
lm_script_area_origin = nodeArray[i].origin;
break;
}
}
}
else if( IsDefined( self.node.script_area ) )
{
lm_script_area = self.node.script_area;
lm_script_area_origin = self.node.origin;
}
if( !IsDefined( lm_script_area ) || !IsDefined( lm_script_area_origin ) )
return undefined;
if( ( distance( self.origin, lm_script_area_origin ) < 400 ) && SoundExists( alias + lm_script_area + "_00" ) )
{
return lm_script_area;
}
return undefined;
}
get_event_override( alias )
{
if( IsDefined( level.dds.event_override_name ) && ( randomFloat( 1 ) >= level.dds.event_override_probability ) &&
SoundExists( alias + level.dds.event_override_name + "_00" ) )
{
return level.dds.event_override_name;
}
return undefined;
}
dds_find_infantry_threat( us, them )
{
THRT_INF_NOTIFY_DISTANCE = 4000;
while( flag( "dds_running_" + us ) )
{
player = get_players()[0];
our_team = GetAIArray( us );
other_team = GetAIArray( them );
success = false;
for( i = 0; i < our_team.size; i++ )
{
for( j = 0; j < other_team.size; j++ )
{
if( ( other_team.size > 1 ) && ( randomFloat( 1 ) < .5 ) )
{
if( other_team[j] canSee( our_team[i] ) && ( distance( other_team[j].origin, our_team[i].origin ) < THRT_INF_NOTIFY_DISTANCE ) &&
( distance( other_team[j].origin, player.origin ) < THRT_INF_NOTIFY_DISTANCE ) )
{
other_team[j] dds_notify( "thrt", ( them != "allies" ) );
success = true;
break;
}
}
}
if( success )
break;
}
wait( 2 );
}
}
player_init()
{
if( !IsPlayer( self ) )
{
PrintLn( "dds::player_init not called on a player; did not set up dds player flags and threads." );
return;
}
self.isKillstreakTimerRunning = false;
self.killstreakcounter = 0;
self ent_flag_init( "dds_killstreak" );
self ent_flag_init( "dds_low_health" );
self thread dds_killstreak_timer();
self thread dds_watch_player_health();
self thread dds_multikill_tracker();
self.dds_characterID = level.dds.player_character_name;
}
dds_multikill_tracker()
{
self endon( "death" );
self endon( "disconnect" );
while( 1 )
{
level flag_wait( "dds_running_" + self.team );
self waittill( "multikill" );
self dds_notify( "multikill", ( self.team == "allies" ) );
}
}
dds_watch_player_health()
{
self endon( "death" );
self endon( "disconnect" );
while( 1 )
{
level flag_wait( "dds_running_" + self.team );
wait( 0.5 );
if( self.health < self.maxhealth * 0.4 )
{
self dds_notify( "low_health", self.team == "allies" );
self ent_flag_set( "dds_low_health" );
self thread reset_player_health();
}
self ent_flag_waitopen( "dds_low_health" );
}
}
reset_player_health()
{
self endon( "death" );
self endon( "disconnect" );
while( 1 )
{
if( self.health > self.maxhealth * 0.75 )
{
self ent_flag_clear( "dds_low_health" );
return;
}
wait( 1 );
}
}
dds_killstreak_timer()
{
self endon( "death" );
self endon( "disconnect" );
kills = getDvarIntDefault( #"dds_killstreak_kills", 3 );
time = getDvarIntDefault( #"dds_killstreak_timer", 10 );
while( 1 )
{
level flag_wait( "dds_running_" + self.team );
self ent_flag_wait( "dds_killstreak" );
self.killstreakcounter++;
if( !self.isKillstreakTimerRunning )
{
self.isKillstreakTimerRunning = true;
self thread track_kills_over_time( kills, time );
}
self ent_flag_clear( "dds_killstreak" );
}
}
track_kills_over_time( kills, time )
{
timer = GetTime() + ( time * 1000 );
while( GetTime() < timer )
{
if( self.killstreakcounter >= kills )
{
self dds_notify( "killstreak", self.team == "allies" );
self.killstreakcounter = 0;
timer = -1;
}
wait( 0.1 );
}
self.killstreakcounter = 0;
self.isKillstreakTimerRunning = false;
}
dds_ai_init()
{
self dds_get_ai_id();
self thread dds_watch_grenade_flee();
self thread dds_watch_friendly_fire();
}
dds_get_ai_id()
{
classname = ToLower( self.classname );
tokens = StrTok( classname, "_" );
if( tokens.size >= 2 )
{
switch( tokens[1] )
{
case "clark":
case "mason":
case "carlos":
return;
case "barnes":
self.dds_characterID = "woo";
return;
case "lewis":
self.dds_characterID = "bow";
return;
case "reznov":
case "woods":
case "bowman":
case "weaver":
case "hudson":
self.dds_characterID = GetSubStr( tokens[1], 0, 3 );
return;
}
}
if( self.team != "neutral" )
{
for( i = 0; i < level.dds.character_names[self.team].size; i++ )
{
if( self.voice == level.dds.character_names[self.team][i] )
{
self.dds_characterID = level.dds.countryIDs[self.voice].label + ( level.dds.countryIDs[self.voice].count % level.dds.countryIDs[self.voice].max_voices );
level.dds.countryIDs[self.voice].count++;
return;
}
}
}
else
{
return;
}
printLn( "dds: didn't set this AI with a dds_characterID" );
}
dds_watch_grenade_flee()
{
self endon( "death" );
self endon( "disconnect" );
while( 1 )
{
self waittill( "grenade_flee", weaponName );
if( weaponName == "frag_grenade_sp" )
{
self dds_notify( "react_grenade", ( self.team == "allies" ) );
}
}
}
dds_watch_friendly_fire()
{
self endon( "death" );
self endon( "disconnect" );
while( 1 )
{
self waittill( "dds_friendly_fire" );
self dds_notify( "friendly_fire", ( self.team == "allies" ) );
}
}
update_player_damage( eAttacker )
{
if( !is_dds_enabled() )
{
return;
}
self.dds_dmg_attacker = eAttacker;
}
update_actor_damage( eAttacker, damage_mod )
{
if( !is_dds_enabled() )
{
return;
}
self.dds_dmg_attacker = eAttacker;
if( IsPlayer( eAttacker ) )
{
switch( damage_mod )
{
case "MOD_GRENADE_SPLASH":
case "MOD_IMPACT":
return;
}
if( self.team == eAttacker.team )
{
self notify( "dds_friendly_fire" );
}
else if( self.team == "neutral" )
{
self dds_notify( "civ_fire", ( eAttacker.team == "allies" ) );
}
}
}
check_kill_damage( mod, dmg_mod )
{
if( IsDefined( self.dds_dmg_attacker ) && IsDefined( self.dds_dmg_attacker.dds_dmg_attacker ) )
{
if( self == self.dds_dmg_attacker.dds_dmg_attacker )
{
return ( "kill_dmg_" + dmg_mod );
}
}
return mod;
}
dds_notify_mod( isAlliesLine, category_name )
{
if( !is_dds_enabled() )
{
return;
}
if( !IsDefined( self.damagemod ) )
return;
if( IsDefined( self.dds_dmg_attacker ) && IsDefined( self.team ) )
{
if( IsDefined( self.dds_dmg_attacker.team ) && ( ( self.dds_dmg_attacker.team == self.team ) || ( self.team == "neutral" ) ) )
{
return;
}
else if( IsDefined( self.dds_dmg_attacker.vteam ) && ( self.dds_dmg_attacker.vteam == self.team ) )
{
return;
}
}
is_bullet_kill = false;
if( !IsDefined( category_name ) )
{
switch( self.damagemod )
{
case "MOD_CRUSH":
case "MOD_TELEFRAG":
case "MOD_FALLING":
case "MOD_SUICIDE":
case "MOD_TRIGGER_HURT":
case "MOD_BURNED":
case "MOD_HIT_BY_OBJECT":
case "MOD_DROWN":
break;
case "MOD_UNKNOWN":
case "MOD_PROJECTILE":
case "MOD_PROJECTILE_SPLASH":
case "MOD_BAYONET":
break;
case "MOD_MELEE":
self dds_notify( check_kill_damage( "kill_melee", "melee" ), isAlliesLine );
break;
case "MOD_EXPLOSIVE":
case "MOD_GRENADE":
case "MOD_GRENADE_SPLASH":
self dds_notify( "kill_explo", isAlliesLine );
break;
case "MOD_PISTOL_BULLET":
case "MOD_RIFLE_BULLET":
self dds_notify( check_kill_damage( "kill_confirm", "shot" ), isAlliesLine );
is_bullet_kill = true;
break;
case "MOD_HEAD_SHOT":
is_bullet_kill = true;
break;
default:
printLn( "^5 MOD: " + self.damagemod + " \n" );
break;
}
}
else
{
self dds_notify( category_name, isAlliesLine );
is_bullet_kill = true;
}
if( IsPlayer( self.attacker ) && is_bullet_kill )
{
self.attacker ent_flag_set( "dds_killstreak" );
}
}
dds_notify_casualty()
{
self dds_notify( "casualty", ( self.team == "allies" ) );
}
dds_notify_grenade( grenade_name, isAlliesLine, isThrowBack )
{
if( !is_dds_enabled() )
{
return;
}
if( !isThrowBack )
{
switch( grenade_name )
{
case "frag_grenade_sp":
self dds_notify( "fragout", isAlliesLine );
break;
case "willy_pete_sp":
self dds_notify( "smokeout", isAlliesLine );
break;
case "flash_grenade_sp":
case "m8_white_smoke_sp":
case "claymore_sp":
case "molotov_sp":
case "vc_grenade_sp":
break;
default:
break;
}
}
else
{
self dds_notify( "frag_throwback", isAlliesLine );
}
}
dds_notify_reload( weaponName, isAlliesLine )
{
if( !IsDefined( weaponName ) )
{
self dds_notify( "reload", isAlliesLine );
return;
}
else if( ( self GetCurrentWeaponClipAmmo() > 0 ) )
{
return;
}
switch( weaponName )
{
case "crossbow_sp":
case "crossbow_vzoom_alt_sp":
case "crossbow_explosive_alt_sp":
break;
default:
self dds_notify( "reload", isAlliesLine );
break;
}
}
dds_notify( category_name, isAlliesLine )
{
if( !flag( "dds_running_allies" ) && isAlliesLine )
{
return;
}
if( !flag( "dds_running_axis" ) && !isAlliesLine )
{
return;
}
if( isAlliesLine && !IsDefined( level.dds.active_events[category_name] ) )
{
return;
}
if( !isAlliesLine && !IsDefined( level.dds.active_events_axis[category_name] ) )
{
return;
}
assertEx( IsDefined( level.dds ), "dds not init." );
assertEx( IsDefined( isAlliesLine ), "isAlliesLine is not defined." );
event = spawnstruct();
event.category_name = category_name;
event.ent = self;
event.ent_origin = self.origin;
event.ent_team = self.team;
event.clear_event_on_prob = false;
event.processed = false;
event.ent_attacker = self.dds_dmg_attacker;
event.isAlliesLine = isAlliesLine;
if( !isAlliesLine )
{
dds_category = find_dds_category_by_name( level.dds.categories_axis, category_name );
if( !IsDefined( dds_category ) )
{
return;
}
event.duration = dds_category.duration;
event.category_alias_name = dds_category.alias_name;
level.dds.active_events_axis[category_name][level.dds.active_events_axis[category_name].size] = event;
}
else
{
dds_category = find_dds_category_by_name( level.dds.categories, category_name );
if( !IsDefined( dds_category ) )
{
return;
}
event.duration = dds_category.duration;
event.category_alias_name = dds_category.alias_name;
level.dds.active_events[category_name][level.dds.active_events[category_name].size] = event;
}
}
dds_notify_response( event, talker, phrase, rspns_cat_name )
{
event.category_response_name = rspns_cat_name;
event.processed = false;
if( ( rspns_cat_name == "grenade_rspns" ) && IsDefined( event.ent ) && IsDefined( event.ent.grenade ) && IsDefined( event.ent.grenade.originalowner ) &&
( IsDefined( event.ent.grenade.originalowner.team != event.ent_team ) ) )
return;
if( !event.isAlliesLine )
{
dds_category = find_dds_category_by_name( level.dds.categories_axis, event.category_response_name );
if( !IsDefined( dds_category ) )
{
return;
}
event.duration = dds_category.duration;
event.category_alias_name = dds_category.alias_name;
level.dds.active_events_axis[event.category_response_name][level.dds.active_events_axis[event.category_response_name].size] = event;
}
else
{
dds_category = find_dds_category_by_name( level.dds.categories, event.category_response_name );
if( !IsDefined( dds_category ) )
{
return;
}
event.duration = dds_category.duration;
event.category_alias_name = dds_category.alias_name;
level.dds.active_events[event.category_response_name][level.dds.active_events[event.category_response_name].size] = event;
}
}
find_dds_category_by_name( category_array, category_name )
{
for( i = 0; i < category_array.size; i++ )
{
if( category_array[i].name == category_name )
{
return category_array[i];
}
}
return undefined;
}
dds_sort_ent_dist( eventArray )
{
player = get_players()[0];
dist_array = [];
index_array = [];
for( i = 0; i < eventArray.size; i++ )
{
length = distance( player.origin, eventArray[i].ent_origin );
dist_array[dist_array.size] = length;
index_array[index_array.size] = i;
}
temp = undefined;
for( i = 0; i < dist_array.size - 1; i++ )
{
if( dist_array[i] <= dist_array[i + 1] )
continue;
temp = dist_array[i];
dist_array[i] = dist_array[i + 1];
dist_array[i + 1] = temp;
temp = index_array[i];
index_array[i] = index_array[i + 1];
index_array[i + 1] = temp;
}
new_array = [];
for( i = 0; i < index_array.size; i++ )
{
new_array[i] = eventArray[index_array[i]];
}
return new_array;
}
dds_sort_ent_duration( eventArray )
{
return eventArray;
}
dds_sort_ent_damage( eventArray )
{
return eventArray;
}
getDvarIntDefault( dvarName, defaultValue )
{
returnVal = defaultValue;
if( getDvar( dvarName ) != "" )
{
return getDvarInt( dvarName );
}
return returnVal;
}
dds_set_event_override( event_name )
{
level.dds.event_override_name = event_name;
}
dds_clear_event_override()
{
level.dds.event_override_name = undefined;
}
dds_set_event_override_probability( probability_value )
{
if( probability_value < 0 || probability_value > 1 )
{
PrintLn( probability_value + " is invalid event override probability. value must be between 0 and 1. resetting to default." );
dds_reset_event_override_probability();
}
else
{
level.dds.event_override_probability = probability_value;
}
}
dds_reset_event_override_probability()
{
level.dds.event_override_probability = .5;
}