516 lines
21 KiB
Plaintext
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();
|
|
}
|