s1-scripts-dev/raw/maps/mp/_stingerm7.gsc
2025-05-21 16:23:17 +02:00

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;
}