373 lines
20 KiB
Plaintext
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;
|
|
}
|