472 lines
12 KiB
Plaintext
472 lines
12 KiB
Plaintext
#include maps\mp\_utility;
|
|
#include common_scripts\utility;
|
|
|
|
CONST_stinger_weaponname = "stingerm7";
|
|
|
|
CONST_lock_require_los = true;
|
|
CONST_lock_angle = 5;
|
|
CONST_lock_time = 1;
|
|
CONST_max_locks = 4;
|
|
CONST_nosight_time_limit = 500;
|
|
|
|
|
|
stingerm7_think()
|
|
{
|
|
self thread stingerm7_targeting();
|
|
self thread stingerm7_monitor_fire();
|
|
}
|
|
|
|
stingerm7_targeting()
|
|
{
|
|
self endon( "death" );
|
|
self endon( "disconnect" );
|
|
self endon( "faux_spawn" );
|
|
self endon( "joined_team" );
|
|
|
|
self.stingerm7_info = SpawnStruct();
|
|
self.stingerm7_info.locked_targets = [];
|
|
self.stingerm7_info.locking_time = 0;
|
|
was_ads_stingerm7 = false;
|
|
|
|
while( true )
|
|
{
|
|
if ( IsSubStr( self GetCurrentWeapon(), CONST_stinger_weaponname ) && self PlayerAds() > .99 )
|
|
{
|
|
was_ads_stingerm7 = true;
|
|
|
|
if ( self.stingerm7_info.locked_targets.size > 0 )
|
|
{
|
|
self remove_invalid_locks();
|
|
}
|
|
self.stingerm7_info.locked_targets = array_remove_dead( array_removeUndefined( self.stingerm7_info.locked_targets ) );
|
|
|
|
if ( IsDefined( self.stingerm7_info.locking_target ) )
|
|
{
|
|
// Check that the stinger's current locking target is still valid. If not, remove it.
|
|
if ( !locking_target_still_valid( self.stingerm7_info.locking_target ) )
|
|
{
|
|
//Target_Remove(self.stingerm7_info.locking_target);
|
|
self.stingerm7_info.locking_target = undefined;
|
|
self notify( "stop_javelin_locking_feedback" );
|
|
}
|
|
}
|
|
|
|
if ( IsDefined( self.stingerm7_info.locking_target ) )
|
|
{
|
|
// If the stinger locking target wasn't removed above, increment the locking_time.
|
|
self.stingerm7_info.locking_time += .05;
|
|
}
|
|
else
|
|
{
|
|
// If there is no locking_target, try to get a new one.
|
|
self.stingerm7_info.locking_time = 0;
|
|
|
|
if ( self.stingerm7_info.locked_targets.size < CONST_max_locks )
|
|
{
|
|
self.stingerm7_info.locking_target = self get_best_locking_target();
|
|
if ( IsDefined( self.stingerm7_info.locking_target ) )
|
|
{
|
|
// Acquired a new locking target.
|
|
self thread locking_feedback();
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( self.stingerm7_info.locking_time >= CONST_lock_time && IsDefined( self.stingerm7_info.locking_target ) && self.stingerm7_info.locked_targets.size < CONST_max_locks )
|
|
{
|
|
// Lock on acquired.
|
|
self notify( "stop_javelin_locking_feedback" );
|
|
self.stingerm7_info.locked_targets[ self.stingerm7_info.locked_targets.size ] = self.stingerm7_info.locking_target;
|
|
|
|
self thread locked_feedback();
|
|
|
|
self.stingerm7_info.locking_target = undefined;
|
|
}
|
|
|
|
if ( self.stingerm7_info.locked_targets.size > 0 )
|
|
{
|
|
self WeaponLockFinalize( self.stingerm7_info.locked_targets[ 0 ] );
|
|
}
|
|
else
|
|
{
|
|
self WeaponLockFree();
|
|
self notify( "stop_javelin_locked_feedback" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( was_ads_stingerm7 == true )
|
|
{
|
|
// The player is not ADS with the StingerM7.
|
|
was_ads_stingerm7 = false;
|
|
self WeaponLockFree();
|
|
self notify( "stop_javelin_locking_feedback" );
|
|
self notify( "stop_javelin_locked_feedback" );
|
|
|
|
self.stingerm7_info.locked_targets = [];
|
|
|
|
if ( IsDefined( self.stingerm7_info.locking_target ) )
|
|
{
|
|
//Target_Remove(self.stingerm7_info.locking_target);
|
|
self.stingerm7_info.locking_target = undefined;
|
|
}
|
|
|
|
self.stingerm7_info.locking_time = 0;
|
|
}
|
|
}
|
|
wait( 0.05 );
|
|
}
|
|
}
|
|
|
|
stingerm7_monitor_fire()
|
|
{
|
|
self endon( "death" );
|
|
self endon( "disconnect" );
|
|
self endon( "faux_spawn" );
|
|
self endon( "joined_team" );
|
|
|
|
while( true )
|
|
{
|
|
self waittill( "missile_fire", projectile, weaponName );
|
|
if ( IsSubStr( weaponName, CONST_stinger_weaponname ) )
|
|
{
|
|
thread stinger_fire( self, projectile, weaponName );
|
|
}
|
|
}
|
|
}
|
|
|
|
stinger_fire( player, projectile, weapon_name )
|
|
{
|
|
// A bit of hack, we could instead modify the engine to fire multiple projectiles.
|
|
// instead, we just delete the one it fired and make our own.
|
|
|
|
init_origin = (0,0,0);
|
|
init_angles = (0,0,0);
|
|
if ( isDefined( projectile ) )
|
|
{
|
|
init_origin = projectile.origin;
|
|
init_angles = projectile.angles;
|
|
projectile Delete();
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
player.stingerm7_info.locked_targets = array_remove_dead( array_removeUndefined( self.stingerm7_info.locked_targets ) );
|
|
|
|
missiles = [];
|
|
|
|
for ( i = 0; i < CONST_max_locks; i++ )
|
|
{
|
|
fire_angles = init_angles + random_vector( 20, 20, 20 );
|
|
fire_direction = AnglesToForward( fire_angles );
|
|
|
|
new_projectile = MagicBullet( weapon_name, init_origin, init_origin + fire_direction, player );
|
|
new_projectile.owner = player;
|
|
|
|
// every locked target gets at least one shot, and remaining shots are randomly divided amongst locked targets
|
|
if ( player.stingerm7_info.locked_targets.size > 0 )
|
|
{
|
|
target = undefined;
|
|
if ( i < player.stingerm7_info.locked_targets.size )
|
|
target = player.stingerm7_info.locked_targets[ i ];
|
|
else
|
|
target = player.stingerm7_info.locked_targets[ RandomInt( player.stingerm7_info.locked_targets.size ) ];
|
|
|
|
new_projectile Missile_SetTargetEnt( target, stingerm7_get_target_offset( target ) );
|
|
new_projectile.lockedStingerTarget = target;
|
|
}
|
|
|
|
missiles[ missiles.size ] = new_projectile;
|
|
}
|
|
|
|
level notify( "stinger_fired", player, missiles );
|
|
|
|
// you used all your ammo
|
|
player SetWeaponAmmoClip( weapon_name, 0 );
|
|
}
|
|
|
|
anyStingerMissileLockedOn( missiles, target )
|
|
{
|
|
foreach ( missile in missiles )
|
|
{
|
|
if ( IsDefined( missile.lockedStingerTarget ) && missile.lockedStingerTarget == target )
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
get_best_locking_target()
|
|
{
|
|
Assert( IsPlayer( self ) );
|
|
|
|
enemy_team = getOtherTeam( self.team );
|
|
enemy_players = [];
|
|
|
|
//add enemy players
|
|
foreach( player in level.players )
|
|
{
|
|
if ( level.teamBased && player.team == self.team )
|
|
continue;
|
|
|
|
if( !isReallyAlive( player) )
|
|
continue;
|
|
|
|
enemy_players[ enemy_players.size ] = player;
|
|
}
|
|
|
|
//add enemy vehicles
|
|
all_vehicles = Vehicle_GetArray();
|
|
enemy_vehicles = [];
|
|
|
|
foreach( vehicle in all_vehicles )
|
|
{
|
|
if ( !isDefined( vehicle.owner ) )
|
|
continue;
|
|
|
|
if ( vehicle maps\mp\killstreaks\_aerial_utility::vehicleIsCloaked() )
|
|
continue;
|
|
|
|
if ( level.teamBased && vehicle.owner.team == self.team )
|
|
continue;
|
|
|
|
enemy_vehicles[ enemy_vehicles.size ] = vehicle;
|
|
}
|
|
|
|
//add horde mode targets
|
|
if( IsDefined( level.isHorde ) && level.isHorde )
|
|
{
|
|
foreach( agent in level.agentarray )
|
|
{
|
|
if ( level.teamBased && agent.team == self.team )
|
|
continue;
|
|
|
|
if( !isReallyAlive( agent) )
|
|
continue;
|
|
|
|
enemy_players[ enemy_players.size ] = agent;
|
|
}
|
|
|
|
foreach( vehicle in all_vehicles )
|
|
{
|
|
|
|
if ( vehicle maps\mp\killstreaks\_aerial_utility::vehicleIsCloaked() )
|
|
continue;
|
|
|
|
if ( level.teamBased && vehicle.team == self.team )
|
|
continue;
|
|
|
|
enemy_vehicles[ enemy_vehicles.size ] = vehicle;
|
|
}
|
|
|
|
}
|
|
|
|
aerialTargets = maps\mp\killstreaks\_killstreaks::getAerialKillstreakArray( enemy_team );
|
|
|
|
targets = array_combine( enemy_players, enemy_vehicles );
|
|
targets = array_combine( targets, aerialTargets );
|
|
if(IsDefined(level.stingerLockOnEntsFunc))
|
|
targets = array_combine( targets, [[level.stingerLockOnEntsFunc]](self) );
|
|
|
|
eye_origin = self GetEye();
|
|
eye_dir = AnglesToForward( self GetPlayerAngles() );
|
|
|
|
best_target = undefined;
|
|
best_target_dot = Cos( CONST_lock_angle );
|
|
foreach( target in targets )
|
|
{
|
|
if ( !array_contains( self.stingerm7_info.locked_targets, target ) )
|
|
{
|
|
target_origin = stingerm7_get_target_pos( target );
|
|
dot = VectorDot( VectorNormalize( target_origin - eye_origin ), eye_dir );
|
|
if ( dot > best_target_dot )
|
|
{
|
|
result = undefined;
|
|
can_target = !CONST_lock_require_los;
|
|
if ( !can_target )
|
|
{
|
|
tracePassed = BulletTracePassed( eye_origin, target_origin, false, target );
|
|
if ( tracePassed )
|
|
can_target = true;
|
|
}
|
|
|
|
if ( can_target )
|
|
{
|
|
best_target = target;
|
|
best_target_dot = dot;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return best_target;
|
|
}
|
|
|
|
locking_target_still_valid( target )
|
|
{
|
|
Assert( IsPlayer( self ) );
|
|
|
|
eye_origin = self GetEye();
|
|
eye_dir = AnglesToForward( self GetPlayerAngles() );
|
|
target_origin = stingerm7_get_target_pos( target );
|
|
|
|
if ( ( IsPlayer( target ) || IsBot( target ) || ( isDefined( level.isHorde ) && level.isHorde && IsAgent( target )) ) && !isReallyAlive( target ) )
|
|
return false;
|
|
|
|
if ( VectorDot( VectorNormalize( target_origin - eye_origin ), eye_dir ) > Cos( CONST_lock_angle ) )
|
|
{
|
|
if (!CONST_lock_require_los || BulletTracePassed( eye_origin, target_origin, false, target ) )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
remove_invalid_locks()
|
|
{
|
|
for ( i = 0; i <= self.stingerm7_info.locked_targets.size; i++ )
|
|
{
|
|
if ( IsDefined( self.stingerm7_info.locked_targets[i] ) && IsDefined( self.stingerm7_info.locked_targets[i].origin ) )
|
|
{
|
|
if ( !IsDefined( self.stingerm7_info.locked_targets[i].sight_lost_time ) )
|
|
{
|
|
self.stingerm7_info.locked_targets[i].sight_lost_time = -1;
|
|
}
|
|
|
|
origin_mod = ( 0, 0, 0 );
|
|
if ( IsPlayer( self.stingerm7_info.locked_targets[i] ) || IsBot( self.stingerm7_info.locked_targets[i] ) )
|
|
{
|
|
origin_mod = ( 0, 0, 64 );
|
|
}
|
|
|
|
if ( self WorldPointInReticle_Rect( self.stingerm7_info.locked_targets[i].origin + origin_mod, 50, 400, 200 ) )
|
|
{
|
|
if ( BulletTracePassed( self GetEye(), self.stingerm7_info.locked_targets[i].origin + origin_mod, false, self.stingerm7_info.locked_targets[i] ) )
|
|
{
|
|
// All checks pass, the target is still valid. Move onto the next one in the list.
|
|
self.stingerm7_info.locked_targets[i].sight_lost_time = -1;
|
|
continue;
|
|
}
|
|
}
|
|
// A check failed, line of sight to target lost.
|
|
if ( self.stingerm7_info.locked_targets[i].sight_lost_time == -1 )
|
|
{
|
|
self.stingerm7_info.locked_targets[i].sight_lost_time = GetTime();
|
|
}
|
|
else if ( GetTime() - self.stingerm7_info.locked_targets[i].sight_lost_time >= CONST_nosight_time_limit )
|
|
{
|
|
self.stingerm7_info.locked_targets[i].sight_lost_time = -1;
|
|
self.stingerm7_info.locked_targets[i] = undefined;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
stingerm7_get_target_pos( target )
|
|
{
|
|
if(IsDefined(target.getStingerTargetPosFunc))
|
|
return target [[target.getStingerTargetPosFunc]]();
|
|
|
|
return target GetPointInBounds( 0, 0, 0 );
|
|
}
|
|
|
|
stingerm7_get_target_offset( target )
|
|
{
|
|
return stingerm7_get_target_pos( target ) - target.origin;
|
|
}
|
|
|
|
locking_feedback()
|
|
{
|
|
self endon( "death" );
|
|
self endon( "disconnect" );
|
|
self endon( "faux_spawn" );
|
|
self endon( "joined_team" );
|
|
self endon( "stop_javelin_locking_feedback" );
|
|
|
|
for ( ;; )
|
|
{
|
|
if( isDefined( level.SpawnedWarbirds ) )
|
|
{
|
|
foreach( warbird in level.SpawnedWarbirds )
|
|
{
|
|
if( isDefined( warbird.owner ) && isDefined( warbird.player ) && isDefined( self.stingerm7_info.locking_target ) && self.stingerm7_info.locking_target == warbird )
|
|
warbird.owner playLocalSound( "wpn_stingerm7_enemy_locked" );
|
|
}
|
|
}
|
|
|
|
if ( isDefined( level.orbitalsupport_player ) && isDefined( self.stingerm7_info.locking_target ) && self.stingerm7_info.locking_target == level.orbitalsupport_planeModel )
|
|
level.orbitalsupport_player playLocalSound( "wpn_stingerm7_enemy_locked" );
|
|
|
|
self playLocalSound( "wpn_stingerm7_locking" );
|
|
self PlayRumbleOnEntity( "heavygun_fire" );
|
|
|
|
wait 0.6;
|
|
}
|
|
}
|
|
|
|
locked_feedback()
|
|
{
|
|
self endon( "death" );
|
|
self endon( "disconnect" );
|
|
self endon( "faux_spawn" );
|
|
self endon( "joined_team" );
|
|
self endon( "stop_javelin_locked_feedback" );
|
|
|
|
for ( ;; )
|
|
{
|
|
if( isDefined( level.SpawnedWarbirds ) )
|
|
{
|
|
foreach( warbird in level.SpawnedWarbirds )
|
|
{
|
|
if( isDefined( warbird.owner ) && isDefined( warbird.player ) && isDefined( self.stingerm7_info.locked_targets ) && IsInArray( self.stingerm7_info.locked_targets, warbird ) )
|
|
warbird.owner playLocalSound( "wpn_stingerm7_enemy_locked" );
|
|
|
|
}
|
|
}
|
|
|
|
if ( isDefined( level.orbitalsupport_player ) && isDefined( self.stingerm7_info.locked_targets ) && IsInArray( self.stingerm7_info.locked_targets, level.orbitalsupport_planeModel ) )
|
|
level.orbitalsupport_player playLocalSound( "wpn_stingerm7_enemy_locked" );
|
|
|
|
self playLocalSound( "wpn_stingerm7_locked" );
|
|
self PlayRumbleOnEntity( "heavygun_fire" );
|
|
|
|
wait 0.25;
|
|
}
|
|
}
|
|
|
|
///////////////////////
|
|
|
|
array_remove_dead( array )
|
|
{
|
|
temp = [];
|
|
|
|
foreach( thing in array )
|
|
{
|
|
if ( !isAlive( thing ) )
|
|
continue;
|
|
|
|
temp[ temp.size ] = thing;
|
|
}
|
|
|
|
return temp;
|
|
}
|
|
|
|
random_vector( num1, num2, num3 )
|
|
{
|
|
return( RandomFloat( num1 ) - num1 * 0.5, RandomFloat( num2 ) - num2 * 0.5, RandomFloat( num3 ) - num3 * 0.5 );
|
|
}
|
|
|
|
IsInArray( array, Ent )
|
|
{
|
|
if ( IsDefined( array ) )
|
|
{
|
|
foreach ( Index in array )
|
|
{
|
|
if ( Index == Ent )
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
} |