2024-12-11 11:28:08 +01:00

1005 lines
24 KiB
Plaintext

#include maps\mp\_utility;
#include common_scripts\utility;
/*
A10 killstreak: the player uses the mini-map selector to select a place to strafe
*/
KS_NAME = "a10_strafe";
kTransitionTime = 0.75;
kLockIconOffset = (0, 0, -70);
init()
{
precacheLocationSelector( "map_artillery_selector" );
config = SpawnStruct();
config.modelNames = [];
config.modelNames[ "allies" ] = "vehicle_a10_warthog_iw6_mp";
config.modelNames[ "axis" ] = "vehicle_a10_warthog_iw6_mp";
config.vehicle = "a10_warthog_mp";
config.inboundSfx = "veh_mig29_dist_loop";
//config.inboundSfx = "veh_aastrike_flyover_loop";
//config.outboundSfx = "veh_aastrike_flyover_outgoing_loop";
//config.compassIconFriendly = "compass_objpoint_a10_friendly";
//config.compassIconEnemy = "compass_objpoint_a10_enemy";
// sonic boom?
config.speed = 3000;
config.halfDistance = 12500;
config.heightRange = 750;
config.chooseDirection = true;
config.selectLocationVO = "KS_hqr_airstrike";
config.inboundVO = "KS_ast_inbound";
config.cannonFireVfx = LoadFX( "fx/smoke/smoke_trail_white_heli" );
config.cannonRumble = "ac130_25mm_fire";
config.turretName = "a10_30mm_turret_mp";
config.turretAttachPoint = "tag_barrel";
config.rocketModelName = "maverick_projectile_mp";
config.numRockets = 4;
config.delayBetweenRockets = 0.125;
config.delayBetweenLockon = 0.4;
config.lockonIcon = "veh_hud_target_chopperfly"; // "veh_hud_target_lock"
config.maxHealth = 1000;
config.xpPopup = "destroyed_a10_strafe";
config.callout = "callout_destroyed_a10";
config.voDestroyed = undefined;
config.explodeVfx = LoadFX( "fx/explosions/aerial_explosion");
// holy crap, lots of sfx
config.sfxCannonFireLoop_1p = "veh_a10_plr_fire_gatling_lp";
config.sfxCannonFireStop_1p = "veh_a10_plr_fire_gatling_cooldown";
config.sfxCannonFireLoop_3p = "veh_a10_npc_fire_gatling_lp";
config.sfxCannonFireStop_3p = "veh_a10_npc_fire_gatling_cooldown";
config.sfxCannonFireBurpTime = 500;
config.sfxCannonFireBurpShort_3p = "veh_a10_npc_fire_gatling_short_burst";
config.sfxCannonFireBurpLong_3p = "veh_a10_npc_fire_gatling_long_burst";
config.sfxCannonBulletImpact = "veh_a10_bullet_impact_lp"; // loop, should play on moving entity
config.sfxMissileFire_1p = [];
config.sfxMissileFire_1p[0] = "veh_a10_plr_missile_ignition_left";
config.sfxMissileFire_1p[1] = "veh_a10_plr_missile_ignition_right";
config.sfxMissileFire_3p = "veh_a10_npc_missile_fire";
config.sfxMissile = "veh_a10_missile_loop";
config.sfxEngine_1p = "veh_a10_plr_engine_lp";
config.sfxEngine_3p = "veh_a10_dist_loop";
level.planeConfigs[ KS_NAME ] = config;
level.killstreakFuncs[KS_NAME] = ::onUse;
/*
a10 sounds
a10p_gatling_loop
a10p_gatling_tail
a10p_missile_launch
a10p_impact
*/
buildAllFlightPathsDefault();
}
onUse( lifeId, streakName )
{
assert( isDefined( self ) );
if ( IsDefined( level.a10strafeActive ) )
{
self IPrintLnBold( &"KILLSTREAKS_AIR_SPACE_TOO_CROWDED" );
return false;
}
else if ( self isUsingRemote()
|| self isKillStreakDenied()
)
{
return false;
}
else if ( GetCSplineCount() < 2 )
{
PrintLn( "ERROR: need at least two CSpline paths for A10 strafing run. Please add them to your level." );
return false;
}
else
{
self thread doStrike( lifeId, KS_NAME );
return true;
}
}
doStrike( lifeId, streakName ) //self == player
{
self endon ("end_remote");
self endon ("death");
level endon ("game_ended");
pathIndex = getPathIndex();
print( " A10 fly path (" + level.a10SplinesIn[ pathIndex ] + ", " + level.a10SplinesOut[ pathIndex ] + ")\n" );
result = self startStrafeSequence( streakName, lifeId );
if ( result )
{
// randomize the order of the whether to pick inbound or outbound?
plane = spawnAircraft( streakName, lifeId, level.a10SplinesIn[ pathIndex ] );
if ( isDefined( plane ) )
{
plane doOneFlyby();
self switchAircraft( plane, streakName );
plane = spawnAircraft( streakName, lifeId, level.a10SplinesIn[ pathIndex ] );
if ( isDefined( plane ) )
{
self thread maps\mp\killstreaks\_killstreaks::clearRideIntro( 1.0, kTransitionTime );
plane doOneFlyby();
plane thread endFlyby( streakName );
self endStrafeSequence( streakName );
}
}
}
}
startStrafeSequence( streakName, lifeId ) // self == owner
{
self setUsingRemote( KS_NAME );
if( GetDvarInt( "camera_thirdPerson" ) )
self setThirdPersonDOF( false );
self.restoreAngles = self.angles;
self freezeControlsWrapper( true );
result = self maps\mp\killstreaks\_killstreaks::initRideKillstreak( KS_NAME );
if( result != "success" )
{
if ( result != "disconnect" )
self clearUsingRemote();
if( IsDefined( self.disabledWeapon ) && self.disabledWeapon )
self _enableWeapon();
self notify( "death" );
return false;
}
if( self isJuggernaut() && IsDefined( self.juggernautOverlay ) )
{
self.juggernautOverlay.alpha = 0;
}
self freezeControlsWrapper( false );
level.a10strafeActive = true;
self.using_remote_a10 = true;
level thread teamPlayerCardSplash( "used_" + streakName, self, self.team );
return true;
}
endStrafeSequence( streakName )
{
self clearUsingRemote();
if( GetDvarInt( "camera_thirdPerson" ) )
{
self setThirdPersonDOF( true );
}
if( self isJuggernaut() && IsDefined( self.juggernautOverlay ) )
{
self.juggernautOverlay.alpha = 1;
}
self SetPlayerAngles( self.restoreAngles );
self.restoreAngles = undefined;
self thread a10_FreezeBuffer();
// play outbound vo
level.a10strafeActive = undefined;
self.using_remote_a10 = undefined;
}
switchAircraft( plane, streakName ) // self == player
{
// !!!! hack
// we don't want to call clearUsingRemote because we want to stay in remote
// but we have to clear this flag so that setUsingRemote during the second pass works
self.usingRemote = undefined;
self VisionSetNakedForPlayer( "black_bw", kTransitionTime );
self thread set_visionset_for_watching_players( "black_bw", kTransitionTime, kTransitionTime );
wait( kTransitionTime );
if ( IsDefined( plane ) )
{
plane thread endFlyby( streakName );
}
// play some VO to indicate a 2nd pilot
}
spawnAircraft( streakName, lifeId, splineId )
{
plane = createPlaneAsHeli( streakName, lifeId, splineId );
if ( !isDefined( plane ) )
return undefined;
plane.streakName = streakName;
// plane endon( "death" );
self RemoteControlVehicle( plane );
plane SetPlaneSplineId( self, splineId );
// plane attachTurret( streakName );
self thread watchIntroCleared( streakName, plane );
config = level.planeConfigs[ streakName ];
plane PlayLoopSound( config.sfxEngine_1p );
// add damage handling
plane thread a10_handleDamage();
maps\mp\killstreaks\_plane::startTrackingPlane( plane );
return plane;
}
attachTurret( streakName ) // self == plane
{
config = level.planeConfigs[ streakName ];
turretPos = self GetTagOrigin( config.turretAttachPoint );
turret = SpawnTurret( "misc_turret", self.origin + turretPos, config.turretName, false );
turret LinkTo( self, config.turretAttachPoint, ( 0, 0, 0 ), ( 0, 0, 0 ) );
turret SetModel( "vehicle_ugv_talon_gun_mp" );
turret.angles = self.angles;
turret.owner = self.owner;
// set model?
turret MakeTurretInoperable();
turret SetTurretModeChangeWait( false );
turret SetMode( "sentry_offline" );
turret MakeUnusable();
turret SetCanDamage( false );
turret SetSentryOwner( self.owner );
self.owner RemoteControlTurret( turret );
self.turret = turret;
}
cleanupAircraft()
{
if ( IsDefined( self.turret ) )
{
self.turret Delete();
}
foreach ( targetInfo in self.targetList )
{
if ( IsDefined( targetInfo["icon"] ) )
{
targetInfo["icon"] Destroy();
targetInfo["icon"] = undefined;
}
}
self Delete();
}
getPathIndex()
{
return ( RandomInt(level.a10SplinesIn.size ) );
}
doOneFlyby()
{
self endon( "death" );
level endon( "game_ended" );
while ( true )
{
// also wait for death of plane
self waittill ( "splinePlaneReachedNode", nodeLabel );
if ( IsDefined( nodeLabel ) && nodeLabel == "End" )
{
self notify( "a10_end_strafe" );
break;
}
}
}
endFlyby( streakName )
{
if( !IsDefined( self ) )
return;
// disconnect the player from the plane
self.owner RemoteControlVehicleOff( self );
if ( IsDefined( self.turret ) )
{
self.owner RemoteControlTurretOff( self.turret );
}
self notify( "end_remote" );
self.owner SetClientOmnvar( "ui_a10", false );
self.owner ThermalVisionFOFOverlayOff();
config = level.planeConfigs[ streakName ];
self StopLoopSound( config.sfxCannonFireLoop_1p );
maps\mp\killstreaks\_plane::stopTrackingPlane( self );
// let it fly away
wait( 5 );
if (IsDefined( self ) )
{
self StopLoopSound( config.sfxEngine_1p );
self cleanupAircraft();
// self notify("delete");
}
}
createPlaneAsHeli( streakName, lifeId, splineId ) // self == player
{
// get plane config
config = level.planeConfigs[ streakName ];
// get the start pos and tangent of the spline
startPos = GetCSplinePointPosition( splineId, 0 );
startTangent = GetCSplinePointTangent( splineId, 0 );
// calculate start angles
startAngles = VectorToAngles( startTangent );
// spawn plane
plane = SpawnHelicopter( self, startPos, startAngles, config.vehicle, config.modelNames[ self.team ] );
if ( !IsDefined( plane ) )
return undefined;
// set plane to be solid
plane MakeVehicleSolidCapsule( 18, -9, 18 );
// set plane owner/team
plane.owner = self;
plane.team = self.team;
// set plane life id
plane.lifeId = lifeId;
// start fx
plane thread maps\mp\killstreaks\_plane::playPlaneFX();
// return the plane
return plane;
}
handleDeath() // self == plane
{
level endon( "game_ended" );
self endon( "delete" );
self waittill( "death" );
// not sure if this will even work
// self.owner stopPilot( self );
level.a10strafeActive = undefined;
self.owner.using_remote_a10 = undefined;
self delete();
}
a10_FreezeBuffer()
{
self endon( "disconnect" );
self endon( "death" );
level endon( "game_ended" );
self freezeControlsWrapper( true );
wait( 0.5 );
self freezeControlsWrapper( false );
}
monitorRocketFire( streakName, plane ) // self == player
{
plane endon( "end_remote" );
plane endon( "death" );
self endon( "death" );
level endon( "game_ended" );
config = level.planeConfigs[ streakName ];
plane.numRocketsLeft = config.numRockets;
self NotifyOnPlayerCommand( "rocket_fire_pressed", "+speed_throw" );
self NotifyOnPlayerCommand( "rocket_fire_pressed", "+ads_akimbo_accessible" );
if( !level.console )
{
self NotifyOnPlayerCommand( "rocket_fire_pressed", "+toggleads_throw" );
}
self SetClientOmnvar( "ui_a10_rocket", plane.numRocketsLeft );
while (plane.numRocketsLeft > 0)
{
self waittill( "rocket_fire_pressed" );
plane onFireRocket( streakName );
wait( config.delayBetweenRockets );
}
}
monitorRocketFire2(streakName, plane)
{
plane endon( "end_remote" );
plane endon( "death" );
self endon( "death" );
level endon( "game_ended" );
config = level.planeConfigs[ streakName ];
plane.numRocketsLeft = config.numRockets;
self NotifyOnPlayerCommand( "rocket_fire_pressed", "+speed_throw" );
self NotifyOnPlayerCommand( "rocket_fire_pressed", "+ads_akimbo_accessible" );
if( !level.console )
{
self NotifyOnPlayerCommand( "rocket_fire_pressed", "+toggleads_throw" );
}
plane.targetList = [];
self SetClientOmnvar( "ui_a10_rocket", plane.numRocketsLeft );
while ( plane.numRocketsLeft > 0 )
{
if ( !(self AdsButtonPressed()) )
{
self waittill( "rocket_fire_pressed" );
}
plane missileAcquireTargets();
if ( plane.targetList.size > 0 )
{
plane thread fireMissiles();
}
}
}
missileGetBestTarget() // self == plane
{
candidateList = [];
foreach (player in level.players)
{
if (self missileIsGoodTarget(player))
{
candidateList[ candidateList.size ] = player;
}
}
foreach (uplink in level.uplinks)
{
if (self missileIsGoodTarget(uplink))
{
candidateList[ candidateList.size ] = uplink;
}
}
// satcoms?
// ugvs?
if ( candidateList.size > 0 )
{
sortedCandidateList = SortByDistance(candidateList, self.origin);
return sortedCandidateList[0];
}
return undefined;
}
missileIsGoodTarget( target ) // self == plane
{
return ( IsAlive(target)
&& target.team != self.owner.team
&& !(self isMissileTargeted( target ))
&& (IsPlayer( target ) && !(target _hasPerk( "specialty_blindeye" )))
// && (self.owner WorldPointInReticle_Circle(target.origin, 65, 200))
&& self missileTargetAngle( target ) > 0.25
);
}
// this needs to be optimized
missileTargetAngle( target ) // self == plane
{
dirToTarget = VectorNormalize( target.origin - self.origin );
facingDir = AnglesToForward( self.angles );
return VectorDot( dirToTarget, facingDir );
}
missileAcquireTargets()
{
self endon ("death");
self endon( "end_remote" );
level endon ("game_ended");
self endon ("a10_missiles_fired");
config = level.planeConfigs[ self.streakName ];
self.owner SetClientOmnvar( "ui_a10_rocket_lock", true );
self thread missileWaitForTriggerRelease();
currentTarget = undefined;
while ( self.targetList.size < self.numRocketsLeft )
{
if ( !IsDefined( currentTarget ) )
{
currentTarget = self missileGetBestTarget();
if ( IsDefined( currentTarget ) )
{
self thread missileLockTarget( currentTarget );
wait (config.delayBetweenLockon);
currentTarget = undefined;
continue;
}
}
wait (0.1);
}
self.owner SetClientOmnvar( "ui_a10_rocket_lock", false );
self notify( "a10_missiles_fired" );
}
missileWaitForTriggerRelease()
{
self endon( "end_remote" );
self endon( "death" );
level endon( "game_ended" );
self endon ("a10_missiles_fired");
owner = self.owner;
owner NotifyOnPlayerCommand( "rocket_fire_released", "-speed_throw" );
owner NotifyOnPlayerCommand( "rocket_fire_released", "-ads_akimbo_accessible" );
if( !level.console )
{
owner NotifyOnPlayerCommand( "rocket_fire_released", "-toggleads_throw" );
}
self.owner waittill( "rocket_fire_released" );
owner SetClientOmnvar( "ui_a10_rocket_lock", false );
self notify( "a10_missiles_fired" );
}
missileLockTarget( target ) // self == plane
{
config = level.planeConfigs[ self.streakName ];
info = [];
// veh_hud_target_marked
info["icon"] = target maps\mp\_entityheadIcons::setHeadIcon( self.owner, config.lockonIcon, kLockIconOffset, 10, 10, false, 0.05, true, false, false, false );
info["target"] = target;
self.targetList[ target GetEntityNumber() ] = info;
self.owner PlayLocalSound( "recondrone_lockon" );
// need to handle case where target dies before
}
isMissileTargeted( target ) // self == plane
{
return ( IsDefined( self.targetList[ target GetEntityNumber() ] ) );
}
fireMissiles() // self == plane
{
self endon( "death" );
level endon( "game_ended" );
config = level.planeConfigs[ self.streakName ];
foreach ( targetInfo in self.targetList )
{
if ( self.numRocketsLeft > 0 )
{
// fire at one target
missile = self onFireHomingMissile( self.streakName, targetInfo["target"], kLockIconOffset );
if ( IsDefined( targetInfo["icon"] ) )
{
missile.icon = targetInfo["icon"];
targetInfo["icon"] = undefined;
}
wait (config.delayBetweenRockets);
}
else
{
break;
}
}
targetList = [];
}
onFireHomingMissile( streakName, target, targetOffset ) // self == plane
{
side = self.numRocketsLeft % 2;
tagName = "tag_missile_" + (side + 1);
rocketPos = self GetTagOrigin( tagName );
if ( IsDefined( rocketPos ) )
{
owner = self.owner;
config = level.planeConfigs[ streakName ];
/*
eye_pos = owner GetEye();
eye_fwd = AnglesToForward( owner GetPlayerAngles() );
eye_trace = BulletTrace( eye_pos + eye_fwd * 360, eye_pos + eye_fwd * MISSILE_IMPACT_DIST_MAX, false, self );
eye_end_dist = max( MISSILE_IMPACT_DIST_MIN, eye_trace[ "fraction" ] * MISSILE_IMPACT_DIST_MAX );
rocket = MagicBullet( projectileName, rocketPos, rocketPos + eye_end_dist * eye_fwd, self.owner );
*/
rocket = MagicBullet( config.rocketModelName, rocketPos, rocketPos + 100 * AnglesToForward(self.angles), self.owner );
rocket thread a10_missile_set_target( target, targetOffset );
Earthquake (0.25, 0.05, self.origin, 512);
self.numRocketsLeft--;
self.owner SetClientOmnvar( "ui_a10_rocket", self.numRocketsLeft );
config = level.planeConfigs[ streakName ];
rocket PlaySoundOnMovingEnt( config.sfxMissileFire_1p[ side ] );
rocket PlayLoopSound( config.sfxMissile );
// self PlaySoundOnMovingEnt( "a10p_missile_launch" );
// HidePart doesn't work with helicopters?
// self HidePart( tagName );
// kill cam stuff?
return rocket;
}
return undefined;
}
MISSILE_IMPACT_DIST_MAX = 15000;
MISSILE_IMPACT_DIST_MIN = 1000;
onFireRocket( streakName ) // self == plane
{
tagName = "tag_missile_" + self.numRocketsLeft;
rocketPos = self GetTagOrigin( tagName );
if ( IsDefined( rocketPos ) )
{
owner = self.owner;
config = level.planeConfigs[ streakName ];
/*
eye_pos = owner GetEye();
eye_fwd = AnglesToForward( owner GetPlayerAngles() );
eye_trace = BulletTrace( eye_pos + eye_fwd * 360, eye_pos + eye_fwd * MISSILE_IMPACT_DIST_MAX, false, self );
eye_end_dist = max( MISSILE_IMPACT_DIST_MIN, eye_trace[ "fraction" ] * MISSILE_IMPACT_DIST_MAX );
rocket = MagicBullet( projectileName, rocketPos, rocketPos + eye_end_dist * eye_fwd, self.owner );
*/
rocket = MagicBullet( config.rocketModelName, rocketPos, rocketPos + 100 * AnglesToForward(self.angles), self.owner );
Earthquake (0.25, 0.05, self.origin, 512);
self.numRocketsLeft--;
self.owner SetClientOmnvar( "ui_a10_rocket", self.numRocketsLeft );
rocket PlaySoundOnMovingEnt( config.sfxMissileFire_1p[ self.numRocketsLeft ] );
rocket PlayLoopSound( config.sfxMissile );
self PlaySoundOnMovingEnt( "a10p_missile_launch" );
// HidePart doesn't work with helicopters?
// self HidePart( tagName );
// kill cam stuff?
}
}
a10_missile_set_target( target, offset )
{
self thread a10_missile_cleanup();
wait 0.2;
self Missile_SetTargetEnt( target, offset );
// self Missile_SetFlightmodeDirect();
}
a10_missile_cleanup()
{
self waittill( "death" );
if ( IsDefined( self.icon ) )
{
self.icon Destroy();
}
}
CANNON_SHAKE_TIME = 0.5;
monitorWeaponFire( streakName, plane ) // self == player
{
plane endon( "end_remote" );
plane endon( "death" );
self endon( "death" );
level endon( "game_ended" );
config = level.planeConfigs[ streakName ];
plane.ammoCount = 1350;
self SetClientOmnvar( "ui_a10_cannon", plane.ammoCount );
self NotifyOnPlayerCommand( "a10_cannon_start", "+attack" );
self NotifyOnPlayerCommand( "a10_cannon_stop", "-attack" );
while ( plane.ammoCount > 0 )
{
// IsFiringVehicleTurret
if ( !(self AttackButtonPressed()) )
{
self waittill( "a10_cannon_start" );
}
cannonShortBurstTimeLimit = GetTime() + config.sfxCannonFireBurpTime;
plane PlayLoopSound( config.sfxCannonFireLoop_1p );
plane thread updateCannonShake( streakName );
self waittill( "a10_cannon_stop" );
plane StopLoopSound( config.sfxCannonFireLoop_1p );
plane PlaySoundOnMovingEnt( config.sfxCannonFireStop_1p );
if ( GetTime() < cannonShortBurstTimeLimit )
{
playSoundAtPos( plane.origin, config.sfxCannonFireBurpShort_3p );
}
else
{
playSoundAtPos( plane.origin, config.sfxCannonFireBurpLong_3p );
}
}
}
// should eventually unify
updateCannonShake( streakName ) // self == plane
{
self.owner endon( "a10_cannon_stop" );
self endon( "death" );
level endon( "game_ended" );
config = level.planeConfigs[ streakName ];
while ( self.ammoCount > 0 )
{
Earthquake (0.2, CANNON_SHAKE_TIME, self.origin, 512);
self.ammoCount -= 10;
self.owner SetClientOmnvar( "ui_a10_cannon", self.ammoCount );
barrelPoint = self GetTagOrigin( "tag_flash_attach" ) + 20 * AnglesToForward( self.angles );
PlayFX( config.cannonFireVFX, barrelPoint );
self PlayRumbleOnEntity( config.cannonRumble );
// this needs to match the cannon's fire rate in the gdt
wait( 0.1 );
}
self.turret TurretFireDisable();
}
ALTITUDE_WARNING_LIMIT = 1000;
monitorAltitude( streakName, plane )
{
plane endon( "end_remote" );
plane endon( "death" );
self endon( "death" );
level endon( "game_ended" );
self SetClientOmnvar( "ui_a10_alt_warn", false );
while( true )
{
// the max is in omnvar
alt = Int( Clamp(plane.origin[2], 0, 16383) );
self SetClientOmnvar( "ui_a10_alt", alt );
if (alt <= ALTITUDE_WARNING_LIMIT && !IsDefined( plane.altWarning ) )
{
plane.altWarning = true;
self SetClientOmnvar( "ui_a10_alt_warn", true );
}
else if (alt > ALTITUDE_WARNING_LIMIT && IsDefined( plane.altWarning ) )
{
plane.altWarning = undefined;
self SetClientOmnvar( "ui_a10_alt_warn", false );
}
wait( 0.1 );
}
}
watchIntroCleared( streakName, plane ) // self == player
{
self endon( "disconnect" );
level endon( "game_ended" );
self waittill( "intro_cleared" );
self SetClientOmnvar( "ui_a10", true );
// self EnableWeapons();
self thread monitorAltitude( streakname, plane );
self thread monitorRocketFire2( streakName, plane );
self thread monitorWeaponFire( streakName, plane );
self thread watchRoundEnd( plane, streakName );
self ThermalVisionFOFOverlayOn();
/*
// pick a path
plane.curFlightPath = level.a10FlightPaths[ 0 ];
plane thread followFlightPath();
*/
self thread watchEarlyExit( plane );
}
watchRoundEnd( plane, streakName ) // self == player
{
plane endon( "death" );
plane endon( "leaving" );
self endon( "disconnect" );
self endon( "joined_team" );
self endon( "joined_spectators" );
level waittill_any( "round_end_finished", "game_ended" );
// leave
plane thread endFlyby( streakName );
self endStrafeSequence( streakName );
self a10_explode();
}
buildAllFlightPathsDefault()
{
// temp - do not check in - should be done per level
inBoundList = [];
inBoundList[0] = 1;
inBoundList[1] = 2;
inBoundList[2] = 3;
inBoundList[3] = 4;
inBoundList[4] = 1;
inBoundList[5] = 2;
inBoundList[6] = 4;
inBoundList[7] = 3;
outBoundList = [];
outBoundList[0] = 2;
outBoundList[1] = 1;
outBoundList[2] = 4;
outBoundList[3] = 3;
outBoundList[4] = 1;
outBoundList[5] = 4;
outBoundList[6] = 3;
outBoundList[7] = 2;
buildAllFlightPaths( inBoundList, outBoundList );
}
buildAllFlightPaths( inBoundList, outBoundList )
{
level.a10SplinesIn = inBoundList;
level.a10SplinesOut = outBoundList;
}
// stolen from a10_proto_script
// check it for more audio
a10_cockpit_breathing()
{
level endon("remove_player_control");
for(;;)
{
wait (RandomFloatRange(3.0, 7.0));
//level.player radio_dialog_add_and_go("a10_breathing_r");
}
}
watchEarlyExit( veh ) // self == player
{
level endon( "game_ended" );
veh endon( "death" );
veh endon( "a10_end_strafe" );
veh thread maps\mp\killstreaks\_killstreaks::allowRideKillstreakPlayerExit();
veh waittill("killstreakExit");
self notify("end_remote");
veh thread endFlyby( veh.streakName );
self endStrafeSequence( veh.streakName );
veh a10_explode();
}
a10_handleDamage()
{
self endon( "end_remote" );
config = level.planeConfigs[ self.streakName ];
self maps\mp\gametypes\_damage::monitorDamage(
config.maxHealth,
"helicopter",
::handleDeathDamage,
::modifyDamage,
true // isKillstreak
);
}
modifyDamage( attacker, weapon, type, damage )
{
modifiedDamage = damage;
// modifiedDamage = self maps\mp\gametypes\_damage::handleMeleeDamage( weapon, type, modifiedDamage );
modifiedDamage = self maps\mp\gametypes\_damage::handleEmpDamage( weapon, type, modifiedDamage );
modifiedDamage = self maps\mp\gametypes\_damage::handleMissileDamage( weapon, type, modifiedDamage );
modifiedDamage = self maps\mp\gametypes\_damage::handleAPDamage( weapon, type, modifiedDamage, attacker );
// do damage effects?
return modifiedDamage;
}
handleDeathDamage( attacker, weapon, type, damage ) // self == plane
{
config = level.planeConfigs[ self.streakName ];
// !!! need VO
self maps\mp\gametypes\_damage::onKillstreakKilled( attacker, weapon, type, damage, config.voDestroyed, config.xpPopup, config.callout );
self a10_explode();
}
// plane explode
a10_explode()
{
config = level.planeConfigs[ self.streakName ];
maps\mp\killstreaks\_plane::stopTrackingPlane( self );
PlayFX ( config.explodeVfx, self.origin );
self Delete(); // self Hide();
}