#using scripts\shared\audio_shared; #namespace driving_fx; class GroundFx { var id ; var handle; constructor() { id = undefined; handle = -1; } destructor() { } function play( localClientNum, vehicle, fx_id, fx_tag ) { if ( !isdefined(fx_id ) ) { //stop( localClientNum ); if ( handle > 0 ) { StopFx( localClientNum, handle ); } id = undefined; handle = -1; return; } if ( !isdefined( id ) ) { id = fx_id; handle = PlayFxOnTag( localClientNum, id, vehicle, fx_tag ); } else { if ( !isdefined( id ) || id != fx_id ) { if ( handle > 0 ) { StopFx( localClientNum, handle ); } id = fx_id; handle = PlayFxOnTag( localClientNum, id, vehicle, fx_tag ); } } } function stop( localClientNum ) { if ( handle > 0 ) { StopFx( localClientNum, handle ); } id = undefined; handle = -1; } } class VehicleWheelFx { var name; var tag_name; var ground_fx; constructor() { name = ""; tag_name = ""; } destructor() { } function init( _name, _tag_name ) { name = _name; tag_name = _tag_name; ground_fx = []; ground_fx[ "skid" ] = new GroundFx(); ground_fx[ "tread" ] = new GroundFx(); ground_fx[ "tread" ].id = ""; ground_fx[ "tread" ].handle = -1; } function update( localClientNum, vehicle, speed_fraction ) { if ( vehicle.vehicleclass === "boat" ) { peelingout = false; sliding = false; trace = bullettrace( vehicle.origin + ( 0, 0, 60 ), vehicle.origin - ( 0, 0, 200 ), false, vehicle ); if( trace["fraction"] < 1.0 ) { surface = trace["surfacetype"]; } else { [[ ground_fx[ "skid" ] ]]->stop( localClientNum ); [[ ground_fx[ "tread" ] ]]->stop( localClientNum ); return; } } else { // If we are not colliding stop all fx if ( !vehicle IsWheelColliding( name ) ) { [[ ground_fx[ "skid" ] ]]->stop( localClientNum ); [[ ground_fx[ "tread" ] ]]->stop( localClientNum ); return; } peelingout = vehicle IsWheelPeelingOut( name ); sliding = vehicle IsWheelSliding( name ); surface = vehicle GetWheelSurface( name ); } origin = vehicle GetTagOrigin( tag_name ) + ( 0, 0, 1 ); angles = vehicle GetTagAngles( tag_name ); fwd = AnglesToForward( angles ); right = AnglesToRight( angles ); rumble = false; if ( peelingout ) { peel_fx = vehicle driving_fx::get_wheel_fx( "peel", surface ); if ( isdefined( peel_fx ) ) { PlayFx( localClientNum, peel_fx, origin, fwd * -1 ); rumble = true; } } if ( sliding ) { skid_fx = vehicle driving_fx::get_wheel_fx( "skid", surface ); [[ ground_fx[ "skid" ] ]]->play( localClientNum, vehicle, skid_fx, tag_name ); vehicle.skidding = true; rumble = true; } else { [[ ground_fx[ "skid" ] ]]->stop( localClientNum ); } if ( speed_fraction > 0.1 ) { tread_fx = vehicle driving_fx::get_wheel_fx( "tread", surface ); [[ ground_fx[ "tread" ] ]]->play( localClientNum, vehicle, tread_fx, tag_name ); } else { [[ ground_fx[ "tread" ] ]]->stop( localClientNum ); } if ( rumble ) { if ( vehicle IsLocalClientDriver( localClientNum ) ) { player = GetLocalPlayer( localClientNum ); player PlayRumbleOnEntity( localClientNum, "reload_small" ); } } } } class vehicle_camera_fx { var quake_time_min; var quake_time_max; var quake_strength_min; var quake_strength_max; var rumble_name; constructor() { quake_time_min = 0.5; quake_time_max = 1.0; quake_strength_min = 0.1; quake_strength_max = 0.115; rumble_name = ""; } destructor() { } function init( t_min, t_max, s_min, s_max, rumble = "" ) { quake_time_min = t_min; quake_time_max = t_max; quake_strength_min = s_min; quake_strength_max = s_max; rumble_name = ( rumble != "" ? rumble : rumble_name ); } function update( localClientNum, vehicle, speed_fraction ) { if ( vehicle IsLocalClientDriver( localClientNum ) ) { player = getlocalplayer( localClientNum ); if ( speed_fraction > 0 ) { strength = RandomFloatRange( quake_strength_min, quake_strength_max ) * speed_fraction; time = RandomFloatRange( quake_time_min, quake_time_max ); player Earthquake( strength, time, player.origin, 500 ); if ( rumble_name != "" && speed_fraction > 0.5 ) { if ( RandomInt( 100 ) < 10 ) { player PlayRumbleOnEntity( localClientNum, rumble_name ); } } } } } } /* DEAD CODE REMOVAL function play_driving_fx_thirdperson( localClientNum, speed, speed_fraction ) { // SP uses _treadfx.csc } */ function vehicle_enter( localClientNum ) { self endon( "entityshutdown" ); while ( 1 ) { self waittill( "enter_vehicle", user ); if ( isdefined( user ) && user isplayer() ) { self thread driving_fx::collision_thread( localClientNum ); self thread driving_fx::jump_landing_thread( localClientNum ); // self thread driving_fx::speed_fx( localClientNum ); } } } function speed_fx( localClientNum ) { self endon( "entityshutdown" ); self endon( "exit_vehicle" ); while ( 1 ) { curspeed = self GetSpeed(); curspeed = 0.0005 * curspeed; curspeed = Abs(curspeed); if (curspeed>0.001) { SetSavedDvar("r_speedBlurFX_enable","1"); SetSavedDvar("r_speedBlurAmount",curspeed); } else { SetSavedDvar("r_speedBlurFX_enable","0"); } wait 0.05; } } function play_driving_fx( localClientNum ) { self endon( "entityshutdown" ); self thread vehicle_enter( localClientNum ); if ( self.surfacefxdeftype == "" ) return; if ( !isdefined( self.wheel_fx ) ) { wheel_names = array( "front_left", "front_right", "back_left", "back_right" ); wheel_tag_names = array( "tag_wheel_front_left", "tag_wheel_front_right", "tag_wheel_back_left", "tag_wheel_back_right" ); // temp hack for RAPS vehicle if( isdefined( self.scriptvehicletype ) && self.scriptvehicletype == "raps" ) { wheel_names = array( "front_left" ); wheel_tag_names = array( "tag_origin" ); } else if( self.vehicleclass == "boat" ) { wheel_names = array( "tag_origin" ); wheel_tag_names = array( "tag_origin" ); } self.wheel_fx = []; for ( i = 0; i < wheel_names.size; i++ ) { self.wheel_fx[i] = new VehicleWheelFx(); [[ self.wheel_fx[i] ]]->init( wheel_names[i], wheel_tag_names[i] ); } self.camera_fx = []; self.camera_fx[ "speed" ] = new vehicle_camera_fx(); [[ self.camera_fx[ "speed" ] ]]->init( 0.5, 1.0, 0.1, 0.115, "reload_small" ); self.camera_fx[ "skid" ] = new vehicle_camera_fx(); [[ self.camera_fx[ "skid" ] ]]->init( 0.25, 0.35, 0.1, 0.115 ); } self.last_screen_dirt = 0; self.screen_dirt_delay = 0; speed_fraction = 0; while ( 1 ) { speed = Length( self GetVelocity() ); max_speed = ( speed < 0 ? self GetMaxReverseSpeed() : self GetMaxSpeed() ); speed_fraction = ( max_speed > 0 ? Abs(speed) / max_speed : 0 ); self.skidding = false; for ( i = 0; i < self.wheel_fx.size; i++ ) { [[ self.wheel_fx[i] ]]->update( localClientNum, self, speed_fraction ); } // [[ self.camera_fx[ "speed" ] ]]->update( localClientNum, self, speed_fraction ); // // if ( self.skidding ) // { // [[ self.camera_fx[ "skid" ] ]]->update( localClientNum, self, ( speed_fraction < 0.25 ? 0.25 : 1 ) ); // } wait( 0.1 ); } } function get_wheel_fx( type, surface ) { fxarray = undefined; if ( type == "tread" ) { fxarray = self.treadfxnamearray; } else if ( type == "peel" ) { fxarray = self.peelfxnamearray; } else if ( type == "skid" ) { fxarray = self.skidfxnamearray; } if( isdefined( fxarray ) ) { return fxarray[ surface ]; } return undefined; } function play_driving_fx_firstperson( localClientNum, speed, speed_fraction ) { const normal_speed_fraction = 0.25; // in yo face! if ( speed > 0 && speed_fraction >= normal_speed_fraction ) { viewangles = getlocalclientangles( localClientNum ); pitch = angleclamp180( viewangles[0] ); const max_additional_time = 1000; const no_effects_pitch = -10.0; // 10 degress up, no dirt const full_effects_pitch = 10.0; // 10 down, full dirt if ( pitch > no_effects_pitch ) { current_additional_time = 0; if ( pitch < full_effects_pitch ) { current_additional_time = max_additional_time * ( ( (pitch - full_effects_pitch) / ( no_effects_pitch - full_effects_pitch ) ) ); } if ( self.last_screen_dirt + self.screen_dirt_delay + current_additional_time < getrealtime() ) { screen_fx_type = self correct_surface_type_for_screen_fx(); if ( screen_fx_type == "dirt" ) { play_screen_fx_dirt( localClientNum ); } else { play_screen_fx_dust( localClientNum ); } self.last_screen_dirt = getrealtime(); self.screen_dirt_delay = RandomIntRange( 250, 500 ); } } } } function collision_thread( localClientNum ) { self endon( "entityshutdown" ); self endon( "exit_vehicle" ); while( 1 ) { self waittill( "veh_collision", hip, hitn, hit_intensity ); if ( self IsLocalClientDriver( localClientNum ) ) { //println( "veh_collision " + hit_intensity ); player = getlocalplayer( localClientNum ); if ( isdefined( self.driving_fx_collision_override ) ) { self [[ self.driving_fx_collision_override ]]( localClientNum, player, hip, hitn, hit_intensity ); } else { if( isdefined( player ) && isdefined( hit_intensity ) ) { if( hit_intensity > self.heavyCollisionSpeed ) { volume = get_impact_vol_from_speed(); if (isdefined (self.sounddef)) { alias = self.sounddef + "_suspension_lg_hd"; } else { alias = "veh_default_suspension_lg_hd"; } id = PlaySound( 0, alias, self.origin, volume); if( isdefined( self.heavyCollisionRumble ) ) { player PlayRumbleOnEntity( localClientNum, self.heavyCollisionRumble ); } } else if( hit_intensity > self.lightCollisionSpeed ) { volume = get_impact_vol_from_speed(); if (isdefined (self.sounddef)) { alias = self.sounddef + "_suspension_lg_lt"; } else { alias = "veh_default_suspension_lg_lt"; } id = PlaySound( 0, alias, self.origin, volume ); if( isdefined( self.lightCollisionRumble ) ) { player PlayRumbleOnEntity( localClientNum, self.lightCollisionRumble ); } } } } } } } function jump_landing_thread( localClientNum ) { self endon( "entityshutdown" ); self endon( "exit_vehicle" ); while( 1 ) { self waittill( "veh_landed" ); if ( self IsLocalClientDriver( localClientNum ) ) { player = getlocalplayer( localClientNum ); if( isdefined( player ) ) { if ( isdefined( self.driving_fx_jump_landing_override ) ) { self [[ self.driving_fx_jump_landing_override ]]( localClientNum, player ); } else { volume = get_impact_vol_from_speed(); if (isdefined (self.sounddef)) { alias = self.sounddef + "_suspension_lg_hd"; } else { alias = "veh_default_suspension_lg_hd"; } id = PlaySound( 0, alias, self.origin, volume); if( isdefined( self.jumpLandingRumble ) ) { player PlayRumbleOnEntity( localClientNum, self.jumpLandingRumble ); } } } } } } function suspension_thread( localClientNum ) { self endon( "entityshutdown" ); self endon( "exit_vehicle" ); while( 1 ) { self waittill( "veh_suspension_limit_activated" ); if ( self IsLocalClientDriver( localClientNum ) ) { player = getlocalplayer( localClientNum ); if( isdefined( player ) ) { volume = get_impact_vol_from_speed(); if (isdefined (self.sounddef)) { alias = self.sounddef + "_suspension_lg_lt"; } else { alias = "veh_default_suspension_lg_lt"; } id = PlaySound( 0, alias, self.origin, volume); player PlayRumbleOnEntity( localClientNum, "damage_light" ); } } } } function get_impact_vol_from_speed( ) { // values to map to a linear scale curspeed = self GetSpeed(); maxSpeed = self GetMaxSpeed(); volume = audio::scale_speed( 0, maxSpeed, 0, 1, curspeed ); volume = volume * volume * volume; return volume; } function any_wheel_colliding() { return ( self iswheelcolliding( "front_left" ) || self iswheelcolliding( "front_right" ) || self iswheelcolliding( "back_left" ) || self iswheelcolliding( "back_right" ) ); } function dirt_surface_type( surface_type ) { switch( surface_type ) { case "dirt": case "mud": case "gravel": case "grass": case "foliage": case "sand": case "snow": case "water": return true; } return false; } function correct_surface_type_for_screen_fx() { right_rear = self GetWheelSurface("back_right"); left_rear = self GetWheelSurface("back_left"); // PrintLn("surfacetypes: " + left_rear + " " + right_rear ); if ( dirt_surface_type( right_rear ) ) return "dirt"; if ( dirt_surface_type( left_rear ) ) return "dirt"; return "dust"; } function play_screen_fx_dirt(localClientNum) { // support for this has been removed with the .menu system /* pick_one = RandomIntRange(0,4); if ( pick_one == 0 ) { AnimateUI( localClientNum, "fullscreen_dirt", "dirt", "in", 0 ); } else if ( pick_one == 1 ) { AnimateUI( localClientNum, "fullscreen_dirt", "dirt_right_splash", "in", 0 ); } else if ( pick_one == 2 ) { AnimateUI( localClientNum, "fullscreen_dirt", "dirt_left_splash", "in", 0 ); } else { AnimateUI( localClientNum, "fullscreen_dirt", "blurred_dirt_random", "in", 0 ); } */ } function play_screen_fx_dust(localClientNum) { // support for this has been removed with the .menu system /* pick_one = RandomIntRange(0,4); if ( pick_one == 0 ) { AnimateUI( localClientNum, "fullscreen_dust", "dust", "in", 0 ); } else if ( pick_one == 1 ) { AnimateUI( localClientNum, "fullscreen_dust", "dust_right_splash", "in", 0 ); } else if ( pick_one == 2 ) { AnimateUI( localClientNum, "fullscreen_dust", "dust_left_splash", "in", 0 ); } else { AnimateUI( localClientNum, "fullscreen_dust", "blurred_dust_random", "in", 0 ); } */ }