Files
Recompilable-gscs-for-BO2-z…/patch_mp/maps/mp/_vehicles.gsc

1634 lines
41 KiB
Plaintext

#include maps/mp/gametypes/_spawning;
#include maps/mp/killstreaks/_qrdrone;
#include maps/mp/killstreaks/_rcbomb;
#include maps/mp/gametypes/_hud_util;
#include maps/mp/_utility;
#include common_scripts/utility;
#using_animtree( "mp_vehicles" );
init()
{
precachevehicle( get_default_vehicle_name() );
setdvar( "scr_veh_cleanupdebugprint", "0" );
setdvar( "scr_veh_driversarehidden", "1" );
setdvar( "scr_veh_driversareinvulnerable", "1" );
setdvar( "scr_veh_alive_cleanuptimemin", "119" );
setdvar( "scr_veh_alive_cleanuptimemax", "120" );
setdvar( "scr_veh_dead_cleanuptimemin", "20" );
setdvar( "scr_veh_dead_cleanuptimemax", "30" );
setdvar( "scr_veh_cleanuptime_dmgfactor_min", "0.33" );
setdvar( "scr_veh_cleanuptime_dmgfactor_max", "1.0" );
setdvar( "scr_veh_cleanuptime_dmgfactor_deadtread", "0.25" );
setdvar( "scr_veh_cleanuptime_dmgfraction_curve_begin", "0.0" );
setdvar( "scr_veh_cleanuptime_dmgfraction_curve_end", "1.0" );
setdvar( "scr_veh_cleanupabandoned", "1" );
setdvar( "scr_veh_cleanupdrifted", "1" );
setdvar( "scr_veh_cleanupmaxspeedmph", "1" );
setdvar( "scr_veh_cleanupmindistancefeet", "75" );
setdvar( "scr_veh_waittillstoppedandmindist_maxtime", "10" );
setdvar( "scr_veh_waittillstoppedandmindist_maxtimeenabledistfeet", "5" );
setdvar( "scr_veh_respawnafterhuskcleanup", "1" );
setdvar( "scr_veh_respawntimemin", "50" );
setdvar( "scr_veh_respawntimemax", "90" );
setdvar( "scr_veh_respawnwait_maxiterations", "30" );
setdvar( "scr_veh_respawnwait_iterationwaitseconds", "1" );
setdvar( "scr_veh_disablerespawn", "0" );
setdvar( "scr_veh_disableoverturndamage", "0" );
setdvar( "scr_veh_explosion_spawnfx", "1" );
setdvar( "scr_veh_explosion_doradiusdamage", "1" );
setdvar( "scr_veh_explosion_radius", "256" );
setdvar( "scr_veh_explosion_mindamage", "20" );
setdvar( "scr_veh_explosion_maxdamage", "200" );
setdvar( "scr_veh_ondeath_createhusk", "1" );
setdvar( "scr_veh_ondeath_usevehicleashusk", "1" );
setdvar( "scr_veh_explosion_husk_forcepointvariance", "30" );
setdvar( "scr_veh_explosion_husk_horzvelocityvariance", "25" );
setdvar( "scr_veh_explosion_husk_vertvelocitymin", "100" );
setdvar( "scr_veh_explosion_husk_vertvelocitymax", "200" );
setdvar( "scr_veh_explode_on_cleanup", "1" );
setdvar( "scr_veh_disappear_maxwaittime", "60" );
setdvar( "scr_veh_disappear_maxpreventdistancefeet", "30" );
setdvar( "scr_veh_disappear_maxpreventvisibilityfeet", "150" );
setdvar( "scr_veh_health_tank", "1350" );
level.vehicle_drivers_are_invulnerable = getDvarInt( "scr_veh_driversareinvulnerable" );
level.onejectoccupants = ::vehicle_eject_all_occupants;
level.vehiclehealths[ "panzer4_mp" ] = 2600;
level.vehiclehealths[ "t34_mp" ] = 2600;
setdvar( "scr_veh_health_jeep", "700" );
if ( init_vehicle_entities() )
{
level.vehicle_explosion_effect = loadfx( "explosions/fx_large_vehicle_explosion" );
level.veh_husk_models = [];
if ( isDefined( level.use_new_veh_husks ) )
{
level.veh_husk_models[ "t34_mp" ] = "veh_t34_destroyed_mp";
}
if ( isDefined( level.onaddvehiclehusks ) )
{
[[ level.onaddvehiclehusks ]]();
}
keys = getarraykeys( level.veh_husk_models );
i = 0;
while ( i < keys.size )
{
precachemodel( level.veh_husk_models[ keys[ i ] ] );
i++;
}
precacherumble( "tank_damage_light_mp" );
precacherumble( "tank_damage_heavy_mp" );
level._effect[ "tanksquish" ] = loadfx( "maps/see2/fx_body_blood_splat" );
}
chopper_player_get_on_gun = %int_huey_gunner_on;
chopper_door_open = %v_huey_door_open;
chopper_door_open_state = %v_huey_door_open_state;
chopper_door_closed_state = %v_huey_door_close_state;
killbrushes = getentarray( "water_killbrush", "targetname" );
_a123 = killbrushes;
_k123 = getFirstArrayKey( _a123 );
while ( isDefined( _k123 ) )
{
brush = _a123[ _k123 ];
brush thread water_killbrush_think();
_k123 = getNextArrayKey( _a123, _k123 );
}
return;
}
water_killbrush_think()
{
for ( ;; )
{
self waittill( "trigger", entity );
if ( isDefined( entity ) )
{
if ( isDefined( entity.targetname ) )
{
if ( entity.targetname == "rcbomb" )
{
entity maps/mp/killstreaks/_rcbomb::rcbomb_force_explode();
break;
}
else
{
if ( entity.targetname == "talon" && !is_true( entity.dead ) )
{
entity notify( "death" );
}
}
}
if ( isDefined( entity.helitype ) && entity.helitype == "qrdrone" )
{
entity maps/mp/killstreaks/_qrdrone::qrdrone_force_destroy();
}
}
}
}
initialize_vehicle_damage_effects_for_level()
{
k_mild_damage_index = 0;
k_moderate_damage_index = 1;
k_severe_damage_index = 2;
k_total_damage_index = 3;
k_mild_damage_health_percentage = 0,85;
k_moderate_damage_health_percentage = 0,55;
k_severe_damage_health_percentage = 0,35;
k_total_damage_health_percentage = 0;
level.k_mild_damage_health_percentage = k_mild_damage_health_percentage;
level.k_moderate_damage_health_percentage = k_moderate_damage_health_percentage;
level.k_severe_damage_health_percentage = k_severe_damage_health_percentage;
level.k_total_damage_health_percentage = k_total_damage_health_percentage;
level.vehicles_damage_states = [];
level.vehicles_husk_effects = [];
level.vehicles_damage_treadfx = [];
vehicle_name = get_default_vehicle_name();
level.vehicles_damage_states[ vehicle_name ] = [];
level.vehicles_damage_treadfx[ vehicle_name ] = [];
level.vehicles_damage_states[ vehicle_name ][ k_mild_damage_index ] = spawnstruct();
level.vehicles_damage_states[ vehicle_name ][ k_mild_damage_index ].health_percentage = k_mild_damage_health_percentage;
level.vehicles_damage_states[ vehicle_name ][ k_mild_damage_index ].effect_array = [];
level.vehicles_damage_states[ vehicle_name ][ k_mild_damage_index ].effect_array[ 0 ] = spawnstruct();
level.vehicles_damage_states[ vehicle_name ][ k_mild_damage_index ].effect_array[ 0 ].damage_effect = loadfx( "vehicle/vfire/fx_tank_sherman_smldr" );
level.vehicles_damage_states[ vehicle_name ][ k_mild_damage_index ].effect_array[ 0 ].sound_effect = undefined;
level.vehicles_damage_states[ vehicle_name ][ k_mild_damage_index ].effect_array[ 0 ].vehicle_tag = "tag_origin";
level.vehicles_damage_states[ vehicle_name ][ k_moderate_damage_index ] = spawnstruct();
level.vehicles_damage_states[ vehicle_name ][ k_moderate_damage_index ].health_percentage = k_moderate_damage_health_percentage;
level.vehicles_damage_states[ vehicle_name ][ k_moderate_damage_index ].effect_array = [];
level.vehicles_damage_states[ vehicle_name ][ k_moderate_damage_index ].effect_array[ 0 ] = spawnstruct();
level.vehicles_damage_states[ vehicle_name ][ k_moderate_damage_index ].effect_array[ 0 ].damage_effect = loadfx( "vehicle/vfire/fx_vfire_med_12" );
level.vehicles_damage_states[ vehicle_name ][ k_moderate_damage_index ].effect_array[ 0 ].sound_effect = undefined;
level.vehicles_damage_states[ vehicle_name ][ k_moderate_damage_index ].effect_array[ 0 ].vehicle_tag = "tag_origin";
level.vehicles_damage_states[ vehicle_name ][ k_severe_damage_index ] = spawnstruct();
level.vehicles_damage_states[ vehicle_name ][ k_severe_damage_index ].health_percentage = k_severe_damage_health_percentage;
level.vehicles_damage_states[ vehicle_name ][ k_severe_damage_index ].effect_array = [];
level.vehicles_damage_states[ vehicle_name ][ k_severe_damage_index ].effect_array[ 0 ] = spawnstruct();
level.vehicles_damage_states[ vehicle_name ][ k_severe_damage_index ].effect_array[ 0 ].damage_effect = loadfx( "vehicle/vfire/fx_vfire_sherman" );
level.vehicles_damage_states[ vehicle_name ][ k_severe_damage_index ].effect_array[ 0 ].sound_effect = undefined;
level.vehicles_damage_states[ vehicle_name ][ k_severe_damage_index ].effect_array[ 0 ].vehicle_tag = "tag_origin";
level.vehicles_damage_states[ vehicle_name ][ k_total_damage_index ] = spawnstruct();
level.vehicles_damage_states[ vehicle_name ][ k_total_damage_index ].health_percentage = k_total_damage_health_percentage;
level.vehicles_damage_states[ vehicle_name ][ k_total_damage_index ].effect_array = [];
level.vehicles_damage_states[ vehicle_name ][ k_total_damage_index ].effect_array[ 0 ] = spawnstruct();
level.vehicles_damage_states[ vehicle_name ][ k_total_damage_index ].effect_array[ 0 ].damage_effect = loadfx( "explosions/fx_large_vehicle_explosion" );
level.vehicles_damage_states[ vehicle_name ][ k_total_damage_index ].effect_array[ 0 ].sound_effect = "vehicle_explo";
level.vehicles_damage_states[ vehicle_name ][ k_total_damage_index ].effect_array[ 0 ].vehicle_tag = "tag_origin";
default_husk_effects = spawnstruct();
default_husk_effects.damage_effect = undefined;
default_husk_effects.sound_effect = undefined;
default_husk_effects.vehicle_tag = "tag_origin";
level.vehicles_husk_effects[ vehicle_name ] = default_husk_effects;
return;
}
get_vehicle_name( vehicle )
{
name = "";
if ( isDefined( vehicle ) )
{
if ( isDefined( vehicle.vehicletype ) )
{
name = vehicle.vehicletype;
}
}
return name;
}
get_default_vehicle_name()
{
return "defaultvehicle_mp";
}
get_vehicle_name_key_for_damage_states( vehicle )
{
vehicle_name = get_vehicle_name( vehicle );
if ( !isDefined( level.vehicles_damage_states[ vehicle_name ] ) )
{
vehicle_name = get_default_vehicle_name();
}
return vehicle_name;
}
get_vehicle_damage_state_index_from_health_percentage( vehicle )
{
damage_state_index = -1;
vehicle_name = get_vehicle_name_key_for_damage_states();
test_index = 0;
while ( test_index < level.vehicles_damage_states[ vehicle_name ].size )
{
if ( vehicle.current_health_percentage <= level.vehicles_damage_states[ vehicle_name ][ test_index ].health_percentage )
{
damage_state_index = test_index;
test_index++;
continue;
}
else
{
}
test_index++;
}
return damage_state_index;
}
update_damage_effects( vehicle, attacker )
{
if ( vehicle.initial_state.health > 0 )
{
previous_damage_state_index = get_vehicle_damage_state_index_from_health_percentage( vehicle );
vehicle.current_health_percentage = vehicle.health / vehicle.initial_state.health;
current_damage_state_index = get_vehicle_damage_state_index_from_health_percentage( vehicle );
if ( previous_damage_state_index != current_damage_state_index )
{
vehicle notify( "damage_state_changed" );
if ( previous_damage_state_index < 0 )
{
start_damage_state_index = 0;
}
else
{
start_damage_state_index = previous_damage_state_index + 1;
}
play_damage_state_effects( vehicle, start_damage_state_index, current_damage_state_index );
if ( vehicle.health <= 0 )
{
vehicle kill_vehicle( attacker );
}
}
}
return;
}
play_damage_state_effects( vehicle, start_damage_state_index, end_damage_state_index )
{
vehicle_name = get_vehicle_name_key_for_damage_states( vehicle );
damage_state_index = start_damage_state_index;
while ( damage_state_index <= end_damage_state_index )
{
effect_index = 0;
while ( effect_index < level.vehicles_damage_states[ vehicle_name ][ damage_state_index ].effect_array.size )
{
effects = level.vehicles_damage_states[ vehicle_name ][ damage_state_index ].effect_array[ effect_index ];
vehicle thread play_vehicle_effects( effects );
effect_index++;
}
damage_state_index++;
}
return;
}
play_vehicle_effects( effects, isdamagedtread )
{
self endon( "delete" );
self endon( "removed" );
if ( !isDefined( isdamagedtread ) || isdamagedtread == 0 )
{
self endon( "damage_state_changed" );
}
if ( isDefined( effects.sound_effect ) )
{
self playsound( effects.sound_effect );
}
waittime = 0;
if ( isDefined( effects.damage_effect_loop_time ) )
{
waittime = effects.damage_effect_loop_time;
}
while ( waittime > 0 )
{
if ( isDefined( effects.damage_effect ) )
{
playfxontag( effects.damage_effect, self, effects.vehicle_tag );
}
wait waittime;
}
}
init_vehicle_entities()
{
vehicles = getentarray( "script_vehicle", "classname" );
array_thread( vehicles, ::init_original_vehicle );
if ( isDefined( vehicles ) )
{
return vehicles.size;
}
return 0;
}
precache_vehicles()
{
}
register_vehicle()
{
if ( !isDefined( level.vehicles_list ) )
{
level.vehicles_list = [];
}
level.vehicles_list[ level.vehicles_list.size ] = self;
}
manage_vehicles()
{
if ( !isDefined( level.vehicles_list ) )
{
return 1;
}
else
{
max_vehicles = getmaxvehicles();
newarray = [];
i = 0;
while ( i < level.vehicles_list.size )
{
if ( isDefined( level.vehicles_list[ i ] ) )
{
newarray[ newarray.size ] = level.vehicles_list[ i ];
}
i++;
}
level.vehicles_list = newarray;
vehiclestodelete = ( level.vehicles_list.size + 1 ) - max_vehicles;
if ( vehiclestodelete > 0 )
{
newarray = [];
i = 0;
while ( i < level.vehicles_list.size )
{
vehicle = level.vehicles_list[ i ];
if ( vehiclestodelete > 0 )
{
if ( isDefined( vehicle.is_husk ) && !isDefined( vehicle.permanentlyremoved ) )
{
deleted = vehicle husk_do_cleanup();
if ( deleted )
{
vehiclestodelete--;
i++;
continue;
}
}
}
else
{
newarray[ newarray.size ] = vehicle;
}
i++;
}
level.vehicles_list = newarray;
}
return level.vehicles_list.size < max_vehicles;
}
}
init_vehicle()
{
self register_vehicle();
if ( isDefined( level.vehiclehealths ) && isDefined( level.vehiclehealths[ self.vehicletype ] ) )
{
self.maxhealth = level.vehiclehealths[ self.vehicletype ];
}
else
{
self.maxhealth = getDvarInt( "scr_veh_health_tank" );
/#
println( "No health specified for vehicle type " + self.vehicletype + "! Using default..." );
#/
}
self.health = self.maxhealth;
self vehicle_record_initial_values();
self init_vehicle_threads();
self maps/mp/gametypes/_spawning::create_vehicle_influencers();
}
initialize_vehicle_damage_state_data()
{
if ( self.initial_state.health > 0 )
{
self.current_health_percentage = self.health / self.initial_state.health;
self.previous_health_percentage = self.health / self.initial_state.health;
}
else
{
self.current_health_percentage = 1;
self.previous_health_percentage = 1;
}
return;
}
init_original_vehicle()
{
self.original_vehicle = 1;
self init_vehicle();
}
vehicle_wait_player_enter_t()
{
self endon( "transmute" );
self endon( "death" );
self endon( "delete" );
while ( 1 )
{
self waittill( "enter_vehicle", player );
player thread player_wait_exit_vehicle_t();
player player_update_vehicle_hud( 1, self );
}
}
player_wait_exit_vehicle_t()
{
self endon( "disconnect" );
self waittill( "exit_vehicle", vehicle );
self player_update_vehicle_hud( 0, vehicle );
}
vehicle_wait_damage_t()
{
self endon( "transmute" );
self endon( "death" );
self endon( "delete" );
while ( 1 )
{
self waittill( "damage" );
occupants = self getvehoccupants();
while ( isDefined( occupants ) )
{
i = 0;
while ( i < occupants.size )
{
occupants[ i ] player_update_vehicle_hud( 1, self );
i++;
}
}
}
}
player_update_vehicle_hud( show, vehicle )
{
if ( show )
{
if ( !isDefined( self.vehiclehud ) )
{
self.vehiclehud = createbar( ( 0, 0, 1 ), 64, 16 );
self.vehiclehud setpoint( "CENTER", "BOTTOM", 0, -40 );
self.vehiclehud.alpha = 0,75;
}
self.vehiclehud updatebar( vehicle.health / vehicle.initial_state.health );
}
else
{
if ( isDefined( self.vehiclehud ) )
{
self.vehiclehud destroyelem();
}
}
if ( getDvar( #"480B1A1D" ) != "" )
{
if ( getDvarInt( #"480B1A1D" ) != 0 )
{
if ( show )
{
if ( !isDefined( self.vehiclehudhealthnumbers ) )
{
self.vehiclehudhealthnumbers = createfontstring( "default", 2 );
self.vehiclehudhealthnumbers setparent( self.vehiclehud );
self.vehiclehudhealthnumbers setpoint( "LEFT", "RIGHT", 8, 0 );
self.vehiclehudhealthnumbers.alpha = 0,75;
self.vehiclehudhealthnumbers.hidewheninmenu = 0;
self.vehiclehudhealthnumbers.archived = 0;
}
self.vehiclehudhealthnumbers setvalue( vehicle.health );
return;
}
else
{
if ( isDefined( self.vehiclehudhealthnumbers ) )
{
self.vehiclehudhealthnumbers destroyelem();
}
}
}
}
}
init_vehicle_threads()
{
self thread vehicle_fireweapon_t();
self thread vehicle_abandoned_by_drift_t();
self thread vehicle_abandoned_by_occupants_t();
self thread vehicle_damage_t();
self thread vehicle_ghost_entering_occupants_t();
self thread vehicle_recycle_spawner_t();
self thread vehicle_disconnect_paths();
if ( isDefined( level.enablevehiclehealthbar ) && level.enablevehiclehealthbar )
{
self thread vehicle_wait_player_enter_t();
self thread vehicle_wait_damage_t();
}
self thread vehicle_wait_tread_damage();
self thread vehicle_overturn_eject_occupants();
if ( getDvarInt( "scr_veh_disableoverturndamage" ) == 0 )
{
self thread vehicle_overturn_suicide();
}
/#
self thread cleanup_debug_print_t();
self thread cleanup_debug_print_clearmsg_t();
#/
}
build_template( type, model, typeoverride )
{
if ( isDefined( typeoverride ) )
{
type = typeoverride;
}
if ( !isDefined( level.vehicle_death_fx ) )
{
level.vehicle_death_fx = [];
}
if ( !isDefined( level.vehicle_death_fx[ type ] ) )
{
level.vehicle_death_fx[ type ] = [];
}
level.vehicle_compassicon[ type ] = 0;
level.vehicle_team[ type ] = "axis";
level.vehicle_life[ type ] = 999;
level.vehicle_hasmainturret[ model ] = 0;
level.vehicle_mainturrets[ model ] = [];
level.vtmodel = model;
level.vttype = type;
}
build_rumble( rumble, scale, duration, radius, basetime, randomaditionaltime )
{
if ( !isDefined( level.vehicle_rumble ) )
{
level.vehicle_rumble = [];
}
struct = build_quake( scale, duration, radius, basetime, randomaditionaltime );
/#
assert( isDefined( rumble ) );
#/
precacherumble( rumble );
struct.rumble = rumble;
level.vehicle_rumble[ level.vttype ] = struct;
precacherumble( "tank_damaged_rumble_mp" );
}
build_quake( scale, duration, radius, basetime, randomaditionaltime )
{
struct = spawnstruct();
struct.scale = scale;
struct.duration = duration;
struct.radius = radius;
if ( isDefined( basetime ) )
{
struct.basetime = basetime;
}
if ( isDefined( randomaditionaltime ) )
{
struct.randomaditionaltime = randomaditionaltime;
}
return struct;
}
build_exhaust( effect )
{
level.vehicle_exhaust[ level.vtmodel ] = loadfx( effect );
}
cleanup_debug_print_t()
{
self endon( "transmute" );
self endon( "death" );
self endon( "delete" );
/#
while ( 1 )
{
if ( isDefined( self.debug_message ) && getDvarInt( "scr_veh_cleanupdebugprint" ) != 0 )
{
print3d( self.origin + vectorScale( ( 0, 0, 1 ), 150 ), self.debug_message, ( 0, 0, 1 ), 1, 1, 1 );
}
wait 0,01;
#/
}
}
cleanup_debug_print_clearmsg_t()
{
self endon( "transmute" );
self endon( "death" );
self endon( "delete" );
/#
while ( 1 )
{
self waittill( "enter_vehicle" );
self.debug_message = undefined;
#/
}
}
cleanup_debug_print( message )
{
/#
self.debug_message = message;
#/
}
vehicle_abandoned_by_drift_t()
{
self endon( "transmute" );
self endon( "death" );
self endon( "delete" );
self wait_then_cleanup_vehicle( "Drift Test", "scr_veh_cleanupdrifted" );
}
vehicle_abandoned_by_occupants_timeout_t()
{
self endon( "transmute" );
self endon( "death" );
self endon( "delete" );
self wait_then_cleanup_vehicle( "Abandon Test", "scr_veh_cleanupabandoned" );
}
wait_then_cleanup_vehicle( test_name, cleanup_dvar_name )
{
self endon( "enter_vehicle" );
self wait_until_severely_damaged();
self do_alive_cleanup_wait( test_name );
self wait_for_vehicle_to_stop_outside_min_radius();
self cleanup( test_name, cleanup_dvar_name, ::vehicle_recycle );
}
wait_until_severely_damaged()
{
while ( 1 )
{
health_percentage = self.health / self.initial_state.health;
if ( isDefined( level.k_severe_damage_health_percentage ) )
{
self cleanup_debug_print( "Damage Test: Still healthy - (" + health_percentage + " >= " + level.k_severe_damage_health_percentage + ") and working treads" );
}
else
{
self cleanup_debug_print( "Damage Test: Still healthy and working treads" );
}
self waittill( "damage" );
health_percentage = self.health / self.initial_state.health;
if ( health_percentage < level.k_severe_damage_health_percentage )
{
return;
}
else
{
}
}
}
get_random_cleanup_wait_time( state )
{
varnameprefix = "scr_veh_" + state + "_cleanuptime";
mintime = getDvarFloat( varnameprefix + "min" );
maxtime = getDvarFloat( varnameprefix + "max" );
if ( maxtime > mintime )
{
return randomfloatrange( mintime, maxtime );
}
else
{
return maxtime;
}
}
do_alive_cleanup_wait( test_name )
{
initialrandomwaitseconds = get_random_cleanup_wait_time( "alive" );
secondswaited = 0;
seconds_per_iteration = 1;
while ( 1 )
{
curve_begin = getDvarFloat( "scr_veh_cleanuptime_dmgfraction_curve_begin" );
curve_end = getDvarFloat( "scr_veh_cleanuptime_dmgfraction_curve_end" );
factor_min = getDvarFloat( "scr_veh_cleanuptime_dmgfactor_min" );
factor_max = getDvarFloat( "scr_veh_cleanuptime_dmgfactor_max" );
treaddeaddamagefactor = getDvarFloat( "scr_veh_cleanuptime_dmgfactor_deadtread" );
damagefraction = 0;
if ( self is_vehicle() )
{
damagefraction = ( self.initial_state.health - self.health ) / self.initial_state.health;
}
else
{
damagefraction = 1;
}
damagefactor = 0;
if ( damagefraction <= curve_begin )
{
damagefactor = factor_max;
}
else if ( damagefraction >= curve_end )
{
damagefactor = factor_min;
}
else
{
dydx = ( factor_min - factor_max ) / ( curve_end - curve_begin );
damagefactor = factor_max + ( ( damagefraction - curve_begin ) * dydx );
}
totalsecstowait = initialrandomwaitseconds * damagefactor;
if ( secondswaited >= totalsecstowait )
{
return;
}
else
{
self cleanup_debug_print( ( test_name + ": Waiting " ) + ( totalsecstowait - secondswaited ) + "s" );
wait seconds_per_iteration;
secondswaited += seconds_per_iteration;
}
}
}
do_dead_cleanup_wait( test_name )
{
total_secs_to_wait = get_random_cleanup_wait_time( "dead" );
seconds_waited = 0;
seconds_per_iteration = 1;
while ( seconds_waited < total_secs_to_wait )
{
self cleanup_debug_print( ( test_name + ": Waiting " ) + ( total_secs_to_wait - seconds_waited ) + "s" );
wait seconds_per_iteration;
seconds_waited += seconds_per_iteration;
}
}
cleanup( test_name, cleanup_dvar_name, cleanup_func )
{
keep_waiting = 1;
while ( keep_waiting )
{
if ( isDefined( cleanup_dvar_name ) )
{
cleanupenabled = getDvarInt( cleanup_dvar_name ) != 0;
}
if ( cleanupenabled != 0 )
{
self [[ cleanup_func ]]();
return;
}
else
{
keep_waiting = 0;
/#
self cleanup_debug_print( "Cleanup disabled for " + test_name + " ( dvar = " + cleanup_dvar_name + " )" );
wait 5;
keep_waiting = 1;
#/
}
}
}
vehicle_wait_tread_damage()
{
self endon( "death" );
self endon( "delete" );
vehicle_name = get_vehicle_name( self );
while ( 1 )
{
self waittill( "broken", brokennotify );
if ( brokennotify == "left_tread_destroyed" )
{
if ( isDefined( level.vehicles_damage_treadfx[ vehicle_name ] ) && isDefined( level.vehicles_damage_treadfx[ vehicle_name ][ 0 ] ) )
{
self thread play_vehicle_effects( level.vehicles_damage_treadfx[ vehicle_name ][ 0 ], 1 );
}
continue;
}
else
{
if ( brokennotify == "right_tread_destroyed" )
{
if ( isDefined( level.vehicles_damage_treadfx[ vehicle_name ] ) && isDefined( level.vehicles_damage_treadfx[ vehicle_name ][ 1 ] ) )
{
self thread play_vehicle_effects( level.vehicles_damage_treadfx[ vehicle_name ][ 1 ], 1 );
}
}
}
}
}
wait_for_vehicle_to_stop_outside_min_radius()
{
maxwaittime = getDvarFloat( "scr_veh_waittillstoppedandmindist_maxtime" );
iterationwaitseconds = 1;
maxwaittimeenabledistinches = 12 * getDvarFloat( "scr_veh_waittillstoppedandmindist_maxtimeenabledistfeet" );
initialorigin = self.initial_state.origin;
totalsecondswaited = 0;
while ( totalsecondswaited < maxwaittime )
{
speedmph = self getspeedmph();
cutoffmph = getDvarFloat( "scr_veh_cleanupmaxspeedmph" );
if ( speedmph > cutoffmph )
{
cleanup_debug_print( "(" + ( maxwaittime - totalsecondswaited ) + "s) Speed: " + speedmph + ">" + cutoffmph );
}
else
{
}
wait iterationwaitseconds;
totalsecondswaited += iterationwaitseconds;
}
}
vehicle_abandoned_by_occupants_t()
{
self endon( "transmute" );
self endon( "death" );
self endon( "delete" );
while ( 1 )
{
self waittill( "exit_vehicle" );
occupants = self getvehoccupants();
if ( occupants.size == 0 )
{
self play_start_stop_sound( "tank_shutdown_sfx" );
self thread vehicle_abandoned_by_occupants_timeout_t();
}
}
}
play_start_stop_sound( sound_alias, modulation )
{
if ( isDefined( self.start_stop_sfxid ) )
{
}
self.start_stop_sfxid = self playsound( sound_alias );
}
vehicle_ghost_entering_occupants_t()
{
self endon( "transmute" );
self endon( "death" );
self endon( "delete" );
while ( 1 )
{
self waittill( "enter_vehicle", player, seat );
isdriver = seat == 0;
if ( getDvarInt( "scr_veh_driversarehidden" ) != 0 && isdriver )
{
player ghost();
}
occupants = self getvehoccupants();
if ( occupants.size == 1 )
{
self play_start_stop_sound( "tank_startup_sfx" );
}
player thread player_change_seat_handler_t( self );
player thread player_leave_vehicle_cleanup_t( self );
}
}
player_is_occupant_invulnerable( smeansofdeath )
{
if ( self isremotecontrolling() )
{
return 0;
}
if ( !isDefined( level.vehicle_drivers_are_invulnerable ) )
{
level.vehicle_drivers_are_invulnerable = 0;
}
if ( level.vehicle_drivers_are_invulnerable )
{
invulnerable = self player_is_driver();
}
return invulnerable;
}
player_is_driver()
{
if ( !isalive( self ) )
{
return 0;
}
vehicle = self getvehicleoccupied();
if ( isDefined( vehicle ) )
{
seat = vehicle getoccupantseat( self );
if ( isDefined( seat ) && seat == 0 )
{
return 1;
}
}
return 0;
}
player_change_seat_handler_t( vehicle )
{
self endon( "disconnect" );
self endon( "exit_vehicle" );
while ( 1 )
{
self waittill( "change_seat", vehicle, oldseat, newseat );
isdriver = newseat == 0;
if ( isdriver )
{
if ( getDvarInt( "scr_veh_driversarehidden" ) != 0 )
{
self ghost();
}
continue;
}
else
{
self show();
}
}
}
player_leave_vehicle_cleanup_t( vehicle )
{
self endon( "disconnect" );
self waittill( "exit_vehicle" );
currentweapon = self getcurrentweapon();
if ( self.lastweapon != currentweapon && self.lastweapon != "none" )
{
self switchtoweapon( self.lastweapon );
}
self show();
}
vehicle_is_tank()
{
if ( self.vehicletype != "sherman_mp" && self.vehicletype != "panzer4_mp" && self.vehicletype != "type97_mp" )
{
return self.vehicletype == "t34_mp";
}
}
vehicle_record_initial_values()
{
if ( !isDefined( self.initial_state ) )
{
self.initial_state = spawnstruct();
}
if ( isDefined( self.origin ) )
{
self.initial_state.origin = self.origin;
}
if ( isDefined( self.angles ) )
{
self.initial_state.angles = self.angles;
}
if ( isDefined( self.health ) )
{
self.initial_state.health = self.health;
}
self initialize_vehicle_damage_state_data();
return;
}
vehicle_fireweapon_t()
{
self endon( "transmute" );
self endon( "death" );
self endon( "delete" );
for ( ;; )
{
self waittill( "turret_fire", player );
if ( isDefined( player ) && isalive( player ) && player isinvehicle() )
{
self fireweapon();
}
}
}
vehicle_should_explode_on_cleanup()
{
return getDvarInt( "scr_veh_explode_on_cleanup" ) != 0;
}
vehicle_recycle()
{
self wait_for_unnoticeable_cleanup_opportunity();
self.recycling = 1;
self suicide();
}
wait_for_vehicle_overturn()
{
self endon( "transmute" );
self endon( "death" );
self endon( "delete" );
worldup = anglesToUp( vectorScale( ( 0, 0, 1 ), 90 ) );
overturned = 0;
while ( !overturned )
{
if ( isDefined( self.angles ) )
{
up = anglesToUp( self.angles );
dot = vectordot( up, worldup );
if ( dot <= 0 )
{
overturned = 1;
}
}
if ( !overturned )
{
wait 1;
}
}
}
vehicle_overturn_eject_occupants()
{
self endon( "transmute" );
self endon( "death" );
self endon( "delete" );
for ( ;; )
{
self waittill( "veh_ejectoccupants" );
if ( isDefined( level.onejectoccupants ) )
{
[[ level.onejectoccupants ]]();
}
wait 0,25;
}
}
vehicle_eject_all_occupants()
{
occupants = self getvehoccupants();
while ( isDefined( occupants ) )
{
i = 0;
while ( i < occupants.size )
{
if ( isDefined( occupants[ i ] ) )
{
occupants[ i ] unlink();
}
i++;
}
}
}
vehicle_overturn_suicide()
{
self endon( "transmute" );
self endon( "death" );
self endon( "delete" );
self wait_for_vehicle_overturn();
seconds = randomfloatrange( 5, 7 );
wait seconds;
damageorigin = self.origin + vectorScale( ( 0, 0, 1 ), 25 );
self finishvehicleradiusdamage( self, self, 32000, 32000, 32000, 0, "MOD_EXPLOSIVE", "defaultweapon_mp", damageorigin, 400, -1, ( 0, 0, 1 ), 0 );
}
suicide()
{
self kill_vehicle( self );
}
kill_vehicle( attacker )
{
damageorigin = self.origin + ( 0, 0, 1 );
self finishvehicleradiusdamage( attacker, attacker, 32000, 32000, 10, 0, "MOD_EXPLOSIVE", "defaultweapon_mp", damageorigin, 400, -1, ( 0, 0, 1 ), 0 );
}
value_with_default( preferred_value, default_value )
{
if ( isDefined( preferred_value ) )
{
return preferred_value;
}
return default_value;
}
vehicle_transmute( attacker )
{
deathorigin = self.origin;
deathangles = self.angles;
modelname = self vehgetmodel();
vehicle_name = get_vehicle_name_key_for_damage_states( self );
respawn_parameters = spawnstruct();
respawn_parameters.origin = self.initial_state.origin;
respawn_parameters.angles = self.initial_state.angles;
respawn_parameters.health = self.initial_state.health;
respawn_parameters.modelname = modelname;
respawn_parameters.targetname = value_with_default( self.targetname, "" );
respawn_parameters.vehicletype = value_with_default( self.vehicletype, "" );
respawn_parameters.destructibledef = self.destructibledef;
vehiclewasdestroyed = !isDefined( self.recycling );
if ( vehiclewasdestroyed || vehicle_should_explode_on_cleanup() )
{
_spawn_explosion( deathorigin );
if ( vehiclewasdestroyed && getDvarInt( "scr_veh_explosion_doradiusdamage" ) != 0 )
{
explosionradius = getDvarInt( "scr_veh_explosion_radius" );
explosionmindamage = getDvarInt( "scr_veh_explosion_mindamage" );
explosionmaxdamage = getDvarInt( "scr_veh_explosion_maxdamage" );
self kill_vehicle( attacker );
self radiusdamage( deathorigin, explosionradius, explosionmaxdamage, explosionmindamage, attacker, "MOD_EXPLOSIVE", self.vehicletype + "_explosion_mp" );
}
}
self notify( "transmute" );
respawn_vehicle_now = 1;
if ( vehiclewasdestroyed && getDvarInt( "scr_veh_ondeath_createhusk" ) != 0 )
{
if ( getDvarInt( "scr_veh_ondeath_usevehicleashusk" ) != 0 )
{
husk = self;
self.is_husk = 1;
}
else
{
husk = _spawn_husk( deathorigin, deathangles, modelname );
}
husk _init_husk( vehicle_name, respawn_parameters );
if ( getDvarInt( "scr_veh_respawnafterhuskcleanup" ) != 0 )
{
respawn_vehicle_now = 0;
}
}
if ( !isDefined( self.is_husk ) )
{
self remove_vehicle_from_world();
}
if ( getDvarInt( "scr_veh_disablerespawn" ) != 0 )
{
respawn_vehicle_now = 0;
}
if ( respawn_vehicle_now )
{
respawn_vehicle( respawn_parameters );
}
}
respawn_vehicle( respawn_parameters )
{
mintime = getDvarInt( "scr_veh_respawntimemin" );
maxtime = getDvarInt( "scr_veh_respawntimemax" );
seconds = randomfloatrange( mintime, maxtime );
wait seconds;
wait_until_vehicle_position_wont_telefrag( respawn_parameters.origin );
if ( !manage_vehicles() )
{
/#
iprintln( "Vehicle can't respawn because MAX_VEHICLES has been reached and none of the vehicles could be cleaned up." );
#/
}
else
{
if ( isDefined( respawn_parameters.destructibledef ) )
{
vehicle = spawnvehicle( respawn_parameters.modelname, respawn_parameters.targetname, respawn_parameters.vehicletype, respawn_parameters.origin, respawn_parameters.angles, respawn_parameters.destructibledef );
}
else
{
vehicle = spawnvehicle( respawn_parameters.modelname, respawn_parameters.targetname, respawn_parameters.vehicletype, respawn_parameters.origin, respawn_parameters.angles );
}
vehicle.vehicletype = respawn_parameters.vehicletype;
vehicle.destructibledef = respawn_parameters.destructibledef;
vehicle.health = respawn_parameters.health;
vehicle init_vehicle();
vehicle vehicle_telefrag_griefers_at_position( respawn_parameters.origin );
}
}
remove_vehicle_from_world()
{
self notify( "removed" );
if ( isDefined( self.original_vehicle ) )
{
if ( !isDefined( self.permanentlyremoved ) )
{
self.permanentlyremoved = 1;
self thread hide_vehicle();
}
return 0;
}
else
{
self _delete_entity();
return 1;
}
}
_delete_entity()
{
/#
#/
self delete();
}
hide_vehicle()
{
under_the_world = ( self.origin[ 0 ], self.origin[ 1 ], self.origin[ 2 ] - 10000 );
self.origin = under_the_world;
wait 0,1;
self hide();
self notify( "hidden_permanently" );
}
wait_for_unnoticeable_cleanup_opportunity()
{
maxpreventdistancefeet = getDvarInt( "scr_veh_disappear_maxpreventdistancefeet" );
maxpreventvisibilityfeet = getDvarInt( "scr_veh_disappear_maxpreventvisibilityfeet" );
maxpreventdistanceinchessq = 144 * maxpreventdistancefeet * maxpreventdistancefeet;
maxpreventvisibilityinchessq = 144 * maxpreventvisibilityfeet * maxpreventvisibilityfeet;
maxsecondstowait = getDvarFloat( "scr_veh_disappear_maxwaittime" );
iterationwaitseconds = 1;
secondswaited = 0;
while ( secondswaited < maxsecondstowait )
{
players_s = get_all_alive_players_s();
oktocleanup = 1;
j = 0;
while ( j < players_s.a.size && oktocleanup )
{
player = players_s.a[ j ];
distinchessq = distancesquared( self.origin, player.origin );
if ( distinchessq < maxpreventdistanceinchessq )
{
self cleanup_debug_print( "(" + ( maxsecondstowait - secondswaited ) + "s) Player too close: " + distinchessq + "<" + maxpreventdistanceinchessq );
oktocleanup = 0;
j++;
continue;
}
else
{
if ( distinchessq < maxpreventvisibilityinchessq )
{
vehiclevisibilityfromplayer = self sightconetrace( player.origin, player, anglesToForward( player.angles ) );
if ( vehiclevisibilityfromplayer > 0 )
{
self cleanup_debug_print( "(" + ( maxsecondstowait - secondswaited ) + "s) Player can see" );
oktocleanup = 0;
}
}
}
j++;
}
if ( oktocleanup )
{
return;
}
wait iterationwaitseconds;
secondswaited += iterationwaitseconds;
}
}
wait_until_vehicle_position_wont_telefrag( position )
{
maxiterations = getDvarInt( "scr_veh_respawnwait_maxiterations" );
iterationwaitseconds = getDvarInt( "scr_veh_respawnwait_iterationwaitseconds" );
i = 0;
while ( i < maxiterations )
{
if ( !vehicle_position_will_telefrag( position ) )
{
return;
}
wait iterationwaitseconds;
i++;
}
}
vehicle_position_will_telefrag( position )
{
players_s = get_all_alive_players_s();
i = 0;
while ( i < players_s.a.size )
{
if ( players_s.a[ i ] player_vehicle_position_will_telefrag( position ) )
{
return 1;
}
i++;
}
return 0;
}
vehicle_telefrag_griefers_at_position( position )
{
attacker = self;
inflictor = self;
players_s = get_all_alive_players_s();
i = 0;
while ( i < players_s.a.size )
{
player = players_s.a[ i ];
if ( player player_vehicle_position_will_telefrag( position ) )
{
player dodamage( 20000, player.origin + ( 0, 0, 1 ), attacker, inflictor, "none" );
}
i++;
}
}
player_vehicle_position_will_telefrag( position )
{
distanceinches = 240;
mindistinchessq = distanceinches * distanceinches;
distinchessq = distancesquared( self.origin, position );
return distinchessq < mindistinchessq;
}
vehicle_recycle_spawner_t()
{
self endon( "delete" );
self waittill( "death", attacker );
if ( isDefined( self ) )
{
self vehicle_transmute( attacker );
}
}
vehicle_play_explosion_sound()
{
self playsound( "car_explo_large" );
}
vehicle_damage_t()
{
self endon( "delete" );
self endon( "removed" );
for ( ;; )
{
self waittill( "damage", damage, attacker );
players = get_players();
i = 0;
while ( i < players.size )
{
if ( !isalive( players[ i ] ) )
{
i++;
continue;
}
else vehicle = players[ i ] getvehicleoccupied();
if ( isDefined( vehicle ) && self == vehicle && players[ i ] player_is_driver() )
{
if ( damage > 0 )
{
earthquake( damage / 400, 1, players[ i ].origin, 512, players[ i ] );
}
if ( damage > 100 )
{
/#
println( "Playing heavy rumble." );
#/
players[ i ] playrumbleonentity( "tank_damage_heavy_mp" );
i++;
continue;
}
else
{
if ( damage > 10 )
{
/#
println( "Playing light rumble." );
#/
players[ i ] playrumbleonentity( "tank_damage_light_mp" );
}
}
}
i++;
}
update_damage_effects( self, attacker );
if ( self.health <= 0 )
{
return;
}
}
}
_spawn_husk( origin, angles, modelname )
{
husk = spawn( "script_model", origin );
husk.angles = angles;
husk setmodel( modelname );
husk.health = 1;
husk setcandamage( 0 );
return husk;
}
is_vehicle()
{
return isDefined( self.vehicletype );
}
swap_to_husk_model()
{
if ( isDefined( self.vehicletype ) )
{
husk_model = level.veh_husk_models[ self.vehicletype ];
if ( isDefined( husk_model ) )
{
self setmodel( husk_model );
}
}
}
_init_husk( vehicle_name, respawn_parameters )
{
self swap_to_husk_model();
effects = level.vehicles_husk_effects[ vehicle_name ];
self play_vehicle_effects( effects );
self.respawn_parameters = respawn_parameters;
forcepointvariance = getDvarInt( "scr_veh_explosion_husk_forcepointvariance" );
horzvelocityvariance = getDvarInt( "scr_veh_explosion_husk_horzvelocityvariance" );
vertvelocitymin = getDvarInt( "scr_veh_explosion_husk_vertvelocitymin" );
vertvelocitymax = getDvarInt( "scr_veh_explosion_husk_vertvelocitymax" );
forcepointx = randomfloatrange( 0 - forcepointvariance, forcepointvariance );
forcepointy = randomfloatrange( 0 - forcepointvariance, forcepointvariance );
forcepoint = ( forcepointx, forcepointy, 0 );
forcepoint += self.origin;
initialvelocityx = randomfloatrange( 0 - horzvelocityvariance, horzvelocityvariance );
initialvelocityy = randomfloatrange( 0 - horzvelocityvariance, horzvelocityvariance );
initialvelocityz = randomfloatrange( vertvelocitymin, vertvelocitymax );
initialvelocity = ( initialvelocityx, initialvelocityy, initialvelocityz );
if ( self is_vehicle() )
{
self launchvehicle( initialvelocity, forcepoint );
}
else
{
self physicslaunch( forcepoint, initialvelocity );
}
self thread husk_cleanup_t();
/#
self thread cleanup_debug_print_t();
#/
}
husk_cleanup_t()
{
self endon( "death" );
self endon( "delete" );
self endon( "hidden_permanently" );
respawn_parameters = self.respawn_parameters;
self do_dead_cleanup_wait( "Husk Cleanup Test" );
self wait_for_unnoticeable_cleanup_opportunity();
self thread final_husk_cleanup_t( respawn_parameters );
}
final_husk_cleanup_t( respawn_parameters )
{
self husk_do_cleanup();
if ( getDvarInt( "scr_veh_respawnafterhuskcleanup" ) != 0 )
{
if ( getDvarInt( "scr_veh_disablerespawn" ) == 0 )
{
respawn_vehicle( respawn_parameters );
}
}
}
husk_do_cleanup()
{
self _spawn_explosion( self.origin );
if ( self is_vehicle() )
{
return self remove_vehicle_from_world();
}
else
{
self _delete_entity();
return 1;
}
}
_spawn_explosion( origin )
{
if ( getDvarInt( "scr_veh_explosion_spawnfx" ) == 0 )
{
return;
}
if ( isDefined( level.vehicle_explosion_effect ) )
{
forward = ( 0, 0, 1 );
rot = randomfloat( 360 );
up = ( cos( rot ), sin( rot ), 0 );
playfx( level.vehicle_explosion_effect, origin, forward, up );
}
thread _play_sound_in_space( "vehicle_explo", origin );
}
_play_sound_in_space( soundeffectname, origin )
{
org = spawn( "script_origin", origin );
org.origin = origin;
org playsound( soundeffectname );
wait 10;
org delete();
}
vehicle_get_occupant_team()
{
occupants = self getvehoccupants();
if ( occupants.size != 0 )
{
occupant = occupants[ 0 ];
if ( isplayer( occupant ) )
{
return occupant.team;
}
}
return "free";
}
vehicledeathwaiter()
{
self notify( "vehicleDeathWaiter" );
self endon( "vehicleDeathWaiter" );
self endon( "disconnect" );
while ( 1 )
{
self waittill( "vehicle_death", vehicle_died );
if ( vehicle_died )
{
self.diedonvehicle = 1;
continue;
}
else
{
self.diedonturret = 1;
}
}
}
turretdeathwaiter()
{
}
vehicle_kill_disconnect_paths_forever()
{
self notify( "kill_disconnect_paths_forever" );
}
vehicle_disconnect_paths()
{
self endon( "death" );
self endon( "kill_disconnect_paths_forever" );
if ( isDefined( self.script_disconnectpaths ) && !self.script_disconnectpaths )
{
self.dontdisconnectpaths = 1;
return;
}
wait randomfloat( 1 );
while ( isDefined( self ) )
{
while ( self getspeed() < 1 )
{
if ( !isDefined( self.dontdisconnectpaths ) )
{
self disconnectpaths();
}
self notify( "speed_zero_path_disconnect" );
while ( self getspeed() < 1 )
{
wait 0,05;
}
}
self connectpaths();
wait 1;
}
}
follow_path( node )
{
self endon( "death" );
/#
assert( isDefined( node ), "vehicle_path() called without a path" );
#/
self notify( "newpath" );
if ( isDefined( node ) )
{
self.attachedpath = node;
}
pathstart = self.attachedpath;
self.currentnode = self.attachedpath;
if ( !isDefined( pathstart ) )
{
return;
}
self attachpath( pathstart );
self startpath();
self endon( "newpath" );
nextpoint = pathstart;
while ( isDefined( nextpoint ) )
{
self waittill( "reached_node", nextpoint );
self.currentnode = nextpoint;
nextpoint notify( "trigger" );
if ( isDefined( nextpoint.script_noteworthy ) )
{
self notify( nextpoint.script_noteworthy );
self notify( "noteworthy" );
}
waittillframeend;
}
}