2023-04-13 17:30:38 +02:00

516 lines
21 KiB
Plaintext

#using scripts\codescripts\struct;
#using scripts\shared\clientfield_shared;
#using scripts\shared\system_shared;
#using scripts\shared\util_shared;
#using scripts\shared\vehicle_shared;
#using scripts\mp\_util;
#using scripts\mp\_vehicle;
// _qrdrone.csc
// Sets up clientside behavior for the qrdrone
#precache( "client_fx", "killstreaks/fx_drgnfire_light_red_3p" );
#precache( "client_fx", "killstreaks/fx_drgnfire_light_green_3p" );
#precache( "client_fx", "killstreaks/fx_drgnfire_light_green_1p" );
#namespace qrdrone;
function autoexec __init__sytem__() { system::register("qrdrone",&__init__,undefined,undefined); }
function __init__()
{
type = "qrdrone_mp";
clientfield::register( "helicopter", "qrdrone_state", 1, 3, "int",&stateChange, !true, !true );
clientfield::register( "vehicle", "qrdrone_state", 1, 3, "int",&stateChange, !true, !true );
level._effect["qrdrone_enemy_light"] = "killstreaks/fx_drgnfire_light_red_3p";
level._effect["qrdrone_friendly_light"] = "killstreaks/fx_drgnfire_light_green_3p";
level._effect["qrdrone_viewmodel_light"] = "killstreaks/fx_drgnfire_light_green_1p";
// vehicle flags
clientfield::register( "helicopter", "qrdrone_countdown", 1, 1, "int", &start_blink, !true, !true );
clientfield::register( "helicopter", "qrdrone_timeout", 1, 1, "int", &final_blink, !true, !true );
clientfield::register( "vehicle", "qrdrone_countdown", 1, 1, "int", &start_blink, !true, !true );
clientfield::register( "vehicle", "qrdrone_timeout", 1, 1, "int", &final_blink, !true, !true );
clientfield::register( "vehicle", "qrdrone_out_of_range", 1, 1, "int", &out_of_range_update, !true, !true );
vehicle::add_vehicletype_callback( "qrdrone_mp",&spawned );
}
function spawned( localClientNum ) // self == qrdrone
{
self util::waittill_dobj( localClientNum );
self thread restartFX( localClientNum, 0 );
self thread collisionHandler(localClientNum);
self thread engineStutterHandler(localClientNum);
self thread QRDrone_watch_distance();
}
//******************************************************************
// *
// *
//******************************************************************
function stateChange( localClientNum, oldVal, newVal, bNewEnt, bInitialSnap, fieldName, bWasTimeJump )
{
self endon("entityshutdown");
self util::waittill_dobj( localClientNum );
self restartFX( localClientNum, newVal );
}
//******************************************************************
// *
// *
//******************************************************************
function restartFX( localClientNum, blinkStage ) // self == qrdrone
{
self notify( "restart_fx" );
/#println( "Restart QRDrone FX: stage " + blinkStage );#/
switch( blinkStage )
{
case 0:
{
self spawn_solid_fx( localClientNum );
break;
}
case 1:
{
self.fx_interval = 1.0;
self spawn_blinking_fx( localClientNum );
break;
}
case 2:
{
self.fx_interval = .133;
self spawn_blinking_fx( localClientNum );
break;
}
case 3:
{
self notify( "stopfx" );
self notify( "fx_death" );
return;
}
}
self thread watchRestartFX( localClientNum );
}
//******************************************************************
// *
// *
//******************************************************************
function watchRestartFX( localClientNum )
{
self endon("entityshutdown");
level util::waittill_any( "demo_jump", "player_switch", "killcam_begin", "killcam_end" );
self restartFX( localClientNum, clientfield::get( "qrdrone_state" ));
}
//******************************************************************
// *
// *
//******************************************************************
function spawn_solid_fx( localClientNum ) // self == qrdrone
{
if ( self IsLocalClientDriver( localClientNum ) )
{
fx_handle = playfxontag( localClientNum, level._effect["qrdrone_viewmodel_light"], self, "tag_body" );
}
else if ( self util::friend_not_foe( localClientNum ) )
{
fx_handle = playfxontag( localClientNum, level._effect["qrdrone_friendly_light"], self, "tag_body" );
}
else
{
fx_handle = playfxontag( localClientNum, level._effect["qrdrone_enemy_light"], self, "tag_body" );
}
self thread cleanupFX( localClientNum, fx_handle );
}
//******************************************************************
// *
// *
//******************************************************************
function spawn_blinking_fx( localClientNum )
{
self thread blink_fx_and_sound( localClientNum, "wpn_qr_alert" );
}
//******************************************************************
// *
// *
//******************************************************************
function blink_fx_and_sound( localClientNum, soundAlias )
{
self endon( "entityshutdown" );
self endon( "restart_fx" );
self endon( "fx_death" );
if ( !isdefined( self.interval ) )
{
self.interval = 1.0;
}
while(1)
{
self PlaySound( localClientNum, soundAlias );
self spawn_solid_fx( localClientNum );
util::server_wait( localClientNum, self.interval / 2);
self notify( "stopfx" );
util::server_wait( localClientNum, self.interval / 2);
self.interval = (self.interval / 1.17);
if (self.interval < .1)
{
self.interval = .1;
}
}
}
//******************************************************************
// *
// *
//******************************************************************
function cleanupFX( localClientNum, handle )
{
self util::waittill_any( "entityshutdown", "blink", "stopfx", "restart_fx" );
stopfx( localClientNum, handle );
}
function start_blink( localClientNum, oldVal, newVal, bNewEnt, bInitialSnap, fieldName, bWasTimeJump )
{
if (!newVal)
return;
self notify("blink");
}
// this second state is necessary so killcams show the appropriate "fast blink" state
function final_blink( localClientNum, oldVal, newVal, bNewEnt, bInitialSnap, fieldName, bWasTimeJump )
{
if (!newVal)
return;
self.interval = .133;
}
function out_of_range_update( localClientNum, oldVal, newVal, bNewEnt, bInitialSnap, fieldName, bWasTimeJump )
{
model = GetUIModel( GetUIModelForController( localClientNum ), "vehicle.outOfRange" );
if ( isdefined( model ) )
{
SetUIModelValue( model, newVal );
}
}
function loop_local_sound( localClientNum, alias, interval, fx )
{
self endon( "entityshutdown" );
self endon( "stopfx" );
level endon( "demo_jump" );
level endon( "player_switch" );
// also playing the blinking light fx with the sound
if ( !isdefined( self.interval ) )
{
self.interval = interval;
}
while(1)
{
self PlaySound( localClientNum, alias );
self spawn_solid_fx( localClientNum );
util::server_wait( localClientNum, self.interval / 2);
self notify( "stopfx" );
util::server_wait( localClientNum, self.interval / 2);
self.interval = (self.interval / 1.17);
if (self.interval < .1)
{
self.interval = .1;
}
}
}
function check_for_player_switch_or_time_jump( localClientNum )
{
self endon("entityshutdown");
level util::waittill_any( "demo_jump", "player_switch", "killcam_begin" );
self notify( "stopfx" );
waittillframeend;
self thread blink_light( localClientNum );
if ( isdefined( self.blinkStartTime ) && self.blinkStartTime <= level.serverTime )
{
self.interval = 1;
self thread start_blink( localClientNum, true );
}
else
{
self spawn_solid_fx( localClientNum );
}
self thread check_for_player_switch_or_time_jump( localClientNum );
}
function blink_light( localClientNum )
{
self endon("entityshutdown");
level endon( "demo_jump" );
level endon( "player_switch" );
level endon( "killcam_begin" );
self waittill("blink");
if ( !isdefined( self.blinkStartTime ) )
{
self.blinkStartTime = level.serverTime;
}
if ( self IsLocalClientDriver( localClientNum ) )
{
self thread loop_local_sound( localClientNum, "wpn_qr_alert", 1, level._effect["qrdrone_viewmodel_light"] );
}
else if ( self util::friend_not_foe( localClientNum ) )
{
self thread loop_local_sound( localClientNum, "wpn_qr_alert", 1, level._effect["qrdrone_friendly_light"] );
}
else
{
self thread loop_local_sound( localClientNum, "wpn_qr_alert", 1, level._effect["qrdrone_enemy_light"] );
}
}
function collisionHandler( localClientNum )
{
self endon( "entityshutdown" );
while( 1 )
{
self waittill( "veh_collision", hip, hitn, hit_intensity );
driver_local_client = self GetLocalClientDriver();
if( isdefined( driver_local_client ) )
{
//println( "veh_collision " + hit_intensity );
player = getlocalplayer( driver_local_client );
if( isdefined( player ) )
{
// todo - play sound here also
if( hit_intensity > 15 )
{
player PlayRumbleOnEntity( driver_local_client, "damage_heavy" );
}
else
{
player PlayRumbleOnEntity( driver_local_client, "damage_light" );
}
}
}
}
}
function engineStutterHandler( localClientNum )
{
self endon( "entityshutdown" );
while( 1 )
{
self waittill( "veh_engine_stutter" );
if ( self IsLocalClientDriver( localClientNum ) )
{
player = getlocalplayer( localClientNum );
if( isdefined( player ) )
{
player PlayRumbleOnEntity( localClientNum, "rcbomb_engine_stutter" );
}
}
}
}
function getMinimumFlyHeight()
{
if ( !isdefined( level.airsupportHeightScale ) )
level.airsupportHeightScale = 1;
airsupport_height = struct::get( "air_support_height", "targetname");
if ( isdefined(airsupport_height) )
{
planeFlyHeight = airsupport_height.origin[2];
}
else
{
/#
PrintLn("WARNING: Missing air_support_height entity in the map. Using default height.");
#/
// original system
planeFlyHeight = 850;
if ( isdefined( level.airsupportHeightScale ) )
{
level.airsupportHeightScale = GetDvarInt( "scr_airsupportHeightScale", level.airsupportHeightScale );
planeFlyHeight *= GetDvarInt( "scr_airsupportHeightScale", level.airsupportHeightScale );
}
if ( isdefined( level.forceAirsupportMapHeight ) )
{
planeFlyHeight += level.forceAirsupportMapHeight;
}
}
return planeFlyHeight;
}
function QRDrone_watch_distance()
{
self endon ("entityshutdown" );
qrdrone_height = struct::get( "qrdrone_height", "targetname");
if ( isdefined(qrdrone_height) )
{
self.maxHeight = qrdrone_height.origin[2];
}
else
{
self.maxHeight = int(getMinimumFlyHeight());
}
self.maxDistance = 12800;
level.mapCenter = GetMapCenter();
self.minHeight = level.mapCenter[2] - 800;
// shouldn't be possible to start out of range, but just in case
inRangePos = self.origin;
soundent = spawn (0, self.origin, "script_origin" );
soundent linkto(self);
// end static on vehicle death
self thread QRDrone_staticStopOnDeath( soundent );
// loop
while ( true )
{
if ( !self QRDrone_in_range() )
{
// increase static with distance from exit point or distance to heli in proximity
staticAlpha = 0;
while ( !self QRDrone_in_range() )
{
if ( isdefined( self.heliInProximity ) )
{
dist = distance( self.origin, self.heliInProximity.origin );
staticAlpha = 1 - ( (dist-150) / (300-150) );
}
else
{
dist = distance( self.origin, inRangePos );
staticAlpha = min( 1, dist/200 );
}
// SOUND: put sound code here to change the volume of the static while the player is
// in static. staticAlpha will be 0 - 1. 0 being no static, 1 being full static.
sid = soundent playloopsound ( "veh_qrdrone_static_lp", .2 );
self vehicle::set_static_amount( staticAlpha * 2 );
wait ( 0.05 );
}
// fade out static
self thread QRDrone_staticFade( staticAlpha, soundent, sid );
}
inRangePos = self.origin;
wait ( 0.05 );
}
}
function QRDrone_in_range()
{
if ( self.origin[2] < self.maxHeight && self.origin[2] > self.minHeight )
{
if ( self isInsideHeightLock() )
{
return true;
}
}
return false;
}
function QRDrone_staticFade( staticAlpha, sndent, sid )
{
self endon ( "entityshutdown" );
while( self QRDrone_in_range() )
{
staticAlpha -= 0.05;
if ( staticAlpha <= 0 )
{
// SOUND: Put call here to completely turn static sound off
sndent StopAllLoopSounds (.5);
//delete sid;
self vehicle::set_static_amount( 0 );
break;
}
// SOUND: Put call here to change volume of static based on staticAlpha
setsoundvolumerate( sid, .6 );
setsoundvolume( sid, staticAlpha );
self vehicle::set_static_amount( staticAlpha * 2 );
wait( 0.05 );
}
}
function QRDrone_staticStopOnDeath( sndent )
{
self waittill ( "entityshutdown" );
sndent StopAllLoopSounds (.1);
sndent delete();
}