891 lines
20 KiB
Plaintext
891 lines
20 KiB
Plaintext
#include maps\mp\_utility;
|
|
#include maps\mp\gametypes\_hud_util;
|
|
#include common_scripts\utility;
|
|
|
|
init()
|
|
{
|
|
//PrecacheMiniMapIcon( "compass_objpoint_reaper_friendly" );
|
|
//PrecacheMiniMapIcon( "compass_objpoint_reaper_enemy" );
|
|
|
|
level.killStreakFuncs["lasedStrike"] = ::tryUseLasedStrike;
|
|
level.numberOfSoflamAmmo = 2;
|
|
|
|
level.lasedStrikeGlow = loadfx("fx/misc/laser_glow");
|
|
level.lasedStrikeExplode = LoadFX( "fx/explosions/uav_advanced_death" );
|
|
|
|
//level.lasedStrikeActive = false;
|
|
//level.lasedStrikeDrone = undefined;
|
|
|
|
remoteMissileSpawnArray = getEntArray( "remoteMissileSpawn" , "targetname" );
|
|
foreach ( startPoint in remoteMissileSpawnArray )
|
|
{
|
|
if ( isDefined( startPoint.target ) )
|
|
startPoint.targetEnt = getEnt( startPoint.target, "targetname" );
|
|
}
|
|
level.lasedStrikeEnts = remoteMissileSpawnArray;
|
|
|
|
thread onPlayerConnect();
|
|
}
|
|
|
|
onPlayerConnect()
|
|
{
|
|
for(;;)
|
|
{
|
|
level waittill("connected", player);
|
|
player thread onPlayerSpawned();
|
|
player.soflamAmmoUsed = 0;
|
|
player.hasSoflam = false;
|
|
}
|
|
}
|
|
|
|
onPlayerSpawned()
|
|
{
|
|
self endon("disconnect");
|
|
|
|
for(;;)
|
|
{
|
|
self waittill( "spawned_player" );
|
|
|
|
//if( isDefined( level.soflamCrate ) )
|
|
// level.soflamCrate maps\mp\killstreaks\_airdrop::setUsableByTeam( self.team );
|
|
}
|
|
}
|
|
|
|
|
|
tryUseLasedStrike( lifeId, streakName )
|
|
{
|
|
return useLasedStrike();
|
|
}
|
|
|
|
|
|
useLasedStrike()
|
|
{
|
|
//self maps\mp\killstreaks\_killstreaks::giveKillstreakWeapon( "iw5_soflam_mp" );
|
|
|
|
//level thread teamPlayerCardSplash( "teamstreak_earned_lasedStrike", self, self.team );
|
|
used = self watchSoflamUsage();
|
|
|
|
if ( isDefined( used ) && used )
|
|
{
|
|
self.hasSoflam = false;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
giveMarker()
|
|
{
|
|
//wait( .25 );
|
|
self maps\mp\killstreaks\_killstreaks::giveKillstreakWeapon( "iw5_soflam_mp" );
|
|
|
|
self.hasSoflam = true;
|
|
self thread watchSoflamUsage();
|
|
}
|
|
|
|
|
|
watchSoflamUsage()
|
|
{
|
|
self notify( "watchSoflamUsage" );
|
|
self endon( "watchSoflamUsage" );
|
|
|
|
level endon( "game_ended" );
|
|
self endon( "disconnect" );
|
|
self endon( "death" );
|
|
|
|
while( self isChangingWeapon() )
|
|
wait ( 0.05 );
|
|
|
|
for(;;)
|
|
{
|
|
|
|
if ( self AttackButtonPressed() && self GetCurrentWeapon() == "iw5_soflam_mp" && self AdsButtonPressed() )
|
|
{
|
|
//self WeaponLockNoClearance( false );
|
|
self WeaponLockTargetTooClose( false );
|
|
self WeaponLockFree();
|
|
|
|
targetInfo = getTargetPoint();
|
|
|
|
if( !isDefined( targetInfo ) )
|
|
{
|
|
wait 0.05;
|
|
continue;
|
|
}
|
|
|
|
if( !isDefined( targetInfo[0] ) )
|
|
{
|
|
wait 0.05;
|
|
continue;
|
|
}
|
|
|
|
targPoint = targetInfo[0];
|
|
|
|
used = self attackLasedTarget( targPoint );
|
|
|
|
if ( used )
|
|
self.soflamAmmoUsed++;
|
|
|
|
if ( self.soflamAmmoUsed >= level.numberOfSoflamAmmo )
|
|
return true;
|
|
}
|
|
|
|
if ( self isChangingWeapon() )
|
|
return false;
|
|
|
|
wait( 0.05 );
|
|
}
|
|
|
|
}
|
|
|
|
playLockSound()
|
|
{
|
|
if ( isDefined( self.playingLockSound ) && self.playingLockSound )
|
|
return;
|
|
|
|
self PlayLocalSound( "javelin_clu_lock" );
|
|
self.playingLockSound = true;
|
|
|
|
wait( .75 );
|
|
|
|
self StopLocalSound( "javelin_clu_lock" );
|
|
self.playingLockSound = false;
|
|
}
|
|
|
|
playLockErrorSound()
|
|
{
|
|
if ( isDefined( self.playingLockSound ) && self.playingLockSound )
|
|
return;
|
|
|
|
self PlayLocalSound( "javelin_clu_aquiring_lock" );
|
|
self.playingLockSound = true;
|
|
|
|
wait( .75 );
|
|
|
|
self StopLocalSound( "javelin_clu_aquiring_lock" );
|
|
self.playingLockSound = false;
|
|
}
|
|
|
|
|
|
attackLasedTarget( targPoint )
|
|
{
|
|
finalTargetEnt = undefined;
|
|
midTargetEnt = undefined;
|
|
|
|
upQuantity = 6000;
|
|
upVector = (0, 0, upQuantity );
|
|
backDist = 3000;
|
|
forward = AnglesToForward( self.angles );
|
|
ownerOrigin = self.origin;
|
|
startpos = ownerOrigin + upVector + forward * backDist * -1;
|
|
|
|
foundAngle = false;
|
|
|
|
//straight down
|
|
|
|
skyTrace = bulletTrace( targPoint + (0,0,upQuantity), targPoint , false );
|
|
if( skyTrace["fraction"] > .99 )
|
|
{
|
|
foundAngle = true;
|
|
startPos = targPoint + (0,0,upQuantity);
|
|
}
|
|
//self thread drawLine( targPoint, targPoint + (0,0,upQuantity), 25, (1,0,0) );
|
|
|
|
|
|
if( !foundAngle )
|
|
{
|
|
skyTrace = bulletTrace( targPoint + (300,0,upQuantity), targPoint , false );
|
|
if( skyTrace["fraction"] > .99 )
|
|
{
|
|
foundAngle = true;
|
|
startPos = targPoint + (300,0,upQuantity);
|
|
}
|
|
//self thread drawLine( targPoint, targPoint + (300,0,upQuantity), 25, (1,0,0) );
|
|
}
|
|
|
|
if( !foundAngle )
|
|
{
|
|
skyTrace = bulletTrace( targPoint + (0,300,upQuantity), targPoint , false );
|
|
if( skyTrace["fraction"] > .99 )
|
|
{
|
|
foundAngle = true;
|
|
startPos = targPoint + (0,300,upQuantity);
|
|
}
|
|
//self thread drawLine( targPoint, targPoint + (0,300,upQuantity), 25, (1,0,0) );
|
|
}
|
|
|
|
if( !foundAngle )
|
|
{
|
|
skyTrace = bulletTrace( targPoint + (0,-300,upQuantity), targPoint , false );
|
|
if( skyTrace["fraction"] > .99 )
|
|
{
|
|
foundAngle = true;
|
|
startPos = targPoint + (0,-300,upQuantity);
|
|
}
|
|
//self thread drawLine( targPoint, targPoint + (0,-300,upQuantity), 25, (1,0,0) );
|
|
}
|
|
|
|
if( !foundAngle )
|
|
{
|
|
skyTrace = bulletTrace( targPoint + (300,300,upQuantity), targPoint , false );
|
|
if( skyTrace["fraction"] > .99 )
|
|
{
|
|
foundAngle = true;
|
|
startPos = targPoint + (300,300,upQuantity);
|
|
}
|
|
//self thread drawLine( targPoint, targPoint + (300,300,upQuantity), 25, (1,0,0) );
|
|
}
|
|
|
|
if( !foundAngle )
|
|
{
|
|
skyTrace = bulletTrace( targPoint + (-300,0,upQuantity), targPoint , false );
|
|
if( skyTrace["fraction"] > .99 )
|
|
{
|
|
foundAngle = true;
|
|
startPos = targPoint + (-300,0,upQuantity);
|
|
}
|
|
//self thread drawLine( targPoint, targPoint + (-300,0,upQuantity), 25, (1,0,0) );
|
|
}
|
|
|
|
if( !foundAngle )
|
|
{
|
|
skyTrace = bulletTrace( targPoint + (-300,-300,upQuantity), targPoint , false );
|
|
if( skyTrace["fraction"] > .99 )
|
|
{
|
|
foundAngle = true;
|
|
startPos = targPoint + (-300,-300,upQuantity);
|
|
}
|
|
//self thread drawLine( targPoint, targPoint + (-300,-300,upQuantity), 25, (1,0,0) );
|
|
}
|
|
|
|
if( !foundAngle )
|
|
{
|
|
skyTrace = bulletTrace( targPoint + (300,-300,upQuantity), targPoint , false );
|
|
if( skyTrace["fraction"] > .99 )
|
|
{
|
|
foundAngle = true;
|
|
startPos = targPoint + (300,-300,upQuantity);
|
|
}
|
|
//self thread drawLine( targPoint, targPoint + (300,-300,upQuantity), 25, (1,0,0) );
|
|
}
|
|
|
|
//backwards vector from player over target area
|
|
if( !foundAngle )
|
|
{
|
|
for ( i = 0; i < 5; i++ )
|
|
{
|
|
upQuantity = upQuantity / 2;
|
|
upVector = (0, 0, upQuantity );
|
|
startpos = self.origin + upVector + forward * backDist * -1;
|
|
|
|
targetSkyCheck = BulletTrace( targPoint, startpos, false );
|
|
if ( targetSkyCheck["fraction"] > .99 )
|
|
{
|
|
foundAngle = true;
|
|
break;
|
|
}
|
|
wait( 0.05 );
|
|
}
|
|
}
|
|
|
|
//check increased angle to try to get it over large objects
|
|
if( !foundAngle )
|
|
{
|
|
for ( i = 0; i < 5; i++ )
|
|
{
|
|
upQuantity = upQuantity * 2.5;
|
|
|
|
upVector = (0, 0, upQuantity );
|
|
startpos = self.origin + upVector + forward * backDist * -1;
|
|
|
|
targetSkyCheck = BulletTrace( targPoint, startpos, false );
|
|
if ( targetSkyCheck["fraction"] > .99 )
|
|
{
|
|
foundAngle = true;
|
|
break;
|
|
}
|
|
wait( 0.05 );
|
|
}
|
|
}
|
|
|
|
if( !foundAngle )
|
|
{
|
|
self thread cantHitTarget();
|
|
return false;
|
|
}
|
|
|
|
//finalTargetEnt = Spawn( "script_origin", targPoint );
|
|
finalTargetEnt = SpawnFx( level.lasedStrikeGlow, targPoint );
|
|
|
|
self thread playLockSound();
|
|
//self WeaponLockFinalize( finalTargetEnt, (0,0,0), false );
|
|
self WeaponLockFinalize( targPoint, (0,0,0), false );
|
|
|
|
missile = MagicBullet("lasedStrike_missile_mp", startPos, targPoint, self);
|
|
missile Missile_SetTargetEnt( finalTargetEnt );
|
|
|
|
self thread loopTriggeredeffect( finalTargetEnt, missile );
|
|
|
|
missile waittill( "death" );
|
|
|
|
if( isDefined( finalTargetEnt ) )
|
|
{
|
|
finalTargetEnt delete();
|
|
}
|
|
|
|
self WeaponLockFree();
|
|
return true;
|
|
}
|
|
|
|
loopTriggeredEffect( effect, missile )
|
|
{
|
|
missile endon( "death" );
|
|
level endon( "game_ended" );
|
|
|
|
for( ;; )
|
|
{
|
|
TriggerFX( effect );
|
|
wait ( 0.05 );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
lasedMissileDistance( remote )
|
|
{
|
|
level endon( "game_ended" );
|
|
remote endon( "death" );
|
|
remote endon( "remote_done" );
|
|
self endon( "death" );
|
|
|
|
while( true )
|
|
{
|
|
targetDist = distance( self.origin, remote.targetent.origin );
|
|
remote.owner SetClientDvar( "ui_reaper_targetDistance", int( targetDist / 12 ) );
|
|
|
|
wait( 0.05 );
|
|
}
|
|
}
|
|
|
|
cantHitTarget()
|
|
{
|
|
self thread playLockErrorSound();
|
|
//self WeaponLockNoClearance( true );
|
|
self WeaponLockTargetTooClose( true );
|
|
}
|
|
|
|
|
|
//does one check per frame
|
|
checkBestTargetVector( remote, targPoint )
|
|
{
|
|
|
|
foreach( ent in level.lasedStrikeEnts )
|
|
{
|
|
check = BulletTrace( ent.origin, targPoint, false, remote );
|
|
if ( check["fraction"] >= .98 )
|
|
{
|
|
return ent;
|
|
}
|
|
|
|
wait (0.05 );
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
getTargetPoint()
|
|
{
|
|
origin = self GetEye();
|
|
angles = self GetPlayerAngles();
|
|
forward = AnglesToForward( angles );
|
|
endpoint = origin + forward * 15000;
|
|
|
|
res = BulletTrace( origin, endpoint, false, undefined );
|
|
|
|
if ( res["surfacetype"] == "none" )
|
|
return undefined;
|
|
if ( res["surfacetype"] == "default" )
|
|
return undefined;
|
|
|
|
ent = res["entity"];
|
|
if ( IsDefined( ent ) )
|
|
{
|
|
if ( ent == level.ac130.planeModel )
|
|
return undefined;
|
|
}
|
|
|
|
results = [];
|
|
results[0] = res["position"];
|
|
results[1] = res["normal"];
|
|
|
|
return results;
|
|
}
|
|
|
|
|
|
//Not In Use
|
|
spawnRemote( owner )
|
|
{
|
|
remote = spawnPlane( owner, "script_model", level.UAVRig getTagOrigin( "tag_origin" ), "compass_objpoint_reaper_friendly", "compass_objpoint_reaper_enemy" );
|
|
if ( !isDefined( remote ) )
|
|
return undefined;
|
|
|
|
remote setModel( "vehicle_predator_b" );
|
|
remote.team = owner.team;
|
|
remote.owner = owner;
|
|
remote.numFlares = 2;
|
|
|
|
remote setCanDamage( true );
|
|
remote thread damageTracker();
|
|
|
|
remote.heliType = "remote_mortar";
|
|
|
|
// for target lists (javelin, stinger, sam, emp, etc)
|
|
remote.uavType = "remote_mortar";
|
|
remote maps\mp\killstreaks\_uav::addUAVModel();
|
|
|
|
// same height and radius as the AC130 with random angle and counter rotation
|
|
zOffset = 6300;
|
|
angle = randomInt( 360 );
|
|
radiusOffset = 6100;
|
|
xOffset = cos( angle ) * radiusOffset;
|
|
yOffset = sin( angle ) * radiusOffset;
|
|
angleVector = vectorNormalize( (xOffset,yOffset,zOffset) );
|
|
angleVector = ( angleVector * 6100 );
|
|
remote linkTo( level.UAVRig, "tag_origin", angleVector, (0,angle-90,10) );
|
|
|
|
remote thread handleDeath( owner );
|
|
|
|
remote thread handleOwnerChangeTeam( owner );
|
|
remote thread handleOwnerDisconnect( owner );
|
|
remote thread handleTimeOut();
|
|
|
|
remote thread handleIncomingStinger();
|
|
remote thread handleIncomingSAM();
|
|
|
|
return remote;
|
|
}
|
|
|
|
|
|
handleDeath( owner )
|
|
{
|
|
level endon( "game_ended" );
|
|
owner endon( "disconnect" );
|
|
self endon( "remote_removed" );
|
|
self endon( "remote_done" );
|
|
|
|
self waittill( "death" );
|
|
|
|
level thread removeRemote( self, true );
|
|
}
|
|
|
|
|
|
handleOwnerChangeTeam( owner )
|
|
{
|
|
level endon( "game_ended" );
|
|
self endon( "remote_done" );
|
|
self endon( "death" );
|
|
owner endon( "disconnect" );
|
|
owner endon( "removed_reaper_ammo" );
|
|
|
|
owner waittill_any( "joined_team", "joined_spectators" );
|
|
|
|
self thread remoteLeave();
|
|
}
|
|
|
|
|
|
handleOwnerDisconnect( owner )
|
|
{
|
|
level endon( "game_ended" );
|
|
self endon( "remote_done" );
|
|
self endon( "death" );
|
|
owner endon( "removed_reaper_ammo" );
|
|
|
|
owner waittill( "disconnect" );
|
|
|
|
self thread remoteLeave();
|
|
}
|
|
|
|
|
|
shotCounter()
|
|
{
|
|
level endon( "game_ended" );
|
|
self endon( "death" );
|
|
self endon( "remote_done" );
|
|
|
|
numShotsFired = 0;
|
|
|
|
for( ;; )
|
|
{
|
|
self waittill( "lasedTargetShotFired" );
|
|
|
|
numShotsFired++;
|
|
|
|
if ( numShotsFired >= 5 )
|
|
break;
|
|
}
|
|
|
|
self thread remoteLeave();
|
|
}
|
|
|
|
|
|
handleTimeOut()
|
|
{
|
|
level endon( "game_ended" );
|
|
self endon( "death" );
|
|
self endon( "remote_done" );
|
|
|
|
wait 120;
|
|
|
|
self thread remoteLeave();
|
|
}
|
|
|
|
removeRemote( remote, clearLevelRef )
|
|
{
|
|
self notify( "remote_removed" );
|
|
|
|
if ( isDefined( remote.targetEnt ) )
|
|
remote.targetEnt delete();
|
|
|
|
level.lasedStrikeActive = false;
|
|
level.lasedStrikeCrateActive = false;
|
|
|
|
if( IsDefined( remote ) )
|
|
{
|
|
remote delete();
|
|
remote maps\mp\killstreaks\_uav::removeUAVModel();
|
|
}
|
|
|
|
if ( !IsDefined( clearLevelRef ) || clearLevelRef == true )
|
|
level.remote_mortar = undefined;
|
|
}
|
|
|
|
|
|
remoteLeave()
|
|
{
|
|
// setting the level variable here because there is a bug if this gets shot down on the way out then this doesn't get cleared because of the endon("death")
|
|
// now it'll definitely get cleared as soon as it tries to leave
|
|
level.remote_mortar = undefined;
|
|
|
|
level endon( "game_ended" );
|
|
self endon( "death" );
|
|
|
|
self notify( "remote_done" );
|
|
|
|
destPoint = self.origin + ( AnglesToForward( self.angles ) * 20000 );
|
|
self moveTo( destPoint, 30 );
|
|
PlayFXOnTag( level._effect[ "ac130_engineeffect" ] , self, "tag_origin" );
|
|
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( 3 );
|
|
|
|
self moveTo( destPoint, 4, 4, 0.0 );
|
|
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( 4 );
|
|
|
|
level thread removeRemote( self, false );
|
|
}
|
|
|
|
|
|
remoteExplode()
|
|
{
|
|
self notify( "death" );
|
|
self Hide();
|
|
forward = ( AnglesToRight( self.angles ) * 200 );
|
|
playFx ( level.lasedStrikeExplode, self.origin, forward );
|
|
|
|
level.lasedStrikeActive = false;
|
|
level.lasedStrikeCrateActive = false;
|
|
}
|
|
|
|
|
|
// Entities spawned from SpawnPlane do not respond to pre-damage callbacks
|
|
// so we have to wait until we get the post-damage event.
|
|
//
|
|
// Because the damage has already happened by the time we find out about it,
|
|
// we need to use an artificially high health value, restore it on erroneous damage
|
|
// events and track a virtual damage taken against a virtual max health.
|
|
damageTracker()
|
|
{
|
|
level endon( "game_ended" );
|
|
self.owner endon( "disconnect" );
|
|
|
|
self.health = 999999; // keep it from dying anywhere in code
|
|
self.maxHealth = 1500; // this is the health we'll check
|
|
self.damageTaken = 0; // how much damage has it taken
|
|
|
|
while( true )
|
|
{
|
|
self waittill( "damage", damage, attacker, direction_vec, point, meansOfDeath, modelName, tagName, partName, iDFlags, weapon );
|
|
|
|
// don't allow people to destroy things on their team if FF is off
|
|
if ( !maps\mp\gametypes\_weapons::friendlyFireCheck( self.owner, attacker ) )
|
|
continue;
|
|
|
|
if ( !IsDefined( self ) )
|
|
return;
|
|
|
|
if ( isDefined( iDFlags ) && ( iDFlags & level.iDFLAGS_PENETRATION ) )
|
|
self.wasDamagedFromBulletPenetration = true;
|
|
|
|
self.wasDamaged = true;
|
|
|
|
modifiedDamage = damage;
|
|
|
|
if( IsPlayer( attacker ) )
|
|
{
|
|
attacker maps\mp\gametypes\_damagefeedback::updateDamageFeedback( "" );
|
|
|
|
if( meansOfDeath == "MOD_RIFLE_BULLET" || meansOfDeath == "MOD_PISTOL_BULLET" )
|
|
{
|
|
if ( attacker _hasPerk( "specialty_armorpiercing" ) )
|
|
modifiedDamage += damage * level.armorPiercingMod;
|
|
}
|
|
}
|
|
|
|
if( IsDefined( weapon ) )
|
|
{
|
|
switch( weapon )
|
|
{
|
|
case "stinger_mp":
|
|
case "javelin_mp":
|
|
self.largeProjectileDamage = true;
|
|
modifiedDamage = self.maxhealth + 1;
|
|
break;
|
|
|
|
case "sam_projectile_mp":
|
|
self.largeProjectileDamage = true;
|
|
break;
|
|
}
|
|
|
|
maps\mp\killstreaks\_killstreaks::killstreakHit( attacker, weapon, self );
|
|
}
|
|
|
|
self.damageTaken += modifiedDamage;
|
|
|
|
if( IsDefined( self.owner ) )
|
|
self.owner playLocalSound( "reaper_damaged" );
|
|
|
|
if ( self.damageTaken >= self.maxHealth )
|
|
{
|
|
if ( isPlayer( attacker ) && ( !isDefined( self.owner ) || attacker != self.owner ) )
|
|
{
|
|
attacker notify( "destroyed_killstreak", weapon );
|
|
thread teamPlayerCardSplash( "callout_destroyed_remote_mortar", attacker );
|
|
attacker thread maps\mp\gametypes\_rank::giveRankXP( "kill", 50, weapon, meansOfDeath );
|
|
attacker thread maps\mp\gametypes\_rank::xpEventPopup( "destroyed_remote_mortar" );
|
|
thread maps\mp\gametypes\_missions::vehicleKilled( self.owner, self, undefined, attacker, damage, meansOfDeath, weapon );
|
|
|
|
}
|
|
|
|
if ( isDefined( self.owner ) )
|
|
self.owner StopLocalSound( "missile_incoming" );
|
|
|
|
self thread remoteExplode();
|
|
// adding this to make sure it gets undefined, there was a weird bug where it could get killed as soon as it was leaving
|
|
// then the threads got killed because of the endon's and this never got reset
|
|
level.remote_mortar = undefined;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
handleIncomingStinger() // self == remote mortar
|
|
{
|
|
level endon ( "game_ended" );
|
|
self endon ( "death" );
|
|
self endon ( "remote_done" );
|
|
|
|
while( true )
|
|
{
|
|
level waittill ( "stinger_fired", player, missile, lockTarget );
|
|
|
|
if ( !IsDefined( lockTarget ) || (lockTarget != self) )
|
|
continue;
|
|
|
|
missile thread stingerProximityDetonate( lockTarget, player );
|
|
}
|
|
}
|
|
|
|
stingerProximityDetonate( missileTarget, player ) // self == missile
|
|
{
|
|
self endon ( "death" );
|
|
missileTarget endon( "death" );
|
|
|
|
if( IsDefined( missileTarget.owner ) )
|
|
missileTarget.owner PlayLocalSound( "missile_incoming" );
|
|
|
|
self Missile_SetTargetEnt( missileTarget );
|
|
|
|
minDist = Distance( self.origin, missileTarget GetPointInBounds( 0, 0, 0 ) );
|
|
lastCenter = missileTarget GetPointInBounds( 0, 0, 0 );
|
|
|
|
while( true )
|
|
{
|
|
// already destroyed
|
|
if( !IsDefined( missileTarget ) )
|
|
center = lastCenter;
|
|
else
|
|
center = missileTarget GetPointInBounds( 0, 0, 0 );
|
|
|
|
lastCenter = center;
|
|
|
|
curDist = Distance( self.origin, center );
|
|
|
|
if( curDist < 3000 && missileTarget.numFlares > 0 )
|
|
{
|
|
missileTarget.numFlares--;
|
|
|
|
missileTarget thread maps\mp\killstreaks\_flares::flares_playFx();
|
|
newTarget = missileTarget maps\mp\killstreaks\_flares::flares_deploy();
|
|
|
|
self Missile_SetTargetEnt( newTarget );
|
|
missileTarget = newTarget;
|
|
|
|
if( IsDefined( missileTarget.owner ) )
|
|
missileTarget.owner StopLocalSound( "missile_incoming" );
|
|
|
|
return;
|
|
}
|
|
|
|
if( curDist < minDist )
|
|
minDist = curDist;
|
|
|
|
if( curDist > minDist )
|
|
{
|
|
if( curDist > 1536 )
|
|
return;
|
|
|
|
if( IsDefined( missileTarget.owner ) )
|
|
{
|
|
missileTarget.owner stopLocalSound( "missile_incoming" );
|
|
|
|
if( level.teambased )
|
|
{
|
|
if( missileTarget.team != player.team )
|
|
RadiusDamage( self.origin, 1000, 1000, 1000, player, "MOD_EXPLOSIVE", "stinger_mp" );
|
|
}
|
|
else
|
|
{
|
|
RadiusDamage( self.origin, 1000, 1000, 1000, player, "MOD_EXPLOSIVE", "stinger_mp" );
|
|
}
|
|
}
|
|
|
|
self Hide();
|
|
|
|
wait( 0.05 );
|
|
self delete();
|
|
}
|
|
|
|
wait ( 0.05 );
|
|
}
|
|
}
|
|
|
|
handleIncomingSAM() // self == remote mortar
|
|
{
|
|
level endon ( "game_ended" );
|
|
self endon ( "death" );
|
|
self endon ( "remote_done" );
|
|
|
|
while( true )
|
|
{
|
|
level waittill ( "sam_fired", player, missileGroup, lockTarget );
|
|
|
|
if ( !IsDefined( lockTarget ) || (lockTarget != self) )
|
|
continue;
|
|
|
|
level thread samProximityDetonate( lockTarget, player, missileGroup );
|
|
}
|
|
}
|
|
|
|
samProximityDetonate( missileTarget, player, missileGroup )
|
|
{
|
|
missileTarget endon( "death" );
|
|
|
|
if( IsDefined( missileTarget.owner ) )
|
|
missileTarget.owner PlayLocalSound( "missile_incoming" );
|
|
|
|
sam_projectile_damage = 150; // this should match the gdt entry
|
|
sam_projectile_damage_radius = 1000;
|
|
|
|
minDist = [];
|
|
for( i = 0; i < missileGroup.size; i++ )
|
|
{
|
|
if( IsDefined( missileGroup[ i ] ) )
|
|
minDist[ i ] = Distance( missileGroup[ i ].origin, missileTarget GetPointInBounds( 0, 0, 0 ) );
|
|
else
|
|
minDist[ i ] = undefined;
|
|
}
|
|
|
|
while( true )
|
|
{
|
|
center = missileTarget GetPointInBounds( 0, 0, 0 );
|
|
|
|
curDist = [];
|
|
for( i = 0; i < missileGroup.size; i++ )
|
|
{
|
|
if( IsDefined( missileGroup[ i ] ) )
|
|
curDist[ i ] = Distance( missileGroup[ i ].origin, center );
|
|
}
|
|
|
|
for( i = 0; i < curDist.size; i++ )
|
|
{
|
|
if( IsDefined( curDist[ i ] ) )
|
|
{
|
|
// if one of the missiles in the group get close, set off flares and redirect them all
|
|
if( curDist[ i ] < 3000 && missileTarget.numFlares > 0 )
|
|
{
|
|
missileTarget.numFlares--;
|
|
|
|
missileTarget thread maps\mp\killstreaks\_flares::flares_playFx();
|
|
newTarget = missileTarget maps\mp\killstreaks\_flares::flares_deploy();
|
|
|
|
for( j = 0; j < missileGroup.size; j++ )
|
|
{
|
|
if( IsDefined( missileGroup[ j ] ) )
|
|
{
|
|
missileGroup[ j ] Missile_SetTargetEnt( newTarget );
|
|
}
|
|
}
|
|
|
|
if( IsDefined( missileTarget.owner ) )
|
|
missileTarget.owner StopLocalSound( "missile_incoming" );
|
|
|
|
return;
|
|
}
|
|
|
|
if( curDist[ i ] < minDist[ i ] )
|
|
minDist[ i ] = curDist[ i ];
|
|
|
|
if( curDist[ i ] > minDist[ i ] )
|
|
{
|
|
if( curDist[ i ] > 1536 )
|
|
continue;
|
|
|
|
if( IsDefined( missileTarget.owner ) )
|
|
{
|
|
missileTarget.owner StopLocalSound( "missile_incoming" );
|
|
|
|
if( level.teambased )
|
|
{
|
|
if( missileTarget.team != player.team )
|
|
RadiusDamage( missileGroup[ i ].origin, sam_projectile_damage_radius, sam_projectile_damage, sam_projectile_damage, player, "MOD_EXPLOSIVE", "sam_projectile_mp" );
|
|
}
|
|
else
|
|
{
|
|
RadiusDamage( missileGroup[ i ].origin, sam_projectile_damage_radius, sam_projectile_damage, sam_projectile_damage, player, "MOD_EXPLOSIVE", "sam_projectile_mp" );
|
|
}
|
|
}
|
|
|
|
missileGroup[ i ] Hide();
|
|
|
|
wait ( 0.05 );
|
|
missileGroup[ i ] delete();
|
|
}
|
|
}
|
|
}
|
|
|
|
wait ( 0.05 );
|
|
}
|
|
}
|