484 lines
11 KiB
Plaintext
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" );
|
|
} |