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

484 lines
11 KiB
Plaintext

#include maps\mp\_utility;
#include common_scripts\utility;
CONST_cloak_duration = 10;
CONST_cloak_cooldown_min_duration = 5;
droneGetSpawnPoint( eyeZOffset ) // self == player
{
if ( !IsDefined( eyeZOffset ) )
eyeZOffset = 50;
forwardOffset = 75;
trace_radius = 23; // Should match vehicle GDT settings
trace_height = trace_radius * 2; // Needs to be at least twice the radius (for some reason)
eye = ( self.origin + ( 0, 0, eyeZOffset ) );
angles = self getplayerangles();
forward = anglestoforward( flat_angle( angles ) );
end = eye + ( forward * forwardOffset );
spawnOrigin = end;
spawnAngles = self.angles;
placementOK = true;
// get the drone out of water
offset = getSpawnInWaterOffset( spawnOrigin + ( 0, 0, -1 * 30 ) );
if ( IsDefined( offset ) && offset > 0 )
{
spawnOrigin += ( 0, 0, offset );
eye += ( 0, 0, offset );
}
else if ( !IsDefined( offset ) )
{
placementOK = false;
}
// Ensure the player can see the placement position
if ( placementOK && !SightTracePassed( eye, end, true, self ) )
{
placementOK = false;
}
// Small test for vehicle clip & glass
if ( placementOK )
{
trace = BulletTrace( eye, end, true, self, true, false, true, true, true );
if ( trace["fraction"] < 1 )
placementOK = false;
}
// Ensure the point is not in solid
if ( placementOK )
{
start = eye + ( 0, 0, trace_height * -0.5 );
end = end + ( 0, 0, trace_height * -0.5 );
trace = self AIPhysicsTrace( start, end, trace_radius, trace_height, false, true );
if ( trace["fraction"] < 1 )
placementOK = false;
}
results = SpawnStruct();
results.placementOK = placementOK;
results.origin = spawnOrigin;
results.angles = spawnAngles;
return results;
}
getSpawnInWaterOffset( spawnOrigin )
{
triggers = getentarray( "trigger_underwater", "targetname" );
if ( triggers.size == 0 )
return 0;
MAX_UNITS_UP = 200;
unitsUp = 0;
testOrigin = Spawn( "script_origin", spawnOrigin );
touchingWater = false;
while ( unitsUp < MAX_UNITS_UP )
{
if ( touchingWaterTriggers( testOrigin, triggers ) )
{
unitsUp += 10;
testOrigin.origin += ( 0, 0, 10 );
}
else
{
break;
}
}
testOrigin Delete();
if ( unitsUp >= MAX_UNITS_UP )
return undefined;
else
return unitsUp;
}
touchingWaterTriggers( ent, triggers )
{
for ( i = 0; i < triggers.size; i++ )
{
trigger = triggers[i];
if ( ent IsTouching( trigger ) )
return true;
}
return false;
}
droneAddToGlobalList( entNum )
{
level.ugvs[entNum] = self;
}
droneRemoveFromGlobalList( entNum )
{
level.ugvs[entNum] = undefined;
}
// Cloaking
droneInitCloakOmnvars() // self == player
{
// self SetClientOmnvar( "ui_drone_cloak", 0 );
// self SetClientOmnvar( "ui_drone_cloaktext", 0 );
// self SetClientOmnvar( "ui_drone_cloaktime", 0 );
// self SetClientOmnvar( "ui_drone_cloakdur", 0 );
}
droneSetupCloaking( vehicle, startAsCloaked ) // self == player
{
vehicle endon( "death" );
droneInitCloakOmnvars();
vehicle.cloakState = 0;
vehicle.CloakCooldown = 0;
self droneCloakingTransition( vehicle, true, true ); // Wait to cloak and then show the model
maps\mp\killstreaks\_killstreaks::playerWaittillRideKillstreakComplete();
if ( IsDefined( startAsCloaked ) && startAsCloaked )
{
self thread droneMonitorDamageWhileCloaking( vehicle );
self SetClientOmnvar( "ui_drone_cloak", 2 );
// Update cloak end time (for HUD meter)
cloakMS = CONST_cloak_duration * 1000;
cloakEndTime = GetTime() + cloakMS;
self SetClientOmnvar( "ui_drone_cloak_time", cloakEndTime );
vehicle.CloakCooldown = CONST_cloak_cooldown_min_duration;
thread CloakCooldown( vehicle );
self thread droneCloakWaitForExit( vehicle );
}
else
{
vehicle PlaySound( "recon_drn_cloak_deactivate" );
self droneCloakingTransition( vehicle, false ); // Decloak immediately
}
}
droneIsCloaked( vehicle ) // self == player
{
return ( vehicle.hasCloak && vehicle.cloakState >= 0 );
}
droneCloakReady( vehicle, startAsCloaked ) // self == player
{
vehicle endon( "death" );
if ( IsDefined( startAsCloaked ) && startAsCloaked )
{
thread droneCloakCooldown( vehicle );
self waittill( "CloakCharged" );
}
while( true )
{
self SetClientOmnvar( "ui_drone_cloak", 1 ); // Cloak Ready
thread droneCloakActivated( vehicle );
thread droneCloakCooldown( vehicle );
if ( vehicle.CloakCooldown != 0 )
{
self SetClientOmnvar( "ui_drone_cloak", 3 );
wait vehicle.CloakCooldown;
}
if ( vehicle.hasCloak )
self SetClientOmnvar( "ui_drone_cloak", 1 );
vehicle waittill( "Cloak" );
vehicle notify( "ActivateCloak" );
vehicle PlaySound( "recon_drn_cloak_activate" );
//the cloak has been used and has fully recharged.
self waittill( "CloakCharged" );
}
}
droneCloakActivated( vehicle )
{
vehicle endon ( "death" );
vehicle waittill( "ActivateCloak" );
self thread droneCloakingTransition( vehicle, true );
self thread droneMonitorDamageWhileCloaking( vehicle );
// Update cloak end time (for HUD meter)
cloakMS = CONST_cloak_duration * 1000;
cloakEndTime = GetTime() + cloakMS;
self SetClientOmnvar( "ui_drone_cloak_time", cloakEndTime );
// Update the hud text (decloak)
self SetClientOmnvar( "ui_drone_cloak", 2 );
vehicle.CloakCooldown = CONST_cloak_cooldown_min_duration;
thread CloakCooldown( vehicle );
self thread droneCloakWaitForExit( vehicle );
}
droneCloakCooldown( vehicle )
{
vehicle endon( "death" );
self waittill( "UnCloak" );
vehicle PlaySound( "recon_drn_cloak_deactivate" );
self thread droneCloakingTransition( vehicle, false );
// Update the hud text (cloak recharging)
self SetClientOmnvar( "ui_drone_cloak", 3 );
self thread droneCloakDeactivatedDialog( vehicle );
}
CloakCooldown( vehicle )
{
vehicle endon( "death" );
self waittill( "UnCloak" );
while( vehicle.CloakCooldown > 0 )
{
vehicle.CloakCooldown -= 0.5;
wait 0.5;
}
vehicle.CloakCooldown = 0;
self notify( "CloakCharged" );
}
droneCloakWaitForExit( vehicle )
{
vehicle endon( "death" );
start = GetTime();
self waittill_any_timeout_no_endon_death( CONST_cloak_duration, "ForceUncloak", "Cloak" );
end = GetTime();
cooldownDuration = max( ( end - start ), CONST_cloak_cooldown_min_duration * 1000 );
vehicle.CloakCooldown = cooldownDuration / 1000;
cooldownEnd = GetTime() + cooldownDuration;
self SetClientOmnvar( "ui_drone_cloak_cooldown", cooldownEnd );
self notify( "UnCloak" );
}
droneCloakingTransition( vehicle, enable, init )
{
vehicle notify( "cloaking_transition" );
vehicle endon( "cloaking_transition" );
vehicle endon( "death" );
if ( enable )
{
if ( vehicle.cloakState == -2 )
return;
vehicle.cloakState = -1;
vehicle CloakingEnable();
if ( IsDefined( vehicle.mgTurret ) )
vehicle.mgTurret CloakingEnable();
vehicle Vehicle_SetMinimapVisible( false );
if ( !isdefined( init ) || !init )
wait 2.2; // should match the code values for the transition + a small time
else
wait 1.5; // during init, we want to give enough time for the cloaking to start then hide, before we unhide
vehicle Show();
if ( IsDefined( vehicle.mgTurret ) )
vehicle.mgTurret Show();
vehicle.cloakState = -2;
}
else
{
if ( vehicle.cloakState == 2 )
return;
vehicle.cloakState = 1;
vehicle CloakingDisable();
vehicle Vehicle_SetMinimapVisible( true );
if ( IsDefined( vehicle.mgTurret ) )
vehicle.mgTurret CloakingDisable();
wait 2.2; // should match the code values for the transition
vehicle.cloakState = 2;
}
}
droneCloakDeactivatedDialog( vehicle )
{
vehicle endon( "death" );
self endon( "CloakCharged" );
while ( true )
{
self waittill( "Cloak" );
self playlocalsound( "recon_drn_cloak_notready" );
wait 1;
}
}
droneMonitorDamageWhileCloaking( vehicle )
{
vehicle endon( "death" );
self endon( "UnCloak" );
wait 1;
vehicle waittill( "damage" );
self notify( "ForceUncloak" );
}
updateShootingLocation( vehicle, effect, ignoreTurret )
{
vehicle endon( "death" );
self endon( "disconnect" );
vehicle endon( "stopShootLocationUpdate" );
vehicle.targetEnt = spawn( "script_model", ( 0, 0, 0 ) );
vehicle.targetEnt setModel( "tag_origin" );
vehicle.targetEnt.angles = ( -90, 0, 0 );
if ( IsDefined( vehicle.mgTurret ) && ( !IsDefined( ignoreTurret ) || !ignoreTurret ) )
{
vehicle.mgTurret SetTargetEntity( vehicle.targetEnt );
vehicle.mgTurret TurretSetGroundAimEntity( vehicle.targetEnt );
}
else
{
vehicle SetOtherEnt( vehicle.targetEnt );
}
thread _cleanupShootingLocationOnDeath( vehicle, effect );
if ( IsDefined( effect ) )
{
PlayFXOnTagForClients( effect, vehicle.targetEnt, "tag_origin", self );
vehicle thread showReticleToEnemies( effect );
}
if ( IsDefined( vehicle.hasAIOption ) && vehicle.hasAIOption )
return;
while ( true )
{
// AI version should manually manage the position of AssaultVeh.TargetEnt
start = self GetViewOrigin();
angles = self GetPlayerAngles();
forward = AnglesToForward( angles );
end = start + ( forward * 8000 );
traceResult = BulletTrace( start, end, false, vehicle );
vehicle.targetEnt.origin = traceResult[ "position" ];
waitframe();
}
}
showReticleToEnemies( effect )
{
self endon ("death");
self endon ( "end_remote" );
if ( !level.hardcoreMode )
{
foreach ( player in level.players )
{
if ( self.owner isEnemy( player ) )
{
waitframe();
PlayFXOnTagForClients( effect, self.targetEnt, "tag_origin", player );
}
}
}
}
_cleanupShootingLocationOnDeath( vehicle, effect )
{
vehicle waittill_any( "death", "stopShootLocationUpdate" );
if ( IsDefined( vehicle.targetEnt ) )
{
targetEnt = vehicle.targetEnt;
if ( IsDefined( effect ) )
StopFXOnTag( effect, targetEnt, "tag_origin" );
waitframe();
targetEnt delete();
}
}
playerHandleExhaustFx( vehicle, effectRef, tag, playerEndonString ) // self == player
{
vehicle endon( "death" );
if ( IsDefined( playerEndonString ) )
self endon( playerEndonString );
PlayFXOnTag( getfx( effectRef ), vehicle, tag );
self thread playerDeleteExhaustFxOnVehicleDeath( vehicle, effectRef, tag );
if ( !vehicle.hasCloak )
return;
while ( true )
{
self waittill( "Cloak" );
StopFXOnTag( getfx( effectRef ), vehicle, tag );
waitframe();
PlayFXOnTagForClients( getfx( effectRef ), vehicle, tag, self );
self waittill( "UnCloak" );
StopFXOnTag( getfx( effectRef ), vehicle, tag );
waitframe();
PlayFXOnTag( getfx( effectRef ), vehicle, tag );
}
}
playerDeleteExhaustFxOnVehicleDeath( vehicle, effectRef, tag ) // self == player
{
vehicle waittill( "death" );
KillFXOnTag( getfx( effectRef ), vehicle, tag );
}
setDroneVisionAndLightSetPerMap( delay, vehicle ) // self == player
{
self endon( "disconnect" );
vehicle endon( "death" );
wait( delay );
if ( IsDefined( level.droneVisionSet ) )
{
self SetClientTriggerVisionSet( level.droneVisionSet, 0 );
}
if ( IsDefined( level.droneLightSet ) )
{
self LightSetForPlayer( level.droneLightSet );
}
}
removeDroneVisionAndLightSetPerMap( delay ) // self == player
{
self SetClientTriggerVisionSet( "", delay );
self LightSetForPlayer( "" );
}
playerWatchForDroneEMP( vehicle )
{
level endon( "game_ended" );
vehicle endon( "death" );
self endon( "assaultDroneHunterKiller" );
vehicle waittill( "emp_damage" );
vehicle notify( "death" );
}