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

529 lines
19 KiB
Plaintext

#using scripts\codescripts\struct;
#using scripts\shared\callbacks_shared;
#using scripts\shared\hud_shared;
#using scripts\shared\util_shared;
#using scripts\shared\clientfield_shared;
#using scripts\shared\lui_shared;
#using scripts\mp\killstreaks\_qrdrone;
#using scripts\mp\_util;
#using scripts\mp\killstreaks\_ai_tank;
#using scripts\mp\killstreaks\_killstreaks;
#using scripts\mp\killstreaks\_killstreakrules;
#using scripts\mp\killstreaks\_turret;
// Manager for all weapons that can be remotely controlled with the tablet
#namespace remote_weapons;
function init()
{
level.remoteWeapons = [];
level.remoteExitHint = &"MP_REMOTE_EXIT";
callback::on_spawned( &on_player_spawned );
}
function on_player_spawned()
{
self endon("disconnect");
self AssignRemoteControlTrigger();
}
function RemoveAndAssignNewRemoteControlTrigger( remoteControlTrigger ) // player = self
{
ArrayRemoveValue( self.activeRemoteControlTriggers, remoteControlTrigger );
self AssignRemoteControlTrigger( true );
}
function AssignRemoteControlTrigger( force_new_assignment = false ) // player = self
{
if ( !isdefined( self.activeRemoteControlTriggers ) )
self.activeRemoteControlTriggers = [];
ArrayRemoveValue( self.activeRemoteControlTriggers, undefined );
if ( ( !isdefined( self.remoteControlTrigger ) || force_new_assignment ) && self.activeRemoteControlTriggers.size > 0 )
{
self.remoteControlTrigger = self.activeRemoteControlTriggers[ self.activeRemoteControlTriggers.size - 1 ];
}
if ( isdefined( self.remoteControlTrigger ) )
{
self.remoteControlTrigger.origin = self.origin;
self.remoteControlTrigger LinkTo( self );
}
}
function RegisterRemoteWeapon( weaponName, hintString, useCallback, endUseCallback, hideCompassOnUse = true )
{
assert( isdefined( level.remoteWeapons ) );
level.remoteWeapons[ weaponName ] = SpawnStruct();
level.remoteWeapons[ weaponName ].hintString = hintString;
level.remoteWeapons[ weaponName ].useCallback = useCallback;
level.remoteWeapons[ weaponName ].endUseCallback = endUseCallback;
level.remoteWeapons[ weaponName ].hideCompassOnUse = hideCompassOnUse;
}
function UseRemoteWeapon( weapon, weaponName, immediate, allowManualDeactivation = true, always_allow_ride = false )
{
player = self;
assert( IsPlayer( player ) );
weapon.remoteOwner = player;
weapon.initTime = GetTime();
weapon.remoteName = weaponName;
weapon.remoteWeaponAllowManualDeactivation = allowManualDeactivation;
weapon thread WatchRemoveRemoteControlledWeapon();
if( !immediate )
{
weapon CreateRemoteWeaponTrigger();
}
else
{
weapon thread WatchOwnerDisconnect();
weapon UseRemoteControlWeapon( allowManualDeactivation, always_allow_ride );
}
}
function WatchForHack()
{
weapon = self;
weapon endon( "death" );
weapon waittill( "killstreak_hacked", hacker );
if ( isdefined( weapon.remoteWeaponAllowManualDeactivation ) && weapon.remoteWeaponAllowManualDeactivation == true )
{
weapon thread WatchRemoteControlDeactivate();
}
weapon.remoteOwner = hacker;
}
function WatchRemoveRemoteControlledWeapon()
{
weapon = self;
weapon endon( "remote_weapon_end" );
weapon util::waittill_any( "death", "remote_weapon_shutdown" );
weapon EndRemoteControlWeaponUse( false );
while( isdefined( weapon ) )
{
{wait(.05);}; // Wait until any death animations and any other waits are finished
}
//Check for queued remote weapon
}
function CreateRemoteWeaponTrigger()
{
weapon = self;
player = weapon.remoteOwner;
if ( isdefined( weapon.useTrigger ) )
{
weapon.useTrigger delete();
}
weapon.useTrigger = spawn( "trigger_radius_use", player.origin, 32, 32 );
weapon.useTrigger EnableLinkTo();
weapon.useTrigger LinkTo( player );
weapon.useTrigger SetHintLowPriority( true );
weapon.useTrigger SetCursorHint( "HINT_NOICON" );
weapon.useTrigger SetHintString( level.remoteWeapons[ weapon.remoteName ].hintString );
weapon.useTrigger SetTeamForTrigger( player.team );
weapon.useTrigger.team = player.team;
player ClientClaimTrigger( weapon.useTrigger );
player.remoteControlTrigger = weapon.useTrigger;
player.activeRemoteControlTriggers[ player.activeRemoteControlTriggers.size ] = weapon.useTrigger;
weapon.useTrigger.ClaimedBy = player;
weapon thread WatchWeaponDeath();
weapon thread WatchOwnerDisconnect();
weapon thread WatchRemoteTriggerUse();
weapon thread WatchRemoteTriggerDisable();
}
function WatchWeaponDeath()
{
weapon = self;
weapon.useTrigger endon( "death" );
weapon util::waittill_any( "death", "remote_weapon_end" );
if ( isdefined( weapon.remoteOwner ) )
{
weapon.remoteOwner RemoveAndAssignNewRemoteControlTrigger( weapon.useTrigger );
}
weapon.useTrigger delete();
}
function WatchOwnerDisconnect()
{
weapon = self;
weapon endon( "remote_weapon_end" );
weapon endon( "remote_weapon_shutdown" );
if( isdefined( weapon.useTrigger ) )
weapon.useTrigger endon( "death" );
weapon.remoteOwner util::waittill_any( "joined_team", "disconnect", "joined_spectators" );
EndRemoteControlWeaponUse( false );
if( isdefined( weapon ) && isdefined( weapon.useTrigger ) )
weapon.useTrigger delete();
}
function WatchRemoteTriggerDisable()
{
weapon = self;
weapon endon( "remote_weapon_end" );
weapon endon( "remote_weapon_shutdown" );
weapon.useTrigger endon( "death" );
while( true )
{
weapon.useTrigger TriggerEnable( !( weapon.remoteOwner IsWallRunning() ) );
wait( 0.1 );
}
}
function AllowRemoteStart()
{
player = self;
if( player useButtonPressed() && !player.throwingGrenade && !player meleeButtonPressed() && !player util::isUsingRemote() && !( isdefined( player.carryObject ) && ( isdefined( player.carryObject.disallowRemoteControl ) && player.carryObject.disallowRemoteControl ) ) )
{
return true;
}
else
{
return false;
}
}
function WatchRemoteTriggerUse()
{
weapon = self;
weapon endon( "death" );
weapon endon( "remote_weapon_end" );
if( weapon.remoteOwner util::is_bot() )
{
return;
}
while( true )
{
weapon.useTrigger waittill( "trigger", player );
if( weapon.remoteOwner IsUsingOffhand() || weapon.remoteOwner IsWallRunning() )
{
continue;
}
if( isdefined( weapon.hackertrigger ) && isdefined( weapon.hackertrigger.progressbar ) )
{
if( weapon.remoteName == "killstreak_remote_turret" )
{
weapon.remoteOwner iPrintLnBold( &"KILLSTREAK_AUTO_TURRET_NOT_AVAILABLE" );
}
continue;
}
if( weapon.remoteOwner AllowRemoteStart() )
{
UseRemoteControlWeapon();
}
}
}
function UseRemoteControlWeapon( allowManualDeactivation = true, always_allow_ride = false )
{
self endon( "death" );
weapon = self;
assert( isdefined( weapon.remoteOwner ) );
weapon.control_initiated = true;
weapon.endRemoteControlWeapon = false;
weapon.remoteOwner endon( "disconnect" );
weapon.remoteOwner endon( "joined_team" );
weapon.remoteOwner DisableOffhandWeapons();
weapon.remoteOwner DisableWeaponCycling();
weapon.remoteOwner.dofutz = false;
if( !isdefined( weapon.disableRemoteWeaponSwitch ) )
{
remoteWeapon = GetWeapon( "killstreak_remote" );
weapon.remoteOwner giveWeapon( remoteWeapon );
weapon.remoteOwner switchToWeapon( remoteWeapon );
if ( always_allow_ride )
{
weapon.remoteOwner util::waittill_any( "weapon_change", "death" );
}
else
{
weapon.remoteOwner waittill( "weapon_change", newWeapon );
}
}
if( isdefined( newweapon ) )
{
if( newweapon != remoteWeapon )
{
weapon.remoteOwner killstreaks::clear_using_remote( true, true );
return;
}
}
weapon.remoteOwner thread killstreaks::watch_for_remove_remote_weapon();
weapon.remoteOwner util::setUsingRemote( weapon.remoteName );
weapon.remoteOwner util::freeze_player_controls( true );
result = weapon.remoteOwner killstreaks::init_ride_killstreak( weapon.remoteName, always_allow_ride );
if( result != "success" )
{
if( result != "disconnect" )
{
weapon.remoteOwner killstreaks::clear_using_remote();
weapon thread ResetControlInitiatedUponOwnerRespawn();
}
}
else
{
weapon.controlled = true;
weapon.killCamEnt = self;
weapon notify("remote_start"); // shuts down the AI scripts for this weapon
if ( allowManualDeactivation )
{
weapon thread watchRemoteControlDeactivate();
}
weapon.remoteOwner thread [[level.remoteWeapons[ weapon.remoteName ].useCallback]]( weapon );
if ( level.remoteWeapons[ weapon.remoteName ].hideCompassOnUse )
{
weapon.remoteOwner killstreaks::hide_compass();
}
}
weapon.remoteOwner util::freeze_player_controls( false );
}
function ResetControlInitiatedUponOwnerRespawn()
{
self endon( "death" );
self.remoteOwner waittill( "spawned" );
self.control_initiated = false;
}
function WatchRemoteControlDeactivate()
{
self notify("WatchRemoteControlDeactivate_remoteWeapons");
self endon ("WatchRemoteControlDeactivate_remoteWeapons");
weapon = self;
weapon endon( "remote_weapon_end" );
weapon endon( "death" );
weapon.remoteOwner endon( "disconnect" );
while( true )
{
timeUsed = 0;
while( weapon.remoteOwner UseButtonPressed() )
{
timeUsed += 0.05;
if ( timeUsed > 0.25 )
{
weapon thread EndRemoteControlWeaponUse( true );
return;
}
{wait(.05);};
}
{wait(.05);};
}
}
function EndRemoteControlWeaponUse( exitRequestedByOwner )
{
weapon = self;
if( !isdefined( weapon ) || ( isdefined( weapon.endRemoteControlWeapon ) && weapon.endRemoteControlWeapon ) )
return;
weapon.endRemoteControlWeapon = true;
remote_controlled = ( isdefined( weapon.control_initiated ) && weapon.control_initiated ) || ( isdefined( weapon.controlled ) && weapon.controlled );
while ( isdefined( weapon ) && ( weapon.forceWaitRemoteControl === true ) && ( remote_controlled == false ) )
{
remote_controlled = ( ( isdefined( weapon.control_initiated ) && weapon.control_initiated ) || ( isdefined( weapon.controlled ) && weapon.controlled ) );
{wait(.05);};
}
if ( !isdefined( weapon ) )
return;
if( isdefined( weapon.remoteOwner ) && remote_controlled )
{
if( isdefined( weapon.remoteWeaponShutdownDelay ) ) //when changing teams or disconnect, we can skip this
{
wait( weapon.remoteWeaponShutdownDelay );
}
player = weapon.remoteOwner;
if( player.dofutz === true )
{
player clientfield::set_to_player( "static_postfx", 1 );
wait 1;
if( isdefined( player ) )
{
player clientfield::set_to_player( "static_postfx", 0 );
player.dofutz = false;
}
}
else if ( !exitRequestedByOwner && weapon.watch_remote_weapon_death === true && !IsAlive( weapon ) )
{
wait ( isdefined( weapon.watch_remote_weapon_death_duration ) ? weapon.watch_remote_weapon_death_duration : 1.0 );
}
if( isdefined( player ) )
{
player thread FadeToBlackAndBackIn();
player waittill( "fade2black" ); // we the prev call to be blocking, in the same time we dont want to be left with black screen if smth external kills this thread.
if( remote_controlled )
player unlink();
player killstreaks::clear_using_remote( true ); // must come before the end use callback, its notify clears all the AI threads on the remote weapons
cleared_killstreak_delay = 1;
player EnableUsability(); // there are cases where the typical path to enable usability is not called, (because of some endon)
}
}
if( isdefined( weapon ) && isdefined( weapon.remoteName ) )
{
self [[ level.remoteWeapons[ weapon.remoteName ].endUseCallback]]( weapon, exitRequestedByOwner );
}
if( isdefined( weapon ))
{
weapon.killCamEnt = weapon;
if( isdefined( weapon.remoteOwner ) )
{
if ( remote_controlled )
{
weapon.remoteOwner unlink();
if( !( isdefined( cleared_killstreak_delay ) && cleared_killstreak_delay ) )
weapon.remoteOwner killstreaks::reset_killstreak_delay_killcam();
weapon.remoteOwner util::clientNotify( "nofutz" );
}
if( isdefined( level.gameEnded ) && level.gameEnded )
{
weapon.remoteOwner util::freeze_player_controls( true );
}
}
}
if( isdefined( weapon ) )
{
weapon.control_initiated = false;
weapon.controlled = false;
if( isdefined( weapon.remoteOwner ) )
weapon.remoteOwner killstreaks::unhide_compass();
if( !exitRequestedByOwner || ( isdefined( weapon.one_remote_use ) && weapon.one_remote_use ) )
weapon notify( "remote_weapon_end" );
}
}
function FadeToBlackAndBackIn()
{
self endon( "disconnect" );
// self endon( "death" ); // never end on death as it may never fade back in
lui::screen_fade_out( 0.1 );
self qrdrone::destroyHud();
{wait(.05);};
self notify( "fade2black" );
lui::screen_fade_in( .2 );
}
function stunStaticFX( duration )
{
self endon( "remove_remote_weapon" );
self.fullscreen_static.alpha = 0.65;
wait ( duration - 0.5 );
time = duration - 0.5;
while ( time < duration )
{
{wait(.05);};
time += 0.05;
self.fullscreen_static.alpha -= 0.05;
}
self.fullscreen_static.alpha = 0.15;
}
function destroyRemoteHUD()
{
self UseServerVisionset( false );
self SetInfraredVision( false );
if ( isdefined(self.fullscreen_static) )
{
self.fullscreen_static destroy();
}
if ( isdefined( self.hud_prompt_exit ))
{
self.hud_prompt_exit destroy();
}
}
function set_static( val )
{
owner = self.owner;
if( isdefined( owner ) && owner.usingvehicle && isdefined( owner.viewlockedentity ) && ( owner.viewlockedentity == self ) )
{
owner clientfield::set_to_player( "static_postfx", val );
}
}
function do_static_fx()
{
self endon( "death" );
self set_static( 1 );
wait 2;
self set_static( 0 );
self notify( "static_fx_done" );
}