1567 lines
40 KiB
Plaintext
1567 lines
40 KiB
Plaintext
#include maps\mp\_utility;
|
|
#include common_scripts\utility;
|
|
|
|
EMP_GRENADE_TIME = 3.5;
|
|
CONST_default_height_z = 2032;
|
|
|
|
CONST_streak_static_disabled = 0;
|
|
CONST_streak_static_enabled = 1;
|
|
CONST_streak_static_damage = 2;
|
|
CONST_streak_static_range1 = 3;
|
|
CONST_streak_static_range2 = 4;
|
|
CONST_streak_static_range3 = 5;
|
|
CONST_streak_static_range4 = 6;
|
|
CONST_streak_static_fullnotext = 7;
|
|
|
|
CONST_VEHICLE_SPAWNFLAG = 16;
|
|
|
|
//===========================================
|
|
// init
|
|
//===========================================
|
|
init()
|
|
{
|
|
if(GetDvarInt("virtuallobbyactive", 0))
|
|
return;
|
|
|
|
/#
|
|
if ( GetDvar( "scr_scorestreak_skip_aerial", "0" ) != "0" )
|
|
return;
|
|
#/
|
|
|
|
level.helis = [];
|
|
level.littleBirds = [];
|
|
|
|
level.heli_leave_nodes = getEntOrStructArray( "heli_leave", "targetname" );
|
|
level.heli_crash_nodes = getEntOrStructArray( "heli_crash_start", "targetname" );
|
|
|
|
assertEx( level.heli_leave_nodes.size, "No \"heli_leave\" nodes found in map!" );
|
|
assertEx( level.heli_crash_nodes.size, "No \"heli_crash_start\" nodes found in map!" );
|
|
|
|
level.chopper_fx["explode"]["death"] = [];
|
|
level.chopper_fx["explode"]["air_death"] = [];
|
|
level.chopper_fx["damage"]["light_smoke"] = loadfx ("vfx/trail/smoke_trail_white_heli_emitter");
|
|
level.chopper_fx["damage"]["heavy_smoke"] = loadfx ("vfx/trail/smoke_trail_black_heli_emitter");
|
|
level.chopper_fx["damage"]["on_fire"] = loadfx ("vfx/fire/helicopter_damaged_fire_m");
|
|
level.chopper_fx["explode"]["large"] = loadfx ("fx/explosions/helicopter_explosion_secondary_small");
|
|
// level.chopper_fx["light"]["left"] = loadfx( "vfx/lights/aircraft_light_wingtip_green" );
|
|
// level.chopper_fx["light"]["right"] = loadfx( "vfx/lights/aircraft_light_wingtip_red" );
|
|
// level.chopper_fx["light"]["belly"] = loadfx( "vfx/lights/aircraft_light_red_blink" );
|
|
// level.chopper_fx["light"]["tail"] = loadfx( "vfx/lights/aircraft_light_white_blink" );
|
|
level.chopper_fx["rocketlaunch"]["warbird"] = LoadFX( "vfx/muzzleflash/rocket_launch_air_to_ground" );
|
|
|
|
level.heli_sound["allies"]["hit"] = "warbird_death_explo";
|
|
level.heli_sound["axis"]["hit"] = "warbird_death_explo";
|
|
// level.heli_sound["allies"]["hitsecondary"] = "cobra_helicopter_secondary_exp";
|
|
// level.heli_sound["axis"]["hitsecondary"] = "cobra_helicopter_secondary_exp";
|
|
level.heli_sound["allies"]["spinloop"] = "warbird_death_spin_loop";
|
|
level.heli_sound["axis"]["spinloop"] = "warbird_death_spin_loop";
|
|
// level.heli_sound["allies"]["spinstart"] = "cobra_helicopter_dying_layer";
|
|
// level.heli_sound["axis"]["spinstart"] = "cobra_helicopter_dying_layer";
|
|
level.heli_sound["allies"]["crash"] = "warbird_air_death";
|
|
level.heli_sound["axis"]["crash"] = "warbird_air_death";
|
|
|
|
level._effect[ "flare" ] = loadfx( "vfx/lensflare/flares_warbird" );
|
|
|
|
level.heli_attract_strength = 1000;
|
|
level.heli_attract_range = 4096;
|
|
level.heli_maxhealth = 2000;
|
|
level.heli_targeting_delay = 0.5;
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// makeHeliType
|
|
//===========================================
|
|
makeHeliType( heliType, deathFx, lightFXFunc )
|
|
{
|
|
level.chopper_fx["explode"]["death"][ heliType ] = loadFx( deathFX );
|
|
level.lightFxFunc[ heliType ] = lightFXFunc;
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// addAirExplosion
|
|
//===========================================
|
|
addAirExplosion( heliType, explodeFx )
|
|
{
|
|
level.chopper_fx["explode"]["air_death"][ heliType ] = loadFx( explodeFx );
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// addToHeliList
|
|
//===========================================
|
|
addToHeliList()
|
|
{
|
|
level.helis[self getEntityNumber()] = self;
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// removeFromHeliList
|
|
//===========================================
|
|
removeFromHeliList( entityNumber )
|
|
{
|
|
level.helis[entityNumber] = undefined;
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// addToLittleBirdList
|
|
//===========================================
|
|
addToLittleBirdList( lbType )
|
|
{
|
|
level.littleBirds[self GetEntityNumber()] = self;
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// removeFromLittleBirdListOnDeath
|
|
//===========================================
|
|
removeFromLittleBirdListOnDeath( lbType )
|
|
{
|
|
entNum = self GetEntityNumber();
|
|
|
|
self waittill ( "death" );
|
|
|
|
level.littleBirds[entNum] = undefined;
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// exceededMaxLittlebirds
|
|
//===========================================
|
|
exceededMaxLittlebirds( streakName )
|
|
{
|
|
if( level.littleBirds.size >= 4 )
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// heli_leave_on_disconnect
|
|
//===========================================
|
|
heli_leave_on_disconnect( owner )
|
|
{
|
|
self endon ( "death" );
|
|
self endon ( "helicopter_done" );
|
|
|
|
owner waittill( "disconnect" );
|
|
|
|
self thread heli_leave();
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// heli_leave_on_changeTeams
|
|
//===========================================
|
|
heli_leave_on_changeTeams( owner )
|
|
{
|
|
self endon ( "death" );
|
|
self endon ( "helicopter_done" );
|
|
|
|
owner waittill_any( "joined_team", "joined_spectators" );
|
|
|
|
self thread heli_leave();
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// heli_ModifyDamage
|
|
//===========================================
|
|
heli_ModifyDamage( attacker, weapon, type, damage )
|
|
{
|
|
modifiedDamage = self maps\mp\gametypes\_damage::modifyDamage( attacker, weapon, type, damage );
|
|
|
|
if( modifiedDamage > 0 )
|
|
self heli_staticDamage( weapon, type, modifiedDamage );
|
|
|
|
// self thread heli_addRecentDamage( modifiedDamage );
|
|
|
|
return modifiedDamage;
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// heli_addRecentDamage
|
|
//===========================================
|
|
heli_addRecentDamage( damage )
|
|
{
|
|
self endon( "death" );
|
|
|
|
self.recentDamageAmount += damage;
|
|
|
|
wait ( 4.0 );
|
|
|
|
self.recentDamageAmount -= damage;
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// heli_leave_on_timeout
|
|
//===========================================
|
|
heli_leave_on_timeout( timeOut )
|
|
{
|
|
self endon ( "death" );
|
|
self endon ( "helicopter_done" );
|
|
|
|
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( timeOut );
|
|
|
|
self thread heli_leave();
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// heli_leave_on_gameended
|
|
//===========================================
|
|
heli_leave_on_gameended( owner )
|
|
{
|
|
self endon ( "death" );
|
|
self endon ( "helicopter_done" );
|
|
|
|
level waittill ( "game_ended" );
|
|
|
|
self thread heli_leave();
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// heli_leave_on_timeout
|
|
//===========================================
|
|
heli_leave( leavePos )
|
|
{
|
|
self notify( "leaving" );
|
|
|
|
self.isLeaving = true;
|
|
|
|
self ClearLookAtEnt();
|
|
|
|
leaveNode = undefined;
|
|
|
|
if( !isDefined( leavePos ) )
|
|
{
|
|
leaveNode = heli_pick_fly_node( level.heli_leave_nodes );
|
|
leavePos = leaveNode.origin;
|
|
}
|
|
|
|
// make sure it doesn't fly away backwards
|
|
endEnt = Spawn( "script_origin", leavePos );
|
|
|
|
if( IsDefined( endEnt ) )
|
|
{
|
|
self SetLookAtEnt( endEnt );
|
|
endEnt thread wait_and_delete( 3.0 );
|
|
}
|
|
|
|
self heli_reset();
|
|
self Vehicle_SetSpeed( 100, 45 );
|
|
if ( IsDefined( leaveNode ) )
|
|
{
|
|
if ( IsDefined( leaveNode.target ) )
|
|
{
|
|
self heli_fly_simple_path( leaveNode );
|
|
}
|
|
else
|
|
{
|
|
self _setVehGoalPos( leaveNode.origin, false );
|
|
self waittillmatch( "goal" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self _setVehGoalPos( leavePos, false );
|
|
self waittillmatch( "goal" );
|
|
}
|
|
self notify( "death" );
|
|
|
|
// give "death" notify time to process
|
|
wait ( 0.05 );
|
|
|
|
if( IsDefined( self.killCamEnt ) )
|
|
self.killCamEnt delete();
|
|
|
|
// decrement the faux vehicle count right before it is deleted this way we know for sure it is gone
|
|
decrementFauxVehicleCount();
|
|
|
|
self delete();
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// heli_pick_fly_node
|
|
//===========================================
|
|
heli_pick_fly_node( nodes )
|
|
{
|
|
// nodes = array_randomize( nodes );
|
|
start = self.origin;
|
|
nextNode = undefined;
|
|
|
|
/#
|
|
if ( GetDvar( "scr_heli_pick_fly_node_debug", "0" ) != "0" )
|
|
{
|
|
foreach ( node in nodes )
|
|
Sphere( node.origin, 100, ( 0, 1, 0 ), false, 300 );
|
|
}
|
|
#/
|
|
|
|
for ( i = 0; i < nodes.size; i++ )
|
|
{
|
|
end = nodes[i].origin;
|
|
if ( flyNodeOrgTracePassed( start, end, self ) )
|
|
{
|
|
dir = end - start;
|
|
dist = Distance( start, end );
|
|
dirRight = RotateVector( dir, ( 0, 90, 0 ) );
|
|
startWing = start + ( dirRight * 100 );
|
|
endWing = startWing + ( dir * dist );
|
|
if ( flyNodeOrgTracePassed( startWing, endWing, self ) )
|
|
{
|
|
dirLeft = RotateVector( dir , ( 0, -90, 0 ) );
|
|
startWing = start + ( dirLeft * 100 );
|
|
endWing = startWing + ( dir * dist );
|
|
if ( flyNodeOrgTracePassed( startWing, endWing, self ) )
|
|
{
|
|
return nodes[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return nodes[ RandomInt( nodes.size ) ];
|
|
}
|
|
|
|
flyNodeOrgTracePassed( start, end, ignoreEnt )
|
|
{
|
|
trace = BulletTrace( start, end, false, ignoreEnt, false, false, true, false, false );
|
|
passed = ( trace["fraction"] >= 1 );
|
|
/#
|
|
if ( GetDvar( "scr_heli_pick_fly_node_debug", "0" ) != "0" )
|
|
{
|
|
if ( passed )
|
|
Line( start, end, ( 0, 1, 0 ), 1, false, 300 );
|
|
else
|
|
Line( start, end, ( 1, 0, 0 ), 1, false, 300 );
|
|
}
|
|
|
|
return passed;
|
|
#/
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// wait_and_delete
|
|
//===========================================
|
|
wait_and_delete( waitTime )
|
|
{
|
|
self endon( "death" );
|
|
level endon( "game_ended" );
|
|
|
|
wait( waitTime );
|
|
|
|
self delete();
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// deleteAfterTime
|
|
//===========================================
|
|
deleteAfterTime( delay )
|
|
{
|
|
wait ( delay );
|
|
|
|
self delete();
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// heli_reset
|
|
//===========================================
|
|
heli_reset()
|
|
{
|
|
// resets helicopter's motion values
|
|
self clearTargetYaw();
|
|
self clearGoalYaw();
|
|
self Vehicle_SetSpeed( 60, 25 );
|
|
self setyawspeed( 100, 45, 45 );
|
|
self setmaxpitchroll( 30, 30 );
|
|
self setneargoalnotifydist( 100 );
|
|
self setturningability(1.0);
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// _setVehGoalPos
|
|
//===========================================
|
|
_setVehGoalPos( goalPosition, shouldStop )
|
|
{
|
|
if( !isDefined( shouldStop ) )
|
|
shouldStop = false;
|
|
|
|
self SetVehGoalPos( goalPosition, shouldStop );
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// heli_flares_monitor
|
|
//===========================================
|
|
heli_flares_monitor( extraFlares )
|
|
{
|
|
switch( self.heliType )
|
|
{
|
|
default:
|
|
self.numFlares = 1;
|
|
break;
|
|
}
|
|
|
|
if( IsDefined( extraFlares ) )
|
|
self.numFlares += extraFlares;
|
|
|
|
self thread handleIncomingStinger();
|
|
}
|
|
|
|
|
|
|
|
//===========================================
|
|
// handleIncomingStinger
|
|
//===========================================
|
|
handleIncomingStinger( functionOverride )
|
|
{
|
|
level endon ( "game_ended" );
|
|
self endon ( "death" );
|
|
self endon ( "crashing" );
|
|
self endon ( "leaving" );
|
|
self endon ( "helicopter_done" );
|
|
|
|
for( ;; )
|
|
{
|
|
level waittill ( "stinger_fired", player, missiles );
|
|
|
|
if( !maps\mp\_stingerm7::anyStingerMissileLockedOn( missiles, self ) )
|
|
continue;
|
|
|
|
if( !IsDefined( missiles ) )
|
|
continue;
|
|
|
|
if( IsDefined( functionOverride ) )
|
|
{
|
|
level thread [[ functionOverride ]]( missiles, player, player.team );
|
|
}
|
|
else
|
|
{
|
|
level thread watchMissileProximity( missiles, player, player.team );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// watchMissileProximity
|
|
//===========================================
|
|
watchMissileProximity( missiles, player, missileTeam ) // self == level
|
|
{
|
|
foreach( missile in missiles )
|
|
missile thread missileWatchProximity( player, missileTeam, missile.lockedStingerTarget );
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// missileWatchProximity
|
|
//===========================================
|
|
missileWatchProximity( player, missileTeam, missileTarget )
|
|
{
|
|
self endon( "death" );
|
|
missileTarget endon( "death" );
|
|
|
|
flaresTime = 5.0;
|
|
flaresDistance = 4000;
|
|
|
|
while( true )
|
|
{
|
|
if( !isDefined( missileTarget ) )
|
|
break;
|
|
|
|
center = missileTarget GetPointInBounds( 0, 0, 0 );
|
|
|
|
curDist = distance( self.origin, center );
|
|
|
|
if( IsDefined( missileTarget.player ) )
|
|
missileTarget.player thread doProximityAlarm( self, missileTarget );
|
|
|
|
if( curDist < flaresDistance )
|
|
{
|
|
if( missileTarget.numFlares > 0 || IsDefined( missileTarget.flaresTarget ) )
|
|
{
|
|
if ( IsDefined( missileTarget.owner ) && IsWarbird( missileTarget ) )
|
|
{
|
|
if ( missileTarget.numFlares == 2 )
|
|
missileTarget.owner SetClientOmnvar( "ui_warbird_flares", 1 );
|
|
else if ( missileTarget.numFlares == 1 )
|
|
missileTarget.owner SetClientOmnvar( "ui_warbird_flares", 2 );
|
|
missileTarget.owner PlayLocalSound( "paladin_deploy_flares" );
|
|
}
|
|
newTarget = missileTarget deployFlares( flaresTime );
|
|
PlayFXOnTag( getfx( "flare" ), newTarget, "tag_origin" );
|
|
if( !IsDefined( missileTarget.flaresTarget ) )
|
|
{
|
|
missileTarget.numFlares--;
|
|
level thread handleFlaresTimer( missileTarget, newTarget, flaresTime );
|
|
}
|
|
self Missile_SetTargetEnt( newTarget );
|
|
return;
|
|
}
|
|
}
|
|
wait ( 0.05 );
|
|
}
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// deployFlares
|
|
//===========================================
|
|
deployFlares( time ) // self == heli/plane
|
|
{
|
|
org = (self GetTagOrigin("tag_origin")) + ( 0, 0, -50 );
|
|
flareObject = Spawn( "script_model", org );
|
|
flareObject SetModel( "tag_origin" );
|
|
flareObject.angles = self.angles;
|
|
|
|
if ( !IsDefined( self.flaresDeployedYaw ) )
|
|
self.flaresDeployedYaw = RandomFloatRange( -180, 180 );
|
|
else
|
|
self.flaresDeployedYaw = self.flaresDeployedYaw + 90;
|
|
|
|
vel = AnglesToForward( ( self.angles[0], self.flaresDeployedYaw, self.angles[2] ) );
|
|
vel = vehicleModifyFlareVector( vel );
|
|
|
|
flareObject MoveGravity( vel, time );
|
|
|
|
flareObject thread deleteAfterTime( time );
|
|
|
|
return flareObject;
|
|
}
|
|
|
|
|
|
vehicleModifyFlareVector( velocityVec ) // self == heli/plane
|
|
{
|
|
if ( self.vehicleType == "warbird" )
|
|
{
|
|
return ( VectorNormalize( velocityVec + ( 0, 0, -0.2 ) ) * 300 );
|
|
}
|
|
else if ( self.vehicleType == "paladin" )
|
|
{
|
|
return ( VectorNormalize( velocityVec + ( 0, 0, -0.5 ) ) * 2000 );
|
|
}
|
|
else // strafing run
|
|
{
|
|
return ( VectorNormalize( velocityVec + ( 0, 0, -0.4 ) ) * 1000 );
|
|
}
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// handleFlaresTimer
|
|
//===========================================
|
|
handleFlaresTimer( missileTarget, flaresTarget, flaresTime )
|
|
{
|
|
missileTarget endon( "death" );
|
|
|
|
missileTarget.flaresTarget = flaresTarget;
|
|
|
|
wait flaresTime;
|
|
|
|
missileTarget.flaresTarget = undefined;
|
|
|
|
if ( IsDefined( missileTarget.owner ) && IsWarbird( missileTarget ) )
|
|
missileTarget.owner SetClientOmnvar( "ui_warbird_flares", 0 );
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// HasTag
|
|
//===========================================
|
|
HasTag( model, tag )
|
|
{
|
|
partCount = GetNumParts( model );
|
|
for ( i = 0; i < partCount; i++ )
|
|
{
|
|
if( toLower( GetPartName( model, i)) == toLower( tag ))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// IsWarbird
|
|
//===========================================
|
|
IsWarbird( heli )
|
|
{
|
|
return IsDefined( heli.heli_type ) && ( heli.heli_type == "warbird" );
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// doProximityAlarm
|
|
//===========================================
|
|
doProximityAlarm( missile, heli )
|
|
{
|
|
self endon( "disconnect" );
|
|
|
|
if ( shouldStopProximityAlarm( missile, heli ) || IsDefined( heli.incomingMissileSound ) )
|
|
return;
|
|
|
|
if ( IsWarbird( heli ) )
|
|
self SetClientOmnvar( "ui_warbird_flares", 3 );
|
|
|
|
self PlayLocalSound( "mp_aerial_enemy_locked" );
|
|
heli.incomingMissileSound = true;
|
|
|
|
while( true )
|
|
{
|
|
if( shouldStopProximityAlarm( missile, heli ) )
|
|
{
|
|
self StopLocalSound( "mp_aerial_enemy_locked" );
|
|
heli.incomingMissileSound = undefined;
|
|
return;
|
|
}
|
|
|
|
waitframe();
|
|
}
|
|
}
|
|
|
|
//===========================================
|
|
// playerFakeShootPaintMissile
|
|
//===========================================
|
|
playerFakeShootPaintMissile( soundEnt ) // self == player
|
|
{
|
|
dir = VectorNormalize( AnglesToForward( self GetPlayerAngles() ) );
|
|
right = VectorNormalize( AnglesToRight( self GetPlayerAngles() ) );
|
|
start = self GetEye() + ( dir * 100 );
|
|
end = start + ( dir * 20000 );
|
|
trace = BulletTrace( start, end, false );
|
|
|
|
if ( trace[ "fraction" ] == 1 )
|
|
return;
|
|
|
|
Earthquake( 0.1, 1, self GetEye(), 500 );
|
|
|
|
start = self GetEye() + right * -1 * 50;
|
|
end = trace["position"];
|
|
|
|
rocket = MagicBullet( "paint_missile_killstreak_mp", start, end, self );
|
|
rocket.owner = self;
|
|
rocket thread watchPaintGrenade();
|
|
self thread playerFireSounds( soundEnt, "paladin_threat_bomb_shot_2d", "paladin_threat_bomb_shot_3d" );
|
|
}
|
|
|
|
playerFakeShootPaintGrenadeAtTarget( soundEnt, startPos, targetPos, stunPlayers, vehicle ) // self == player
|
|
{
|
|
GRENADE_SPEED = 5000;
|
|
|
|
Earthquake( 0.2, 1, self GetViewOrigin(), 300 );
|
|
|
|
grenadeForward = VectorNormalize( targetPos - startPos );
|
|
grenadeVelocity = grenadeForward * GRENADE_SPEED;
|
|
|
|
grenade = MagicGrenadeManual( "paint_grenade_killstreak_mp", startPos, grenadeVelocity, 2, self );
|
|
grenade.owner = self;
|
|
grenade thread watchPaintGrenade( stunPlayers, vehicle );
|
|
|
|
self thread playerFireSounds( soundEnt, "recon_drn_launcher_shot_plr", "recon_drn_launcher_shot_npc" );
|
|
self playRumbleOnEntity( "damage_heavy" );
|
|
}
|
|
|
|
playerFakeShootEmpGrenadeAtTarget( soundEnt, startPos, targetPos )
|
|
{
|
|
GRENADE_SPEED = 5000;
|
|
|
|
Earthquake( 0.2, 1, self GetViewOrigin(), 300 );
|
|
|
|
grenadeForward = VectorNormalize( targetPos - startPos );
|
|
grenadeVelocity = grenadeForward * GRENADE_SPEED;
|
|
|
|
grenade = MagicGrenadeManual( "emp_grenade_killstreak_mp", startPos, grenadeVelocity, 2, self );
|
|
grenade.owner = self;
|
|
|
|
self thread playerFireSounds( soundEnt, "recon_drn_launcher_shot_plr", "recon_drn_launcher_shot_npc" );
|
|
self playRumbleOnEntity( "damage_heavy" );
|
|
}
|
|
|
|
playerFireSounds( soundEnt, sound2d, sound3d )
|
|
{
|
|
if ( IsDefined( sound3d ) )
|
|
soundEnt PlaySoundOnMovingEnt( sound3d );
|
|
|
|
/#
|
|
if ( GetDvar( "scr_paladin_stay_on_ground", "0" ) != "0" )
|
|
return;
|
|
#/
|
|
if ( IsDefined( sound2d ) )
|
|
self PlayLocalSound( sound2d );
|
|
}
|
|
|
|
watchPaintGrenade( stunPlayers, vehicle )
|
|
{
|
|
if ( !IsDefined( stunPlayers ) )
|
|
stunPlayers = false;
|
|
|
|
owner = self.owner;
|
|
owner endon( "disconnect" );
|
|
owner endon( "death" );
|
|
|
|
self waittill( "explode", position );
|
|
|
|
if ( owner isEMPed() && IsDefined( level.empEquipmentDisabled ) && level.empEquipmentDisabled )
|
|
return;
|
|
|
|
detectionGrenadeThink( position, owner, stunPlayers, vehicle );
|
|
}
|
|
|
|
detectionGrenadeThink( position, owner, stunPlayers, vehicle )
|
|
{
|
|
if ( !IsDefined( stunPlayers ) )
|
|
stunPlayers = false;
|
|
|
|
assert( isDefined( owner ) );
|
|
|
|
foreach ( guy in level.players )
|
|
{
|
|
if ( !IsDefined( guy ) || !isReallyAlive( guy ) || !IsAlliedSentient( owner, guy ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
thread maps\mp\_threatdetection::detection_grenade_hud_effect( guy, position, 1.0, 400 );
|
|
thread maps\mp\_threatdetection::detection_highlight_hud_effect( guy, 5 );
|
|
}
|
|
|
|
teamPlayers = getPlayersOnTeam( owner.team );
|
|
|
|
foreach( guy in level.players )
|
|
{
|
|
if ( !IsDefined( guy ) || !isReallyAlive( guy ) || IsAlliedSentient( owner, guy ) || guy _hasPerk( "specialty_coldblooded" ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if( Distance( guy.origin, position ) < 400 )
|
|
{
|
|
guy maps\mp\_threatdetection::addThreatEvent( teamPlayers, 5, "PAINT_GRENADE", true, false );
|
|
owner maps\mp\gametypes\_damagefeedback::updateDamageFeedback( "paint" );
|
|
guy thread detectionGrenadeWatch( owner, 5 );
|
|
guy notify( "paint_marked_target", owner );
|
|
if ( stunPlayers )
|
|
maps\mp\gametypes\_weapons::flashbangPlayer( guy, position, owner );
|
|
if( isdefined( vehicle ) && vehicle.VehName == "recon_uav" )
|
|
owner maps\mp\gametypes\_missions::processChallenge( "ch_streak_recon");
|
|
}
|
|
}
|
|
}
|
|
|
|
detectionGrenadeWatch( owner, time ) // self == victim
|
|
{
|
|
level endon( "game_ended" );
|
|
self notify( "detectionGrenadeWatch" );
|
|
self endon( "detectionGrenadeWatch" );
|
|
|
|
// Award XP on tag, unless already tagged by this player
|
|
if ( !IsDefined( self.tagMarkedBy ) || self.tagMarkedBy != owner )
|
|
{
|
|
owner thread maps\mp\_events::killStreakTagEvent();
|
|
owner playRumbleOnEntity( "damage_heavy" );
|
|
}
|
|
|
|
// Mark the target
|
|
self DesignateFoFTarget( true );
|
|
self.tagMarkedBy = owner;
|
|
|
|
self waittill_any_timeout( time, "death", "disconnect" );
|
|
|
|
// Unmark the target
|
|
if ( IsDefined( self ) )
|
|
{
|
|
self DesignateFoFTarget( false );
|
|
self.tagMarkedBy = undefined;
|
|
}
|
|
|
|
}
|
|
|
|
//===========================================
|
|
// getPlayersOnTeam
|
|
//===========================================
|
|
getPlayersOnTeam( team ) // optional: self == player
|
|
{
|
|
teammates = [];
|
|
foreach( player in level.players )
|
|
{
|
|
if( player.hasSpawned && isAlive( player ) && team == player.team && ( !IsPlayer( self ) || player != self ) )
|
|
{
|
|
teammates[ teammates.size ] = player;
|
|
}
|
|
}
|
|
|
|
return teammates;
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// shouldStopProximityAlarm
|
|
//===========================================
|
|
shouldStopProximityAlarm( missile, heli )
|
|
{
|
|
return ( !IsDefined( heli ) || !IsDefined( heli.player ) || !IsDefined( missile ) || IsDefined( heli.flaresTarget ) || !isReallyAlive( self ) || IsDefined( heli.crashed ) || IsDefined( heli.isCrashing ) );
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// heli_staticDamage
|
|
//===========================================
|
|
heli_staticDamage( weapon, damageType, modifiedDamage )
|
|
{
|
|
if( modifiedDamage > 0 && IsDefined( self.owner ) )
|
|
{
|
|
self.owner thread maps\mp\killstreaks\_aerial_utility::playerShowStreakStaticForDamage();
|
|
}
|
|
|
|
if( modifiedDamage > 0 && IsDefined( self.warbirdBuddyTurret ) && IsDefined( self.warbirdBuddyTurret.owner ) )
|
|
{
|
|
self.warbirdBuddyTurret.owner thread maps\mp\killstreaks\_aerial_utility::playerShowStreakStaticForDamage();
|
|
}
|
|
}
|
|
|
|
//===========================================
|
|
// heli_monitorEMP
|
|
//===========================================
|
|
heli_monitorEMP()
|
|
{
|
|
level endon( "game_ended" );
|
|
self endon( "death" );
|
|
self endon( "crashing" );
|
|
self endon( "leaving" );
|
|
|
|
while( true )
|
|
{
|
|
self waittill( "emp_damage" );
|
|
|
|
self thread heli_EMPGrenaded();
|
|
}
|
|
}
|
|
|
|
//===========================================
|
|
// heli_EMPGrenaded
|
|
//===========================================
|
|
heli_EMPGrenaded()
|
|
{
|
|
self notify( "heli_EMPGrenaded" );
|
|
self endon( "heli_EMPGrenaded" );
|
|
|
|
self endon( "death" );
|
|
self endon( "leaving" );
|
|
self endon( "crashing" );
|
|
self.owner endon( "disconnect" );
|
|
level endon( "game_ended" );
|
|
|
|
self.empGrenaded = true;
|
|
|
|
if( IsDefined( self.mgTurretLeft ) )
|
|
self.mgTurretLeft notify( "stop_shooting" );
|
|
|
|
if( IsDefined( self.mgTurretRight ) )
|
|
self.mgTurretRight notify( "stop_shooting" );
|
|
|
|
wait( EMP_GRENADE_TIME );
|
|
|
|
self.empGrenaded = false;
|
|
|
|
if( IsDefined( self.mgTurretLeft ) )
|
|
self.mgTurretLeft notify( "turretstatechange" );
|
|
|
|
if( IsDefined( self.mgTurretRight ) )
|
|
self.mgTurretRight notify( "turretstatechange" );
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// heli_existance
|
|
//===========================================
|
|
heli_existance()
|
|
{
|
|
entityNumber = self getEntityNumber();
|
|
|
|
self waittill_any( "death", "crashing", "leaving" );
|
|
|
|
self removeFromHeliList( entityNumber );
|
|
|
|
self notify( "helicopter_done" );
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// heli_crash
|
|
//===========================================
|
|
heli_crash()
|
|
{
|
|
self notify( "crashing" );
|
|
|
|
self ClearLookAtEnt();
|
|
self.isCrashing = true;
|
|
|
|
crashNode = heli_pick_fly_node( level.heli_crash_nodes );
|
|
|
|
if( IsDefined( self.mgTurretLeft ) )
|
|
self.mgTurretLeft notify( "stop_shooting" );
|
|
|
|
if( IsDefined( self.mgTurretRight ) )
|
|
self.mgTurretRight notify( "stop_shooting" );
|
|
|
|
self thread heli_spin( 180 );
|
|
self thread heli_secondary_explosions();
|
|
self Vehicle_SetSpeed( 100, 45 );
|
|
if ( IsDefined( crashNode.target ) )
|
|
{
|
|
self heli_fly_simple_path( crashNode );
|
|
}
|
|
else
|
|
{
|
|
self _setVehGoalPos( crashNode.origin, false );
|
|
self waittillmatch( "goal" );
|
|
}
|
|
self thread heli_explode();
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// heli_secondary_explosions
|
|
//===========================================
|
|
heli_secondary_explosions()
|
|
{
|
|
teamname = self.team;
|
|
|
|
playFxOnTag( level.chopper_fx["explode"]["large"], self, "tag_engine_left" );
|
|
if ( IsDefined( level.heli_sound[teamname]["hitsecondary"] ) )
|
|
self playSound ( level.heli_sound[teamname]["hitsecondary"] );
|
|
|
|
wait ( 3.0 );
|
|
|
|
if ( !isDefined( self ) )
|
|
return;
|
|
|
|
playFxOnTag( level.chopper_fx["explode"]["large"], self, "tag_engine_left" );
|
|
if ( IsDefined( level.heli_sound[teamname]["hitsecondary"] ) )
|
|
self playSound ( level.heli_sound[teamname]["hitsecondary"] );
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// heli_spin
|
|
//===========================================
|
|
heli_spin( speed )
|
|
{
|
|
self endon( "death" );
|
|
|
|
teamname = self.team;
|
|
|
|
// play hit sound immediately so players know they got it
|
|
self playSound ( level.heli_sound[teamname]["hit"] );
|
|
|
|
// play heli crashing spinning sound
|
|
self thread spinSoundShortly();
|
|
|
|
// spins until death
|
|
self setyawspeed( speed, speed, speed );
|
|
while ( isdefined( self ) )
|
|
{
|
|
self settargetyaw( self.angles[1]+(speed*0.9) );
|
|
wait ( 1 );
|
|
}
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// spinSoundShortly
|
|
//===========================================
|
|
spinSoundShortly()
|
|
{
|
|
self endon("death");
|
|
|
|
wait .25;
|
|
teamname = self.team;
|
|
self stopLoopSound();
|
|
wait .05;
|
|
self playLoopSound( level.heli_sound[teamname]["spinloop"] );
|
|
wait .05;
|
|
if ( IsDefined( level.heli_sound[teamname]["spinstart"] ) )
|
|
self playLoopSound( level.heli_sound[teamname]["spinstart"] );
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// heli_explode
|
|
//===========================================
|
|
heli_explode( altStyle )
|
|
{
|
|
self notify( "death" );
|
|
|
|
if( isDefined( altStyle ) && isDefined( level.chopper_fx["explode"]["air_death"][self.heli_type] ) )
|
|
{
|
|
deathAngles = self getTagAngles( "tag_deathfx" );
|
|
|
|
playFx( level.chopper_fx["explode"]["air_death"][self.heli_type], self getTagOrigin( "tag_deathfx" ), anglesToForward( deathAngles ), anglesToUp( deathAngles ) );
|
|
}
|
|
else
|
|
{
|
|
org = self.origin;
|
|
forward = ( self.origin + ( 0, 0, 1 ) ) - self.origin;
|
|
playFx( level.chopper_fx["explode"]["death"][self.heli_type], org, forward );
|
|
}
|
|
|
|
// play heli explosion sound
|
|
teamname = self.team;
|
|
self playSound( level.heli_sound[teamname]["crash"] );
|
|
|
|
// give "death" notify time to process
|
|
wait ( 0.05 );
|
|
|
|
if( IsDefined( self.killCamEnt ) )
|
|
self.killCamEnt delete();
|
|
|
|
// decrement the faux vehicle count right before it is deleted this way we know for sure it is gone
|
|
decrementFauxVehicleCount();
|
|
|
|
self delete();
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// heli_fly_simple_path
|
|
//===========================================
|
|
heli_fly_simple_path( startNode )
|
|
{
|
|
self endon ( "death" );
|
|
self endon ( "leaving" );
|
|
|
|
// only one thread instance allowed
|
|
self notify( "flying");
|
|
self endon( "flying" );
|
|
|
|
heli_reset();
|
|
|
|
currentNode = startNode;
|
|
while ( isDefined( currentNode.target ) )
|
|
{
|
|
nextNode = getEntOrStruct( currentNode.target, "targetname" );
|
|
assertEx( isDefined( nextNode ), "Next node in path is undefined, but has targetname. Bad Node Position: " + currentNode.origin );
|
|
|
|
if( isDefined( currentNode.script_airspeed ) && isDefined( currentNode.script_accel ) )
|
|
{
|
|
heli_speed = currentNode.script_airspeed;
|
|
heli_accel = currentNode.script_accel;
|
|
}
|
|
else
|
|
{
|
|
heli_speed = 30 + randomInt(20);
|
|
heli_accel = 15 + randomInt(15);
|
|
}
|
|
|
|
if( isDefined( self.isAttacking ) && self.isAttacking )
|
|
{
|
|
wait ( 0.05 );
|
|
continue;
|
|
}
|
|
|
|
if( isDefined( self.isPerformingManeuver ) && self.isPerformingManeuver )
|
|
{
|
|
wait ( 0.05 );
|
|
continue;
|
|
}
|
|
|
|
self Vehicle_SetSpeed( heli_speed, heli_accel );
|
|
|
|
// end of the path
|
|
if ( !isDefined( nextNode.target ) )
|
|
{
|
|
self _setVehGoalPos( nextNode.origin+(self.zOffset), false );
|
|
self waittill( "near_goal" );
|
|
}
|
|
else
|
|
{
|
|
self _setVehGoalPos( nextNode.origin+(self.zOffset), false );
|
|
self waittill( "near_goal" );
|
|
|
|
self setGoalYaw( nextNode.angles[ 1 ] );
|
|
|
|
self waittillmatch( "goal" );
|
|
}
|
|
|
|
currentNode = nextNode;
|
|
}
|
|
|
|
printLn( currentNode.origin );
|
|
printLn( self.origin );
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// handle_player_starting_aerial_view
|
|
//===========================================
|
|
handle_player_starting_aerial_view()
|
|
{
|
|
self notify( "player_start_aerial_view" );
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// handle_player_ending_aerial_view
|
|
//===========================================
|
|
handle_player_ending_aerial_view()
|
|
{
|
|
self notify( "player_stop_aerial_view" );
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// getHeliAnchor
|
|
//===========================================
|
|
getHeliAnchor()
|
|
{
|
|
if ( IsDefined( level.heliAnchor ) )
|
|
return level.heliAnchor;
|
|
|
|
warbirdAnchor = getEntOrStruct( "warbird_anchor", "targetname" );
|
|
|
|
if ( !IsDefined( warbirdAnchor ) )
|
|
{
|
|
PrintLn( "WARNING: need a struct or entity with targetname warbird_anchor in the center of the map." );
|
|
warbirdAnchor = SpawnStruct();
|
|
warbirdAnchor.origin = ( 0, 0, CONST_default_height_z );
|
|
warbirdAnchor.targetname = "warbird_anchor";
|
|
}
|
|
|
|
if ( !IsDefined( warbirdAnchor.script_noteworthy ) )
|
|
warbirdAnchor.script_noteworthy = 3500;
|
|
|
|
level.heliAnchor = warbirdAnchor;
|
|
|
|
return level.heliAnchor;
|
|
}
|
|
|
|
|
|
//===========================================
|
|
// playerHandleBoundaryStatic
|
|
//===========================================
|
|
playerHandleBoundaryStatic( vehicle, endonString1, endonString2 )
|
|
{
|
|
if ( IsDefined( endonString1 ) )
|
|
self endon( endonString1 );
|
|
if ( IsDefined( endonString2 ) )
|
|
self endon( endonString2 );
|
|
|
|
outOfBoundsTriggers = GetEntArray( "remote_heli_range", "targetname" );
|
|
if ( !IsDefined( vehicle.vehicleType ) || outOfBoundsTriggers.size == 0 )
|
|
{
|
|
self playerHandleBoundaryStaticRadius( vehicle, endonString1, endonString2 );
|
|
return;
|
|
}
|
|
|
|
while ( true )
|
|
{
|
|
leaving = vehicle vehicleTouchingAnyTrigger( outOfBoundsTriggers );
|
|
|
|
if ( leaving )
|
|
{
|
|
self thread playerStartOutOfBoundsStatic( vehicle, endonString1, endonString2 );
|
|
while ( true )
|
|
{
|
|
waitframe();
|
|
if ( !IsDefined( vehicle.alwaysStaticOut ) || !vehicle.alwaysStaticOut )
|
|
{
|
|
back = !vehicle vehicleTouchingAnyTrigger( outOfBoundsTriggers );
|
|
if ( back )
|
|
{
|
|
vehicle notify( "staticDone" );
|
|
self thread playerStaticToNormal( vehicle, endonString1, endonString2 );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
waitframe();
|
|
}
|
|
}
|
|
|
|
vehicleTouchingAnyTrigger( triggers ) // self == vehicle
|
|
{
|
|
foreach ( trigger in triggers )
|
|
{
|
|
if ( self IsTouching( trigger ) )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
playerStaticToNormal( vehicle, endonString1, endonString2 )
|
|
{
|
|
if ( IsDefined( endonString1 ) )
|
|
self endon( endonString1 );
|
|
if ( IsDefined( endonString2 ) )
|
|
self endon( endonString2 );
|
|
|
|
vehicle endon( "staticStarting" );
|
|
vehicle.staticLevel--;
|
|
|
|
while ( vehicle.staticLevel > 0 )
|
|
{
|
|
self playerShowStreakStaticForRange( vehicle.staticLevel );
|
|
if ( IsDefined( vehicle.buddy ) )
|
|
vehicle.buddy playerShowStreakStaticForRange( vehicle.staticLevel );
|
|
wait 0.5;
|
|
vehicle.staticLevel--;
|
|
}
|
|
|
|
self playerShowStreakStaticForRange( 0 );
|
|
if ( IsDefined( vehicle.buddy ) )
|
|
vehicle.buddy playerShowStreakStaticForRange( 0 );
|
|
}
|
|
|
|
playerStartOutOfBoundsStatic( vehicle, endonString1, endonString2 )
|
|
{
|
|
if ( IsDefined( endonString1 ) )
|
|
self endon( endonString1 );
|
|
if ( IsDefined( endonString2 ) )
|
|
self endon( endonString2 );
|
|
|
|
vehicle notify( "staticStarting" );
|
|
vehicle endon( "staticDone" );
|
|
|
|
if ( !IsDefined( vehicle.staticLevel ) || vehicle.staticLevel == 0 )
|
|
vehicle.staticLevel = 1;
|
|
|
|
while ( vehicle.staticLevel < 4 )
|
|
{
|
|
self playerShowStreakStaticForRange( vehicle.staticLevel );
|
|
if ( IsDefined( vehicle.buddy ) )
|
|
vehicle.buddy playerShowStreakStaticForRange( vehicle.staticLevel );
|
|
|
|
if ( IsDefined( vehicle.PlayerAttachPoint ) )
|
|
vehicle.PlayerAttachPoint PlaySound( "mp_warbird_outofbounds_warning" );
|
|
|
|
if ( IsDefined( vehicle.staticLevelWaitTime ) )
|
|
wait vehicle.staticLevelWaitTime;
|
|
else
|
|
wait 2;
|
|
vehicle.staticLevel++;
|
|
}
|
|
|
|
vehicle notify( "outOfBounds" );
|
|
}
|
|
|
|
playerHandleBoundaryStaticRadius( vehicle, endonString1, endonString2 )
|
|
{
|
|
if ( IsDefined( endonString1 ) )
|
|
self endon( endonString1 );
|
|
if ( IsDefined( endonString2 ) )
|
|
self endon( endonString2 );
|
|
|
|
WarbirdAnchor = getHeliAnchor();
|
|
levelBoundaryRadius = Int( WarbirdAnchor.script_noteworthy );
|
|
|
|
while ( true )
|
|
{
|
|
DistanceFromCenter = Distance( WarbirdAnchor.origin, vehicle.origin );
|
|
|
|
if ( DistanceFromCenter < levelBoundaryRadius )
|
|
{
|
|
self playerShowStreakStaticForRange( 0 );
|
|
}
|
|
else if ( DistanceFromCenter > levelBoundaryRadius && DistanceFromCenter < levelBoundaryRadius + 500 )
|
|
{
|
|
self playerShowStreakStaticForRange( 1 );
|
|
if ( IsDefined( vehicle.PlayerAttachPoint ) )
|
|
vehicle.PlayerAttachPoint PlaySound( "mp_warbird_outofbounds_warning" );
|
|
}
|
|
else if ( DistanceFromCenter > levelBoundaryRadius + 500 && DistanceFromCenter < levelBoundaryRadius + 1000 )
|
|
{
|
|
self playerShowStreakStaticForRange( 2 );
|
|
if ( IsDefined( vehicle.PlayerAttachPoint ) )
|
|
vehicle.PlayerAttachPoint PlaySound( "mp_warbird_outofbounds_warning" );
|
|
}
|
|
else if ( DistanceFromCenter > levelBoundaryRadius + 1000 && DistanceFromCenter < levelBoundaryRadius + 1500 )
|
|
{
|
|
self playerShowStreakStaticForRange( 3 );
|
|
if ( IsDefined( vehicle.PlayerAttachPoint ) )
|
|
vehicle.PlayerAttachPoint PlaySound( "mp_warbird_outofbounds_warning" );
|
|
}
|
|
else
|
|
{
|
|
self playerShowStreakStaticForRange( 4 );
|
|
vehicle notify( "outOfBounds" );
|
|
}
|
|
|
|
wait 0.5;
|
|
}
|
|
}
|
|
|
|
playerEnableStreakStatic()
|
|
{
|
|
self notify( "playerUpdateStreakStatic" );
|
|
self SetClientOmnvar( "ui_streak_overlay_state", CONST_streak_static_enabled );
|
|
}
|
|
|
|
playerDisableStreakStatic()
|
|
{
|
|
self notify( "playerUpdateStreakStatic" );
|
|
self SetClientOmnvar( "ui_streak_overlay_state", CONST_streak_static_disabled );
|
|
}
|
|
|
|
playerShowFullStatic()
|
|
{
|
|
self notify( "playerUpdateStreakStatic" );
|
|
self SetClientOmnvar( "ui_streak_overlay_state", CONST_streak_static_fullnotext );
|
|
}
|
|
|
|
playerShowStreakStaticForDamage()
|
|
{
|
|
self endon( "disconnect" );
|
|
|
|
// Only allow damage if in the base 'enabled' state
|
|
if ( self GetClientOmnvar( "ui_streak_overlay_state" ) != CONST_streak_static_enabled )
|
|
return;
|
|
|
|
self notify( "playerUpdateStreakStatic" );
|
|
self endon( "playerUpdateStreakStatic" );
|
|
|
|
self SetClientOmnvar( "ui_streak_overlay_state", CONST_streak_static_damage );
|
|
wait( 1 );
|
|
self SetClientOmnvar( "ui_streak_overlay_state", CONST_streak_static_enabled );
|
|
}
|
|
|
|
playerShowStreakStaticForRange( rangeIndex )
|
|
{
|
|
assert( rangeIndex >= 0 && rangeIndex <= 4 );
|
|
|
|
targetIndex = CONST_streak_static_enabled;
|
|
switch( rangeIndex )
|
|
{
|
|
case 0: targetIndex = CONST_streak_static_enabled; break;
|
|
case 1: targetIndex = CONST_streak_static_range1; break;
|
|
case 2: targetIndex = CONST_streak_static_range2; break;
|
|
case 3: targetIndex = CONST_streak_static_range3; break;
|
|
case 4: targetIndex = CONST_streak_static_range4; break;
|
|
default:
|
|
AssertMsg( "Unhandled range for playerShowStreakStaticForRange" );
|
|
}
|
|
|
|
self notify( "playerUpdateStreakStatic" );
|
|
self SetClientOmnvar( "ui_streak_overlay_state", targetIndex );
|
|
}
|
|
|
|
getEntOrStruct( name, type )
|
|
{
|
|
ent = GetEnt( name, type );
|
|
if ( IsDefined( ent ) )
|
|
return ent;
|
|
return getstruct( name, type );
|
|
}
|
|
|
|
getEntOrStructArray( name, type )
|
|
{
|
|
structArray = getstructarray( name, type );
|
|
entArray = GetEntArray( name, type );
|
|
if ( entArray.size > 0 )
|
|
structArray = array_combine( structArray, entArray );
|
|
return structArray;
|
|
}
|
|
|
|
//===========================================
|
|
// playerHandleKillVehicle
|
|
//===========================================
|
|
|
|
playerHandleKillVehicle( vehicle, endonString1, endonString2 )
|
|
{
|
|
if ( IsDefined( endonString1 ) )
|
|
self endon( endonString1 );
|
|
if ( IsDefined( endonString2 ) )
|
|
self endon( endonString2 );
|
|
|
|
if( !isDefined( level.vehicle_kill_triggers ) )
|
|
return;
|
|
|
|
while ( true )
|
|
{
|
|
inDeathTrigger = vehicle vehicleTouchingAnyTrigger( level.vehicle_kill_triggers );
|
|
|
|
if ( inDeathTrigger )
|
|
{
|
|
vehicle notify( "death" );
|
|
}
|
|
|
|
waitframe();
|
|
}
|
|
}
|
|
|
|
setup_kill_drone_trig( name, type )
|
|
{
|
|
if ( isdefined( name ) && isdefined( type ) )
|
|
{
|
|
ents = getentarray( name, type );
|
|
array_thread( ents, ::setup_kill_drone_trig_proc );
|
|
}
|
|
else if( self isVehicleKillTrigger() )
|
|
self setup_kill_drone_trig_proc();
|
|
}
|
|
|
|
setup_kill_drone_trig_proc()
|
|
{
|
|
if( self isVehicleKillTrigger() )
|
|
{
|
|
if( !isDefined( level.vehicle_kill_triggers ) )
|
|
level.vehicle_kill_triggers = [];
|
|
|
|
level.vehicle_kill_triggers[ level.vehicle_kill_triggers.size ] = self;
|
|
}
|
|
}
|
|
|
|
isVehicleKillTrigger()
|
|
{
|
|
if( isDefined( self.classname ) && IsSubStr( self.classname, "trigger_multiple" ) && isDefined( self.spawnflags ) && (self.spawnflags & CONST_VEHICLE_SPAWNFLAG ) )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
vehicleIsCloaked() // self == vehicle
|
|
{
|
|
return ( IsDefined( self.cloakstate ) && self.cloakstate < 1 );
|
|
}
|
|
|
|
thermalVision( endonString, adsAperature, adsFocalDistance, normalAperature, normalFocalDistance, focusSpeed, aperatureSpeed )
|
|
{
|
|
self endon( endonString );
|
|
|
|
inverted = false;
|
|
|
|
disableOrbitalThermal( self );
|
|
self VisionSetThermalForPlayer( "default", 0.25 );
|
|
self SetClientOmnvar( "ui_killstreak_optic", false );
|
|
|
|
if ( IsBot( self ) )
|
|
return;
|
|
|
|
self notifyOnPlayerCommand( "switch thermal", "+actionslot 1" );
|
|
self thread playerCleanupThermalVisionCommands( endonString );
|
|
|
|
while ( true )
|
|
{
|
|
self waittill ( "switch thermal" );
|
|
|
|
if ( !inverted )
|
|
{
|
|
enableOrbitalThermal( self, endonString, adsAperature, adsFocalDistance, normalAperature, normalFocalDistance, focusSpeed, aperatureSpeed );
|
|
self SetClientOmnvar( "ui_killstreak_optic", true );
|
|
self PlayLocalSound( "paladin_toggle_flir_plr" );
|
|
}
|
|
else
|
|
{
|
|
disableOrbitalThermal( self );
|
|
self SetClientOmnvar( "ui_killstreak_optic", false );
|
|
self PlayLocalSound( "paladin_toggle_flir_plr" );
|
|
}
|
|
|
|
inverted = !inverted;
|
|
}
|
|
}
|
|
|
|
playerCleanupThermalVisionCommands( endonString )
|
|
{
|
|
self endon( "disconnect" );
|
|
|
|
self waittill( endonString );
|
|
|
|
self NotifyOnPlayerCommandRemove( "switch thermal", "+actionslot 1" );
|
|
}
|
|
|
|
disableOrbitalThermal( ent )
|
|
{
|
|
ent ThermalVisionOff();
|
|
ent notify ( "thermal_vision_off" );
|
|
ent DisablePhysicalDepthOfFieldScripting();
|
|
|
|
ent.orbitalThermalMode = false;
|
|
}
|
|
|
|
enableOrbitalThermal( ent, endonString, adsAperature, adsFocalDistance, normalAperature, normalFocalDistance, focusSpeed, aperatureSpeed )
|
|
{
|
|
ent endon( "disconnect" );
|
|
ent endon( "death" );
|
|
ent endon( "faux_spawn" );
|
|
ent endon( endonString );
|
|
|
|
// Should be initialized in opticsthermal_think() in _opticsthermal.gsc
|
|
if ( !IsDefined( ent.opticsThermalEnabled ) )
|
|
ent.opticsThermalEnabled = false;
|
|
if ( !IsDefined( ent.orbitalThermalMode ) )
|
|
ent.orbitalThermalMode = false;
|
|
|
|
ent.orbitalThermalMode = true;
|
|
while ( ent.opticsThermalEnabled )
|
|
wait 0.05;
|
|
|
|
ent ThermalVisionOn();
|
|
ent EnablePhysicalDepthOfFieldScripting(3);
|
|
ent thread setThermalDOF( endonString, adsAperature, adsFocalDistance, normalAperature, normalFocalDistance, focusSpeed, aperatureSpeed );
|
|
}
|
|
|
|
setThermalDOF( endonString, adsAperature, adsFocalDistance, normalAperature, normalFocalDistance, focusSpeed, aperatureSpeed )
|
|
{
|
|
self endon ( endonString );
|
|
self endon( "disconnect" );
|
|
self endon( "thermal_vision_off" );
|
|
|
|
while( 1 )
|
|
{
|
|
adsAmt = self playerAds();
|
|
aperature = float_lerp( normalAperature, adsAperature, adsAmt );
|
|
focalDistance = float_lerp( normalFocalDistance, adsFocalDistance, adsAmt );
|
|
self SetPhysicalDepthOfField( aperature, focalDistance, focusSpeed, aperatureSpeed );
|
|
wait 0.1;
|
|
}
|
|
}
|
|
|
|
float_lerp( start, end, percent )
|
|
{
|
|
return (start + percent*(end - start));
|
|
}
|
|
|
|
patchHeliLoopNode( nodeOrigin, newNodeOrigin )
|
|
{
|
|
checkedNodes = [];
|
|
nextNode = getEntOrStruct( "heli_loop_start", "targetname" );
|
|
|
|
while ( true )
|
|
{
|
|
if ( array_contains( checkedNodes, nextNode ) )
|
|
break;
|
|
|
|
if ( nextNode.origin == nodeOrigin )
|
|
{
|
|
nextNode.origin = newNodeOrigin;
|
|
return;
|
|
}
|
|
|
|
checkedNodes[checkedNodes.size] = nextNode;
|
|
|
|
nextNode = getEntOrStruct( nextNode.target, "targetname" );
|
|
}
|
|
|
|
AssertMsg( "Could not patch node with origin " + nodeOrigin + " because it can't be found." );
|
|
} |