boiii-scripts/mp/killstreaks/_satellite.gsc
2023-04-13 17:30:38 +02:00

373 lines
20 KiB
Plaintext

#using scripts\codescripts\struct;
#using scripts\shared\challenges_shared;
#using scripts\shared\clientfield_shared;
#using scripts\shared\system_shared;
#using scripts\shared\util_shared;
#using scripts\shared\hostmigration_shared;
#using scripts\shared\callbacks_shared;
#using scripts\shared\tweakables_shared;
#using scripts\shared\weapons\_heatseekingmissile;
#using scripts\shared\weapons\_weaponobjects;
#using scripts\shared\damagefeedback_shared;
#using scripts\shared\scoreevents_shared;
#using scripts\shared\math_shared;
#using scripts\shared\killstreaks_shared;
#using scripts\mp\gametypes\_battlechatter;
#using scripts\mp\gametypes\_globallogic_audio;
#using scripts\mp\killstreaks\_airsupport;
#using scripts\mp\killstreaks\_killstreak_bundles;
#using scripts\mp\killstreaks\_killstreak_hacking;
#using scripts\mp\killstreaks\_killstreakrules;
#using scripts\mp\killstreaks\_killstreaks;
#using scripts\mp\teams\_teams;
#using scripts\mp\_util;
#namespace satellite;
#precache( "string", "mpl_killstreak_satellite" );
#precache( "string", "KILLSTREAK_EARNED_SATELLITE" );
#precache( "string", "KILLSTREAK_SATELLITE_INBOUND" );
#precache( "string", "KILLSTREAK_DESTROYED_SATELLITE" );
#precache( "string", "KILLSTREAK_SATELLITE_NOT_AVAILABLE" );
#precache( "string", "KILLSTREAK_SATELLITE_HACKED" );
function init()
{
if ( level.teamBased )
{
foreach( team in level.teams )
{
level.activeSatellites[ team ] = 0;
}
}
else
{
level.activeSatellites = [];
}
level.activePlayerSatellites = [];
if ( tweakables::getTweakableValue( "killstreak", "allowradardirection" ) )
{
killstreaks::register( "satellite", "satellite", "killstreak_satellite", "uav_used", &ActivateSatellite );
killstreaks::register_strings( "satellite", &"KILLSTREAK_EARNED_SATELLITE", &"KILLSTREAK_SATELLITE_NOT_AVAILABLE", &"KILLSTREAK_SATELLITE_INBOUND", undefined, &"KILLSTREAK_SATELLITE_HACKED" );
killstreaks::register_dialog( "satellite", "mpl_killstreak_satellite", "satelliteDialogBundle", undefined, "friendlySatellite", "enemySatellite", "enemySatelliteMultiple", "friendlySatelliteHacked", "enemySatelliteHacked", "requestSatellite", "threatSatellite" );
}
callback::on_connect( &OnPlayerConnect );
callback::on_spawned( &OnPlayerSpawned );
level thread SatelliteTracker();
}
function OnPlayerConnect()
{
self.entnum = self getEntityNumber();
if ( !level.teamBased )
{
level.activeSatellites[ self.entnum ] = 0;
}
level.activePlayerSatellites[ self.entnum ] = 0; // needed for satellite-related kill scores
}
function OnPlayerSpawned( local_client_num )
{
if ( !level.teambased )
{
UpdatePlayerSatelliteForDM( self );
}
}
function ActivateSatellite()
{
if( self killstreakrules::isKillstreakAllowed( "satellite", self.team ) == false )
{
return false;
}
killstreak_id = self killstreakrules::killstreakStart( "satellite", self.team );
if( killstreak_id == -1 )
{
return false;
}
minFlyHeight = int( airsupport::getMinimumFlyHeight() );
zOffset = minFlyHeight + ( 5500 );
// pick a random start point from map center
travelAngle = RandomFloatRange( (isdefined(level.satellite_spawn_from_angle_min)?level.satellite_spawn_from_angle_min:( 90.0 )), (isdefined(level.satellite_spawn_from_angle_max)?level.satellite_spawn_from_angle_max:( 180.0 )) );
travelRadius = airsupport::GetMaxMapWidth() * ( 1.5 );
xOffset = sin( travelAngle ) * travelRadius;
yOffset = cos( travelAngle ) * travelRadius;
satellite = spawn( "script_model", airsupport::GetMapCenter() + ( xOffset, yOffset, zOffset ));
satellite setModel( "veh_t7_drone_srv_blimp" );
satellite SetScale( ( 1 ) );
satellite.killstreak_id = killstreak_id;
satellite.owner = self;
satellite.ownerEntNum = self GetEntityNumber();
satellite.team = self.team;
satellite setTeam( self.team );
satellite setOwner( self );
satellite killstreaks::configure_team( "satellite", killstreak_id, self, undefined, undefined, &ConfigureTeamPost );
satellite killstreak_hacking::enable_hacking( "satellite", &HackedPreFunction, undefined );
satellite.targetname = "satellite";
satellite.maxhealth = ( 700 );
satellite.lowhealth = ( ( 700 ) * 0.5 );
satellite.health = 99999;
satellite.leaving = false;
satellite SetCanDamage( true );
satellite thread killstreaks::MonitorDamage( "satellite", satellite.maxhealth, &DestroySatellite, satellite.lowhealth, &OnLowHealth, 0, undefined, false );
satellite thread killstreaks::WaitTillEMP( &DestroySatelliteByEMP );
// satellite.overrideVehicleDamage = &SatelliteDamageOverride; // satellite is not a vehicle right now
satellite.killstreakDamageModifier = &killstreakDamageModifier;
satellite.rocketDamage = ( satellite.maxhealth / ( 3 ) ) + 1;
/#
//Box( airsupport::GetMapCenter() + ( xOffset, yOffset, zOffset ), (-4, -4, 0 ), ( 4, 4, 5000 ), 0, ( 1, 0, 0 ), 0.6, false, 2000 );
//Box( airsupport::GetMapCenter() + ( -xOffset, -yoffset, zOffset ), (-4, -4, 0 ), ( 4, 4, 5000 ), 0, ( 0, 1, 0 ), 0.6, false, 2000 );
#/
satellite MoveTo( airsupport::GetMapCenter() + ( -xOffset, -yoffset, zOffset ), ( 40000 ) * 0.001 );
Target_Set( satellite );
satellite clientfield::set( "enemyvehicle", 1 );
satellite thread killstreaks::WaitForTimeout( "satellite", ( 40000 ), &OnTimeout, "death", "crashing" );
satellite thread heatseekingmissile::MissileTarget_ProximityDetonateIncomingMissile( "death", undefined, true );
satellite thread Rotate( ( 10 ) );
self killstreaks::play_killstreak_start_dialog( "satellite", self.team, killstreak_id );
satellite thread killstreaks::player_killstreak_threat_tracking( "satellite" );
self AddWeaponStat( GetWeapon( "satellite" ), "used", 1 );
return true;
}
function HackedPreFunction( hacker )
{
satellite = self;
satellite ResetActiveSatellite();
}
function ConfigureTeamPost( owner, isHacked )
{
satellite = self;
satellite thread teams::WaitUntilTeamChangeSingleTon( owner, "Satellite_watch_team_change", &OnTeamChange, self.entNum, "delete", "death", "leaving" );
if ( isHacked == false )
{
satellite teams::HideToSameTeam();
}
else
{
satellite SetVisibleToAll();
}
satellite AddActiveSatellite();
}
function Rotate( duration )
{
self endon( "death" );
while( true )
{
self rotateyaw( -360, duration );
wait( duration );
}
}
function OnLowHealth( attacker, weapon )
{
}
function OnTeamChange( entNum, event )
{
DestroySatellite( undefined, undefined );
}
function OnTimeout()
{
self killstreaks::play_pilot_dialog_on_owner( "timeout", "satellite" );
self.leaving = true;
self RemoveActiveSatellite();
airsupport::Leave( ( 10 ) );
wait( ( 10 ) );
if( Target_IsTarget( self ) )
Target_Remove( self );
self delete();
}
function DestroySatelliteByEMP( attacker, arg )
{
DestroySatellite( attacker, GetWeapon( "emp" ) );
}
function DestroySatellite( attacker = undefined, weapon = undefined )
{
attacker = self [[ level.figure_out_attacker ]]( attacker );
if ( isdefined( attacker ) && ( !isdefined( self.owner ) || self.owner util::IsEnemyPlayer( attacker ) ) )
{
challenges::destroyedAircraft( attacker, weapon, false );
scoreevents::processScoreEvent( "destroyed_satellite", attacker, self.owner, weapon );
attacker challenges::addFlySwatterStat( weapon, self );
LUINotifyEvent( &"player_callout", 2, &"KILLSTREAK_DESTROYED_SATELLITE", attacker.entnum );
if( !self.leaving )
self killstreaks::play_destroyed_dialog_on_owner( "satellite", self.killstreak_id );
}
self notify( "crashing" );
params = level.killstreakBundle["satellite"];
if( isdefined( params.ksExplosionFX ) )
PlayFXOnTag( params.ksExplosionFX, self, "tag_origin" );
self setModel( "tag_origin" );
if( Target_IsTarget( self ) )
Target_Remove( self );
wait( 0.5 );
if( !self.leaving )
self RemoveActiveSatellite();
self delete();
}
function HasSatellite( team_or_entnum )
{
return level.activeSatellites[ team_or_entnum ] > 0;
}
function AddActiveSatellite()
{
if ( level.teamBased )
{
level.activeSatellites[ self.team ]++;
}
else
{
level.activeSatellites[ self.ownerEntNum ]++;
}
level.activePlayerSatellites[ self.ownerEntNum ]++;
level notify( "satellite_update" );
}
function RemoveActiveSatellite()
{
self ResetActiveSatellite();
killstreakrules::killstreakStop( "satellite", self.originalteam, self.killstreak_id );
}
function ResetActiveSatellite()
{
if( level.teamBased )
{
level.activeSatellites[ self.team ]--;
assert( level.activeSatellites[ self.team ] >= 0 );
if( level.activeSatellites[ self.team ] < 0 )
{
level.activeSatellites[ self.team ] = 0;
}
}
else if ( isdefined( self.ownerEntNum ) )
{
level.activeSatellites[ self.ownerEntNum ]--;
assert( level.activeSatellites[ self.ownerEntNum ] >= 0 );
if( level.activeSatellites[ self.ownerEntNum ] < 0 )
{
level.activeSatellites[ self.ownerEntNum ] = 0;
}
}
assert( isdefined( self.ownerEntNum ) );
level.activePlayerSatellites[ self.ownerEntNum ]--;
assert( level.activePlayerSatellites[ self.ownerEntNum ] >= 0 );
level notify( "satellite_update" );
}
function SatelliteTracker()
{
level endon ( "game_ended" );
while( true )
{
level waittill ( "satellite_update" );
// intentionally keeping both teambased and non-teambased logic for now
// TODO: one "might" be able to change it to teambased only; when trying to do so, watch for knock-on effects
if( level.teamBased )
{
foreach( team in level.teams )
{
activeSatellites = level.activeSatellites[ team ];
activeSatellitesAndUAVs = activeSatellites + ( ( isdefined( level.activeUAVs ) ) ? level.activeUAVs[ team ] : 0 );
SetTeamSatellite( team, ( activeSatellites > 0 ) );
util::set_team_radar( team, ( activeSatellitesAndUAVs > 0 ) );
}
}
else
{
for( i = 0; i < level.players.size; i++ )
{
UpdatePlayerSatelliteForDM( level.players[ i ] );
}
}
}
}
function UpdatePlayerSatelliteForDM( player )
{
if( !isdefined( player.entnum ) )
{
player.entnum = player getEntityNumber();
}
activeSatellites = level.activeSatellites[ player.entnum ];
activeSatellitesAndUAVs = activeSatellites + ( ( isdefined( level.activeUAVs ) ) ? level.activeUAVs[ player.entnum ] : 0 );
player SetClientUIVisibilityFlag( "radar_client", ( activeSatellitesAndUAVs > 0 ) );
player.hasSatellite = ( activeSatellites > 0 );
}
function killstreakDamageModifier( damage, attacker, direction, point, sMeansOfDeath, tagName, modelName, partname, weapon, flags, inflictor, chargeLevel )
{
if( ( sMeansOfDeath == "MOD_PISTOL_BULLET" ) || ( sMeansOfDeath == "MOD_RIFLE_BULLET" ) )
return 0;
if ( sMeansOfDeath == "MOD_PROJECTILE_SPLASH" )
return 0;
return damage;
}