Files
Recompilable-gscs-for-BO2-z…/patch_mp/maps/mp/_heatseekingmissile.gsc

689 lines
14 KiB
Plaintext

#include maps/mp/killstreaks/_airsupport;
#include maps/mp/killstreaks/_helicopter;
#include maps/mp/gametypes/_weapon_utils;
#include common_scripts/utility;
#include maps/mp/_utility;
init()
{
precacherumble( "stinger_lock_rumble" );
game[ "locking_on_sound" ] = "uin_alert_lockon_start";
game[ "locked_on_sound" ] = "uin_alert_lockon";
precachestring( &"MP_CANNOT_LOCKON_TO_TARGET" );
thread onplayerconnect();
level.fx_flare = loadfx( "vehicle/vexplosion/fx_heli_chaff" );
/#
setdvar( "scr_freelock", "0" );
#/
}
onplayerconnect()
{
for ( ;; )
{
level waittill( "connecting", player );
player thread onplayerspawned();
}
}
onplayerspawned()
{
self endon( "disconnect" );
for ( ;; )
{
self waittill( "spawned_player" );
self clearirtarget();
thread stingertoggleloop();
self thread stingerfirednotify();
}
}
clearirtarget()
{
self notify( "stinger_irt_cleartarget" );
self notify( "stop_lockon_sound" );
self notify( "stop_locked_sound" );
self.stingerlocksound = undefined;
self stoprumble( "stinger_lock_rumble" );
self.stingerlockstarttime = 0;
self.stingerlockstarted = 0;
self.stingerlockfinalized = 0;
if ( isDefined( self.stingertarget ) )
{
lockingon( self.stingertarget, 0 );
lockedon( self.stingertarget, 0 );
}
self.stingertarget = undefined;
self weaponlockfree();
self weaponlocktargettooclose( 0 );
self weaponlocknoclearance( 0 );
self stoplocalsound( game[ "locking_on_sound" ] );
self stoplocalsound( game[ "locked_on_sound" ] );
self destroylockoncanceledmessage();
}
stingerfirednotify()
{
self endon( "disconnect" );
self endon( "death" );
while ( 1 )
{
self waittill( "missile_fire", missile, weap );
if ( maps/mp/gametypes/_weapon_utils::isguidedrocketlauncherweapon( weap ) )
{
if ( isDefined( self.stingertarget ) && self.stingerlockfinalized )
{
self.stingertarget notify( "stinger_fired_at_me" );
}
level notify( "missile_fired" );
self notify( "stinger_fired" );
}
}
}
stingertoggleloop()
{
self endon( "disconnect" );
self endon( "death" );
for ( ;; )
{
self waittill( "weapon_change", weapon );
while ( maps/mp/gametypes/_weapon_utils::isguidedrocketlauncherweapon( weapon ) )
{
abort = 0;
while ( !self playerstingerads() )
{
wait 0,05;
if ( !maps/mp/gametypes/_weapon_utils::isguidedrocketlauncherweapon( self getcurrentweapon() ) )
{
abort = 1;
break;
}
else
{
}
}
if ( abort )
{
break;
}
else self thread stingerirtloop();
while ( self playerstingerads() )
{
wait 0,05;
}
self notify( "stinger_IRT_off" );
self clearirtarget();
weapon = self getcurrentweapon();
}
}
}
stingerirtloop()
{
self endon( "disconnect" );
self endon( "death" );
self endon( "stinger_IRT_off" );
locklength = self getlockonspeed();
for ( ;; )
{
wait 0,05;
if ( self.stingerlockfinalized )
{
passed = softsighttest();
if ( !passed )
{
continue;
}
else if ( !isstillvalidtarget( self.stingertarget ) )
{
self clearirtarget();
continue;
}
else if ( !self.stingertarget.locked_on )
{
self.stingertarget notify( "missile_lock" );
}
lockingon( self.stingertarget, 0 );
lockedon( self.stingertarget, 1 );
thread looplocallocksound( game[ "locked_on_sound" ], 0,75 );
continue;
}
else if ( self.stingerlockstarted )
{
if ( !isstillvalidtarget( self.stingertarget ) )
{
self clearirtarget();
continue;
}
else lockingon( self.stingertarget, 1 );
lockedon( self.stingertarget, 0 );
passed = softsighttest();
if ( !passed )
{
continue;
}
else timepassed = getTime() - self.stingerlockstarttime;
if ( timepassed < locklength )
{
continue;
}
else /#
assert( isDefined( self.stingertarget ) );
#/
self notify( "stop_lockon_sound" );
self.stingerlockfinalized = 1;
self weaponlockfinalize( self.stingertarget );
continue;
}
else besttarget = self getbeststingertarget();
if ( !isDefined( besttarget ) )
{
self destroylockoncanceledmessage();
continue;
}
else if ( !self locksighttest( besttarget ) )
{
self destroylockoncanceledmessage();
continue;
}
else if ( self locksighttest( besttarget ) && isDefined( besttarget.lockondelay ) && besttarget.lockondelay )
{
self displaylockoncanceledmessage();
continue;
}
else
{
self destroylockoncanceledmessage();
initlockfield( besttarget );
self.stingertarget = besttarget;
self.stingerlockstarttime = getTime();
self.stingerlockstarted = 1;
self.stingerlostsightlinetime = 0;
self thread looplocalseeksound( game[ "locking_on_sound" ], 0,6 );
}
}
}
destroylockoncanceledmessage()
{
if ( isDefined( self.lockoncanceledmessage ) )
{
self.lockoncanceledmessage destroy();
}
}
displaylockoncanceledmessage()
{
if ( isDefined( self.lockoncanceledmessage ) )
{
return;
}
self.lockoncanceledmessage = newclienthudelem( self );
self.lockoncanceledmessage.fontscale = 1,25;
self.lockoncanceledmessage.x = 0;
self.lockoncanceledmessage.y = 50;
self.lockoncanceledmessage.alignx = "center";
self.lockoncanceledmessage.aligny = "top";
self.lockoncanceledmessage.horzalign = "center";
self.lockoncanceledmessage.vertalign = "top";
self.lockoncanceledmessage.foreground = 1;
self.lockoncanceledmessage.hidewhendead = 0;
self.lockoncanceledmessage.hidewheninmenu = 1;
self.lockoncanceledmessage.archived = 0;
self.lockoncanceledmessage.alpha = 1;
self.lockoncanceledmessage settext( &"MP_CANNOT_LOCKON_TO_TARGET" );
}
getbeststingertarget()
{
targetsall = target_getarray();
targetsvalid = [];
idx = 0;
while ( idx < targetsall.size )
{
/#
if ( getDvar( "scr_freelock" ) == "1" )
{
if ( self insidestingerreticlenolock( targetsall[ idx ] ) )
{
targetsvalid[ targetsvalid.size ] = targetsall[ idx ];
}
idx++;
continue;
#/
}
else if ( level.teambased )
{
if ( isDefined( targetsall[ idx ].team ) && targetsall[ idx ].team != self.team )
{
if ( self insidestingerreticlenolock( targetsall[ idx ] ) )
{
targetsvalid[ targetsvalid.size ] = targetsall[ idx ];
}
}
idx++;
continue;
}
else
{
if ( self insidestingerreticlenolock( targetsall[ idx ] ) )
{
if ( isDefined( targetsall[ idx ].owner ) && self != targetsall[ idx ].owner )
{
targetsvalid[ targetsvalid.size ] = targetsall[ idx ];
}
}
}
idx++;
}
if ( targetsvalid.size == 0 )
{
return undefined;
}
chosenent = targetsvalid[ 0 ];
if ( targetsvalid.size > 1 )
{
}
return chosenent;
}
insidestingerreticlenolock( target )
{
radius = self getlockonradius();
return target_isincircle( target, self, 65, radius );
}
insidestingerreticlelocked( target )
{
radius = self getlockonradius();
return target_isincircle( target, self, 65, radius );
}
isstillvalidtarget( ent )
{
if ( !isDefined( ent ) )
{
return 0;
}
if ( !target_istarget( ent ) )
{
return 0;
}
if ( !insidestingerreticlelocked( ent ) )
{
return 0;
}
return 1;
}
playerstingerads()
{
return self playerads() == 1;
}
looplocalseeksound( alias, interval )
{
self endon( "stop_lockon_sound" );
self endon( "disconnect" );
self endon( "death" );
for ( ;; )
{
self playlocalsound( alias );
self playrumbleonentity( "stinger_lock_rumble" );
wait ( interval / 2 );
}
}
looplocallocksound( alias, interval )
{
self endon( "stop_locked_sound" );
self endon( "disconnect" );
self endon( "death" );
if ( isDefined( self.stingerlocksound ) )
{
return;
}
self.stingerlocksound = 1;
for ( ;; )
{
self playlocalsound( alias );
self playrumbleonentity( "stinger_lock_rumble" );
wait ( interval / 6 );
self playlocalsound( alias );
self playrumbleonentity( "stinger_lock_rumble" );
wait ( interval / 6 );
self playlocalsound( alias );
self playrumbleonentity( "stinger_lock_rumble" );
wait ( interval / 6 );
self stoprumble( "stinger_lock_rumble" );
}
self.stingerlocksound = undefined;
}
locksighttest( target )
{
eyepos = self geteye();
if ( !isDefined( target ) )
{
return 0;
}
passed = bullettracepassed( eyepos, target.origin, 0, target );
if ( passed )
{
return 1;
}
front = target getpointinbounds( 1, 0, 0 );
passed = bullettracepassed( eyepos, front, 0, target );
if ( passed )
{
return 1;
}
back = target getpointinbounds( -1, 0, 0 );
passed = bullettracepassed( eyepos, back, 0, target );
if ( passed )
{
return 1;
}
return 0;
}
softsighttest()
{
lost_sight_limit = 500;
if ( self locksighttest( self.stingertarget ) )
{
self.stingerlostsightlinetime = 0;
return 1;
}
if ( self.stingerlostsightlinetime == 0 )
{
self.stingerlostsightlinetime = getTime();
}
timepassed = getTime() - self.stingerlostsightlinetime;
if ( timepassed >= lost_sight_limit )
{
self clearirtarget();
return 0;
}
return 1;
}
initlockfield( target )
{
if ( isDefined( target.locking_on ) )
{
return;
}
target.locking_on = 0;
target.locked_on = 0;
}
lockingon( target, lock )
{
/#
assert( isDefined( target.locking_on ) );
#/
clientnum = self getentitynumber();
if ( lock )
{
target notify( "locking on" );
target.locking_on |= 1 << clientnum;
self thread watchclearlockingon( target, clientnum );
}
else
{
self notify( "locking_on_cleared" );
target.locking_on &= 1 << clientnum;
}
}
watchclearlockingon( target, clientnum )
{
target endon( "death" );
self endon( "locking_on_cleared" );
self waittill_any( "death", "disconnect" );
target.locking_on &= 1 << clientnum;
}
lockedon( target, lock )
{
/#
assert( isDefined( target.locked_on ) );
#/
clientnum = self getentitynumber();
if ( lock )
{
target.locked_on |= 1 << clientnum;
self thread watchclearlockedon( target, clientnum );
}
else
{
self notify( "locked_on_cleared" );
target.locked_on &= 1 << clientnum;
}
}
watchclearlockedon( target, clientnum )
{
self endon( "locked_on_cleared" );
self waittill_any( "death", "disconnect" );
if ( isDefined( target ) )
{
target.locked_on &= 1 << clientnum;
}
}
missiletarget_lockonmonitor( player, endon1, endon2 )
{
self endon( "death" );
if ( isDefined( endon1 ) )
{
self endon( endon1 );
}
if ( isDefined( endon2 ) )
{
self endon( endon2 );
}
for ( ;; )
{
if ( target_istarget( self ) )
{
}
wait 0,1;
}
}
_incomingmissile( missile )
{
if ( !isDefined( self.incoming_missile ) )
{
self.incoming_missile = 0;
}
self.incoming_missile++;
self thread _incomingmissiletracker( missile );
}
_incomingmissiletracker( missile )
{
self endon( "death" );
missile waittill( "death" );
self.incoming_missile--;
/#
assert( self.incoming_missile >= 0 );
#/
}
missiletarget_ismissileincoming()
{
if ( !isDefined( self.incoming_missile ) )
{
return 0;
}
if ( self.incoming_missile )
{
return 1;
}
return 0;
}
missiletarget_handleincomingmissile( responsefunc, endon1, endon2 )
{
level endon( "game_ended" );
self endon( "death" );
if ( isDefined( endon1 ) )
{
self endon( endon1 );
}
if ( isDefined( endon2 ) )
{
self endon( endon2 );
}
for ( ;; )
{
self waittill( "stinger_fired_at_me", missile, weap, attacker );
_incomingmissile( missile );
if ( isDefined( responsefunc ) )
{
[[ responsefunc ]]( missile, attacker, weap, endon1, endon2 );
}
}
}
missiletarget_proximitydetonateincomingmissile( endon1, endon2 )
{
missiletarget_handleincomingmissile( ::missiletarget_proximitydetonate, endon1, endon2 );
}
_missiledetonate( attacker, weapon )
{
self endon( "death" );
radiusdamage( self.origin, 500, 600, 600, attacker, undefined, weapon );
wait 0,05;
self detonate();
wait 0,05;
self delete();
}
missiletarget_proximitydetonate( missile, attacker, weapon, endon1, endon2 )
{
level endon( "game_ended" );
missile endon( "death" );
if ( isDefined( endon1 ) )
{
self endon( endon1 );
}
if ( isDefined( endon2 ) )
{
self endon( endon2 );
}
mindist = distance( missile.origin, self.origin );
lastcenter = self.origin;
missile missile_settarget( self );
for ( ;; )
{
if ( !isDefined( self ) )
{
center = lastcenter;
}
else
{
center = self.origin;
}
lastcenter = center;
curdist = distance( missile.origin, center );
if ( curdist < 3500 && isDefined( self.numflares ) && self.numflares > 0 )
{
self.numflares--;
self thread missiletarget_playflarefx();
self maps/mp/killstreaks/_helicopter::trackassists( attacker, 0, 1 );
newtarget = self missiletarget_deployflares( missile.origin, missile.angles );
missile missile_settarget( newtarget );
missiletarget = newtarget;
return;
}
if ( curdist < mindist )
{
mindist = curdist;
}
if ( curdist > mindist )
{
if ( curdist > 500 )
{
return;
}
missile thread _missiledetonate( attacker, weapon );
}
wait 0,05;
}
}
missiletarget_playflarefx()
{
if ( !isDefined( self ) )
{
return;
}
flare_fx = level.fx_flare;
if ( isDefined( self.fx_flare ) )
{
flare_fx = self.fx_flare;
}
if ( isDefined( self.flare_ent ) )
{
playfxontag( flare_fx, self.flare_ent, "tag_origin" );
}
else
{
playfxontag( flare_fx, self, "tag_origin" );
}
if ( isDefined( self.owner ) )
{
self playsoundtoplayer( "veh_huey_chaff_drop_plr", self.owner );
}
self playsound( "veh_huey_chaff_explo_npc" );
}
missiletarget_deployflares( origin, angles )
{
vec_toforward = anglesToForward( self.angles );
vec_toright = anglesToRight( self.angles );
vec_tomissileforward = anglesToForward( angles );
delta = self.origin - origin;
dot = vectordot( vec_tomissileforward, vec_toright );
sign = 1;
if ( dot > 0 )
{
sign = -1;
}
flare_dir = vectornormalize( vectorScale( vec_toforward, -0,5 ) + vectorScale( vec_toright, sign ) );
velocity = vectorScale( flare_dir, randomintrange( 200, 400 ) );
velocity = ( velocity[ 0 ], velocity[ 1 ], velocity[ 2 ] - randomintrange( 10, 100 ) );
flareorigin = self.origin;
flareorigin += vectorScale( flare_dir, randomintrange( 500, 700 ) );
flareorigin += vectorScale( ( 1, 0, 0 ), 500 );
if ( isDefined( self.flareoffset ) )
{
flareorigin += self.flareoffset;
}
flareobject = spawn( "script_origin", flareorigin );
flareobject.angles = self.angles;
flareobject setmodel( "tag_origin" );
flareobject movegravity( velocity, 5 );
flareobject thread deleteaftertime( 5 );
self thread debug_tracker( flareobject );
return flareobject;
}
debug_tracker( target )
{
target endon( "death" );
while ( 1 )
{
maps/mp/killstreaks/_airsupport::debug_sphere( target.origin, 10, ( 1, 0, 0 ), 1, 1 );
wait 0,05;
}
}