2024-12-11 11:28:08 +01:00

1112 lines
29 KiB
Plaintext

#include maps\mp\_utility;
#include maps\mp\gametypes\_hud_util;
#include common_scripts\utility;
#include maps\mp\gametypes\_hostmigration;
init()
{
level.radarViewTime = 23; // time radar remains active
level.uavBlockTime = 23; // this only seems to be used for the FFA version.
// level.killStreakFuncs[ "uav" ] = ::tryUseUAV;
// level.killStreakFuncs[ "uav_support" ] = ::tryUseUAV;
// level.killStreakFuncs[ "counter_uav" ] = ::tryUseUAV;
// level.killstreakFuncs[ "directional_uav" ] = ::tryUseUAV;
level.killstreakFuncs[ "uav_3dping" ] = ::tryUse3DPing;
level.uavSettings = [];
// level.uavSettings[ "uav" ] = SpawnStruct();
// level.uavSettings[ "uav" ].timeOut = level.radarViewTime;
// level.uavSettings[ "uav" ].health = 999999; // keep it from dying anywhere in code
// level.uavSettings[ "uav" ].maxHealth = 1000; // this is what we check against for death
// level.uavSettings[ "uav" ].streakName = "uav";
// level.uavSettings[ "uav" ].modelBase = "vehicle_uav_static_mp";
// level.uavSettings[ "uav" ].fxId_explode = LoadFX( "fx/explosions/uav_advanced_death" );
// level.uavSettings[ "uav" ].fxId_leave = LoadFX( "fx/fire/jet_engine_ac130" );
// level.uavSettings[ "uav" ].fx_leave_tag = "tag_origin";
// level.uavSettings[ "uav" ].fxId_contrail = undefined;
// level.uavSettings[ "uav" ].fx_contrail_tag = undefined;
// level.uavSettings[ "uav" ].sound_explode = "ball_drone_explode"; // TODO: get sound
// level.uavSettings[ "uav" ].teamSplash = undefined;
// level.uavSettings[ "uav" ].calloutDestroyed = "callout_destroyed_uav";
// level.uavSettings[ "uav" ].addFunc = ::addActiveUAV;
// level.uavSettings[ "uav" ].removeFunc = ::removeActiveUAV;
//
// level.uavSettings[ "uav_support" ] = SpawnStruct();
// level.uavSettings[ "uav_support" ].timeOut = level.radarViewTime;
// level.uavSettings[ "uav_support" ].health = 999999; // keep it from dying anywhere in code
// level.uavSettings[ "uav_support" ].maxHealth = 1000; // this is what we check against for death
// level.uavSettings[ "uav_support" ].streakName = "uav_support";
// level.uavSettings[ "uav_support" ].modelBase = "vehicle_uav_static_mp";
// level.uavSettings[ "uav_support" ].fxId_explode = LoadFX( "fx/explosions/uav_advanced_death" );
// level.uavSettings[ "uav_support" ].fxId_leave = LoadFX( "fx/fire/jet_engine_ac130" );
// level.uavSettings[ "uav_support" ].fx_leave_tag = "tag_origin";
// level.uavSettings[ "uav_support" ].fxId_contrail = undefined;
// level.uavSettings[ "uav_support" ].fx_contrail_tag = undefined;
// level.uavSettings[ "uav_support" ].sound_explode = "ball_drone_explode"; // TODO: get sound
// level.uavSettings[ "uav_support" ].teamSplash = undefined;
// level.uavSettings[ "uav_support" ].calloutDestroyed = "callout_destroyed_uav";
// level.uavSettings[ "uav_support" ].addFunc = ::addActiveUAV;
// level.uavSettings[ "uav_support" ].removeFunc = ::removeActiveUAV;
//
// level.uavSettings[ "counter_uav" ] = SpawnStruct();
// level.uavSettings[ "counter_uav" ].timeOut = level.uavBlockTime;
// level.uavSettings[ "counter_uav" ].health = 999999; // keep it from dying anywhere in code
// level.uavSettings[ "counter_uav" ].maxHealth = 1000; // this is what we check against for death
// level.uavSettings[ "counter_uav" ].streakName = "counter_uav";
// level.uavSettings[ "counter_uav" ].modelBase = "vehicle_uav_static_mp";
// level.uavSettings[ "counter_uav" ].fxId_explode = LoadFX( "fx/explosions/uav_advanced_death" );
// level.uavSettings[ "counter_uav" ].fxId_leave = LoadFX( "fx/fire/jet_engine_ac130" );
// level.uavSettings[ "counter_uav" ].fx_leave_tag = "tag_origin";
// level.uavSettings[ "counter_uav" ].fxId_contrail = undefined;
// level.uavSettings[ "counter_uav" ].fx_contrail_tag = undefined;
// level.uavSettings[ "counter_uav" ].sound_explode = "ball_drone_explode"; // TODO: get sound
// level.uavSettings[ "counter_uav" ].teamSplash = undefined;
// level.uavSettings[ "counter_uav" ].calloutDestroyed = "callout_destroyed_counter_uav";
// level.uavSettings[ "counter_uav" ].addFunc = ::addActiveCounterUAV;
// level.uavSettings[ "counter_uav" ].removeFunc = ::removeActiveCounterUAV;
//
// level.uavSettings[ "directional_uav" ] = SpawnStruct();
// level.uavSettings[ "directional_uav" ].timeOut = level.radarViewTime;
// level.uavSettings[ "directional_uav" ].health = 999999; // keep it from dying anywhere in code
// level.uavSettings[ "directional_uav" ].maxHealth = 2000; // this is what we check against for death
// level.uavSettings[ "directional_uav" ].streakName = "directional_uav";
// level.uavSettings[ "directional_uav" ].modelBase = "vehicle_phantom_ray";
// level.uavSettings[ "directional_uav" ].fxId_explode = LoadFX( "fx/explosions/uav_advanced_death" );
// level.uavSettings[ "directional_uav" ].fxId_leave = LoadFX( "fx/fire/jet_engine_ac130" );
// level.uavSettings[ "directional_uav" ].fx_leave_tag = "tag_origin";
// level.uavSettings[ "directional_uav" ].fxId_contrail = LoadFX( "fx/smoke/advanced_uav_contrail" );
// level.uavSettings[ "directional_uav" ].fx_contrail_tag = "tag_jet_trail";
// level.uavSettings[ "directional_uav" ].sound_explode = "ball_drone_explode"; // TODO: get sound
// level.uavSettings[ "directional_uav" ].teamSplash = "used_directional_uav";
// level.uavSettings[ "directional_uav" ].calloutDestroyed = "callout_destroyed_uav";
// level.uavSettings[ "directional_uav" ].addFunc = ::addActiveUAV;
// level.uavSettings[ "directional_uav" ].removeFunc = ::removeActiveUAV;
level.uavSettings[ "uav_3dping" ] = SpawnStruct();
level.uavSettings[ "uav_3dping" ].timeOut = 63;
level.uavSettings[ "uav_3dping" ].streakName = "uav_3dping";
level.uavSettings[ "uav_3dping" ].highlightFadeTime = 1.5; // time it takes to fade out the hightlight
level.uavSettings[ "uav_3dping" ].pingTime = 10.0; // time between pings
level.uavSettings[ "uav_3dping" ].fxId_ping = LoadFX( "vfx/gameplay/mp/killstreaks/vfx_3d_world_ping" );
level.uavSettings[ "uav_3dping" ].sound_ping_plr = "oracle_radar_pulse_plr";
level.uavSettings[ "uav_3dping" ].sound_ping_npc = "oracle_radar_pulse_npc";
level.uavSettings[ "uav_3dping" ].voTimeOut = "oracle_gone";
level.uavSettings[ "uav_3dping" ].teamSplash = "used_uav_3dping";
minimapOrigins = GetEntArray( "minimap_corner", "targetname" );
if ( miniMapOrigins.size )
uavOrigin = maps\mp\gametypes\_spawnlogic::findBoxCenter( miniMapOrigins[0].origin, miniMapOrigins[1].origin );
else
uavOrigin = (0,0,0);
level.UAVRig = Spawn( "script_model", uavOrigin );
//level.UAVRig SetModel( "c130_zoomrig" );
level.UAVRig.angles = (0,115,0);
level.UAVRig Hide();
// used for debug printing
level.UAVRig.targetname = "uavrig_script_model";
level.UAVRig thread rotateUAVRig();
if ( level.multiTeamBased )
{
for( i = 0; i < level.teamNameList.size; i++ )
{
level.radarMode[level.teamNameList[i]] = "normal_radar";
level.activeUAVs[level.teamNameList[i]] = 0;
level.activeCounterUAVs[level.teamNameList[i]] = 0;
level.uavModels[level.teamNameList[i]] = [];
}
}
else if ( level.teamBased )
{
level.radarMode["allies"] = "normal_radar";
level.radarMode["axis"] = "normal_radar";
level.activeUAVs["allies"] = 0;
level.activeUAVs["axis"] = 0;
level.activeCounterUAVs["allies"] = 0;
level.activeCounterUAVs["axis"] = 0;
level.uavModels["allies"] = [];
level.uavModels["axis"] = [];
}
else
{
level.radarMode = [];
level.activeUAVs = [];
level.activeCounterUAVs = [];
level.uavModels = [];
level thread onPlayerConnect();
}
level thread UAVTracker();
/#
SetDevDvarIfUninitialized( "scr_uav_timeout", level.radarViewTime );
SetDevDvarIfUninitialized( "scr_uav_3dping_timeout", level.uavSettings[ "uav_3dping" ].timeOut );
SetDevDvarIfUninitialized( "scr_uav_3dping_pingTime", level.uavSettings[ "uav_3dping" ].pingTime );
SetDevDvarIfUninitialized( "scr_uav_3dping_highlightFadeTime", level.uavSettings[ "uav_3dping" ].highlightFadeTime );
#/
}
onPlayerConnect()
{
while( true )
{
level waittill( "connected", player );
level.activeUAVs[ player.guid ] = 0;
level.activeUAVs[ player.guid + "_radarStrength" ] = 0;
level.activeCounterUAVs[ player.guid ] = 0;
level.radarMode[ player.guid ] = "normal_radar";
}
}
rotateUAVRig( rotateTime, endonMsg )
{
if( IsDefined( endonMsg ) )
self endon( endonMsg );
if( !IsDefined( rotateTime ) )
rotateTime = 60;
while( true )
{
self RotateYaw( -360, rotateTime );
wait ( rotateTime );
}
}
tryUseUAV( lifeId, streakName )
{
return useUAV( streakName );
}
tryUse3DPing( lifeId, streakName ) // self == player
{
uavType = "uav_3dping";
self thread watch3DPing( uavType );
self thread watch3DPingTimeout( uavType );
level thread teamPlayerCardSplash( level.uavSettings[ uavType ].teamSplash, self );
return true;
}
useUAV( uavType ) // self == player
{
self maps\mp\_matchdata::logKillstreakEvent( uavType, self.origin );
team = self.pers[ "team" ];
useTime = level.uavSettings[ uavType ].timeOut;
/#
useTime = GetDvarInt( "scr_uav_timeout", level.uavSettings[ uavType ].timeOut );
#/
level thread launchUAV( self, useTime, uavType );
switch( uavType )
{
case "counter_uav":
self notify( "used_counter_uav" );
break;
case "directional_uav":
self.radarShowEnemyDirection = true;
if( level.teambased )
{
foreach( player in level.players )
{
if( player.pers["team"] == team )
{
player.radarShowEnemyDirection = true;
}
}
}
level thread teamPlayerCardSplash( level.uavSettings[ uavType ].teamSplash, self, team );
self notify( "used_directional_uav" );
break;
default:
self notify( "used_uav" );
break;
}
return true;
}
launchUAV( owner, duration, uavType ) // self == level
{
team = owner.team;
UAVModel = Spawn( "script_model", level.UAVRig GetTagOrigin( "tag_origin" ) );
/#
if( GetDvarInt( "scr_debuguav" ) )
{
UAVModel thread debugLocation();
UAVModel thread debugTrace();
}
#/
UAVModel SetModel( level.uavSettings[ uavType ].modelBase );
UAVModel.team = team;
UAVModel.owner = owner;
UAVModel.timeToAdd = 0;
UAVModel.uavType = uavType;
UAVModel.health = level.uavSettings[ uavType ].health;
UAVModel.maxHealth = level.uavSettings[ uavType ].maxHealth;
if( uavType == "directional_uav" )
UAVModel thread spawnFxDelay( level.uavSettings[ uavType ].fxId_contrail, level.uavSettings[ uavType ].fx_contrail_tag );
UAVModel addUAVModel();
UAVModel thread damageTracker();
UAVModel thread handleIncomingStinger();
UAVModel thread removeUAVModelOnDeath();
zOffset = RandomIntRange( 3000, 5000 );
// we need to make sure the uav doesn't go higher than 8100 units because bullets die at 8192
if( IsDefined( level.spawnpoints ) )
spawns = level.spawnPoints;
else
spawns = level.startSpawnPoints;
lowestSpawn = spawns[0];
foreach( spawn in spawns )
{
if ( spawn.origin[2] < lowestSpawn.origin[2] )
lowestSpawn = spawn;
}
lowestZ = lowestSpawn.origin[2];
UAVRigZ = level.UAVRig.origin[2];
if( lowestZ < 0 )
{
UAVRigZ += lowestZ * -1;
lowestZ = 0;
}
diffZ = UAVRigZ - lowestZ;
AssertEx( diffZ < 8100.0, "The lowest spawn and the UAV node are more than 8100 z units apart, please notify MP Design." );
if( diffZ + zOffset > 8100.0 )
{
zOffset -= ( ( diffZ + zOffset ) - 8100.0 );
}
angle = RandomInt( 360 );
radiusOffset = RandomInt( 2000 ) + 5000;
xOffset = cos( angle ) * radiusOffset;
yOffset = sin( angle ) * radiusOffset;
angleVector = VectorNormalize( (xOffset,yOffset,zOffset) );
angleVector = ( angleVector * RandomIntRange( 6000, 7000 ) );
UAVModel LinkTo( level.UAVRig, "tag_origin", angleVector, (0,angle - 90,0) );
UAVModel thread updateUAVModelVisibility();
UAVModel [[ level.uavSettings[ uavType ].addFunc ]]();
// this adds 5 seconds of time to all active UAV's of the same type.
if( IsDefined( level.activeUAVs[ team ] ) )
{
foreach( uav in level.UAVModels[ team ] )
{
if( uav == UAVModel )
continue;
uav.timeToAdd += 5;
}
}
level notify ( "uav_update" );
UAVModel waittill_notify_or_timeout_hostmigration_pause( "death", duration );
if( UAVModel.damageTaken < UAVModel.maxHealth )
{
UAVModel Unlink();
destPoint = UAVModel.origin + ( AnglesToForward( UAVModel.angles ) * 20000 );
UAVModel MoveTo( destPoint, 60 );
if( IsDefined( level.uavSettings[ uavType ].fxId_leave ) && IsDefined( level.uavSettings[ uavType ].fx_leave_tag ) )
PlayFXOnTag( level.uavSettings[ uavType ].fxId_leave, UAVModel, level.uavSettings[ uavType ].fx_leave_tag );
UAVModel waittill_notify_or_timeout_hostmigration_pause( "death", 3 );
if ( UAVModel.damageTaken < UAVModel.maxHealth )
{
UAVModel notify( "leaving" );
UAVModel.isLeaving = true;
UAVModel MoveTo( destPoint, 4, 4, 0.0 );
}
UAVModel waittill_notify_or_timeout_hostmigration_pause( "death", 4 + UAVModel.timeToAdd );
}
UAVModel [[ level.uavSettings[ uavType ].removeFunc ]]();
UAVModel delete();
UAVModel removeUAVModel();
if( uavType == "directional_uav" )
{
owner.radarShowEnemyDirection = false;
if( level.teambased )
{
foreach( player in level.players )
{
if( player.pers["team"] == team )
{
player.radarShowEnemyDirection = false;
}
}
}
}
level notify ( "uav_update" );
}
updateUAVModelVisibility() // self == uavmodel
{
self endon ( "death" );
while( true )
{
level waittill_either( "joined_team", "uav_update" );
self Hide();
foreach( player in level.players )
{
if( level.teamBased )
{
if( player.team != self.team )
self ShowToPlayer( player );
}
else
{
if( IsDefined( self.owner ) && player == self.owner )
continue;
self ShowToPlayer( player );
}
}
}
}
damageTracker() // self == uavmodel
{
level endon ( "game_ended" );
self SetCanDamage( true );
self.damageTaken = 0; // how much damage has it taken
while( true )
{
self waittill( "damage", damage, attacker, direction_vec, point, meansOfDeath, modelName, tagName, partName, iDFlags, weapon );
if ( !IsPlayer( attacker ) )
{
if ( !IsDefined( self ) )
return;
continue;
}
if ( IsDefined( iDFlags ) && ( iDFlags & level.iDFLAGS_PENETRATION ) )
self.wasDamagedFromBulletPenetration = true;
self.wasDamaged = true;
modifiedDamage = damage;
if( IsPlayer( attacker ) )
{
attacker maps\mp\gametypes\_damagefeedback::updateDamageFeedback( "" );
if( meansOfDeath == "MOD_RIFLE_BULLET" || meansOfDeath == "MOD_PISTOL_BULLET" )
{
if ( attacker _hasPerk( "specialty_armorpiercing" ) )
modifiedDamage += damage * level.armorPiercingMod;
}
}
if( IsDefined( weapon ) )
{
switch( weapon )
{
case "stinger_mp":
case "javelin_mp":
self.largeProjectileDamage = true;
modifiedDamage = self.maxHealth + 1;
break;
case "sam_projectile_mp":
self.largeProjectileDamage = true;
mult = 0.25;
if( self.uavType == "directional_uav" )
mult = 0.15;
modifiedDamage = self.maxHealth * mult; // takes about 2 burst of sam rockets
break;
}
maps\mp\killstreaks\_killstreaks::killstreakHit( attacker, weapon, self );
}
self.damageTaken += modifiedDamage;
/#
if ( IsDefined( self ) && GetDvarInt( "g_debugDamage" ) )
PrintLn( "uav:" + self getEntityNumber() + " health:" + ( self.health - self.damageTaken ) + " attacker:" + attacker.clientid + " inflictor is player:" + IsPlayer( attacker ) + " damage:" + modifiedDamage + " range:" + Distance( attacker.origin, self.origin ) );
#/
if ( self.damageTaken >= self.maxHealth )
{
if ( IsPlayer( attacker ) && ( !IsDefined( self.owner ) || attacker != self.owner ) )
{
thread teamPlayerCardSplash( level.uavSettings[ self.uavType ].calloutDestroyed, attacker );
thread maps\mp\gametypes\_missions::vehicleKilled( self.owner, self, undefined, attacker, damage, meansOfDeath, weapon );
attacker thread maps\mp\gametypes\_rank::giveRankXP( "kill", 50, weapon, meansOfDeath );
attacker notify( "destroyed_killstreak" );
if ( IsDefined( self.UAVRemoteMarkedBy ) && self.UAVRemoteMarkedBy != attacker )
self.UAVRemoteMarkedBy thread maps\mp\killstreaks\_remoteuav::remoteUAV_processTaggedAssist();
}
self Hide();
forward = ( AnglesToRight( self.angles ) * 200 );
PlayFX ( level.uavSettings[ self.uavType ].fxId_explode, self.origin, forward );
self notify( "death" );
return;
}
}
}
UAVTracker() // self == level
{
level endon ( "game_ended" );
while( true )
{
level waittill ( "uav_update" );
if( level.multiTeamBased )
{
for( i = 0; i < level.teamNameList.size; i++ )
{
updateTeamUAVStatus( level.teamNameList[i] );
}
}
else if ( level.teamBased )
{
updateTeamUAVStatus( "allies" );
updateTeamUAVStatus( "axis" );
}
else
{
updatePlayersUAVStatus();
}
}
}
_getRadarStrength( team )
{
activeUAVs = 0;
activeCounterUAVs = 0;
foreach ( uav in level.UAVModels[ team ] )
{
if ( uav.uavType == "counter_uav" )
continue;
if ( uav.uavType == "remote_mortar" )
continue;
activeUAVs++;
}
if( level.multiTeamBased )
{
//count active counter uav's owned by the other team.
foreach( teamName in level.teamNameList )
{
foreach ( uav in level.UAVModels[teamName] )
{
if( teamName == team )
continue;
if ( uav.uavType != "counter_uav" )
continue;
activeCounterUAVs++;
}
}
}
else
{
foreach ( uav in level.UAVModels[level.otherTeam[team] ] )
{
if ( uav.uavType != "counter_uav" )
continue;
activeCounterUAVs++;
}
}
if( activeCounterUAVs > 0 )
radarStrength = -3;
else
radarStrength = activeUAVs;
strengthMin = GetUAVStrengthMin();
strengthMax = GetUAVStrengthMax();
//clamp between min/max
if( radarStrength <= strengthMin )
{
radarStrength = strengthMin;
}
else if( radarStrength >= strengthMax )
{
radarStrength = strengthMax;
}
return radarStrength;
}
updateTeamUAVStatus( team )
{
radarStrength = _getRadarStrength( team );
SetTeamRadarStrength( team, radarStrength );
if ( radarStrength >= GetUAVStrengthLevelNeutral() )
unblockTeamRadar( team );
else
blockTeamRadar( team );
if ( radarStrength <= GetUAVStrengthLevelNeutral() )
{
setTeamRadarWrapper( team, 0 );
updateTeamUAVType( team );
return;
}
if ( radarStrength >= GetUAVStrengthLevelShowEnemyFastSweep() )
level.radarMode[team] = "fast_radar";
else
level.radarMode[team] = "normal_radar";
updateTeamUAVType( team );
setTeamRadarWrapper( team, 1 );
}
//for FFA
updatePlayersUAVStatus()
{
strengthMin = GetUAVStrengthMin();
strengthMax = GetUAVStrengthMax();
strengthDirectional = GetUAVStrengthLevelShowEnemyDirectional();
//allPlayersCounterUAVTotal = 0;
////calculate total counter uavs that currently exists across all players
//foreach ( player in level.players )
//{
// allPlayersCounterUAVTotal += level.activeCounterUAVs[ player.guid ];
//}
foreach ( player in level.players )
{
radarStrength = level.activeUAVs[ player.guid + "_radarStrength" ];
// if there are any counters up that aren't this player's then they are blocked
foreach( enemyPlayer in level.players )
{
if( enemyPlayer == player )
continue;
activeCounterUAVs = level.activeCounterUAVs[ enemyPlayer.guid ];
if( activeCounterUAVs > 0 )
{
radarStrength = -3;
break;
}
}
//clamp between min/max
if( radarStrength <= strengthMin )
{
radarStrength = strengthMin;
}
else if( radarStrength >= strengthMax )
{
radarStrength = strengthMax;
}
player.radarstrength = radarStrength;
if ( radarStrength >= GetUAVStrengthLevelNeutral() )
player.isRadarBlocked = false;
else
player.isRadarBlocked = true;
if ( radarStrength <= GetUAVStrengthLevelNeutral() )
{
player.hasRadar = false;
player.radarShowEnemyDirection = false;
continue;
}
if ( radarStrength >= GetUAVStrengthLevelShowEnemyFastSweep() )
player.radarMode = "fast_radar";
else
player.radarMode = "normal_radar";
//set directional status
player.radarShowEnemyDirection = radarStrength >= strengthDirectional;
player.hasRadar = true;
}
}
blockPlayerUAV()
{
self endon ( "disconnect" );
self notify ( "blockPlayerUAV" );
self endon ( "blockPlayerUAV" );
self.isRadarBlocked = true;
wait ( level.uavBlockTime );
self.isRadarBlocked = false;
//self iPrintLn( &"KILLSTREAKS_WAR_COUNTER_RADAR_EXPIRED" );
}
updateTeamUAVType( team )
{
shouldBeDirectional = _getRadarStrength( team ) >= GetUAVStrengthLevelShowEnemyDirectional();
foreach ( player in level.players )
{
if ( player.team == "spectator" )
continue;
player.radarMode = level.radarMode[player.team];
//use direction based on uav signal strength
if( player.team == team )
{
player.radarShowEnemyDirection = shouldBeDirectional;
}
}
}
usePlayerUAV( doubleUAV, useTime )
{
level endon("game_ended");
self endon("disconnect");
self notify ( "usePlayerUAV" );
self endon ( "usePlayerUAV" );
if ( doubleUAV )
self.radarMode = "fast_radar";
else
self.radarMode = "normal_radar";
self.hasRadar = true;
wait ( useTime );
self.hasRadar = false;
}
setTeamRadarWrapper( team, value )
{
setTeamRadar( team, value );
level notify( "radar_status_change", team );
}
handleIncomingStinger()
{
level endon ( "game_ended" );
self endon ( "death" );
while( true )
{
level waittill ( "stinger_fired", player, missile, lockTarget );
if ( !IsDefined( lockTarget ) || (lockTarget != self) )
continue;
missile thread stingerProximityDetonate( lockTarget, player );
}
}
stingerProximityDetonate( targetEnt, player )
{
self endon ( "death" );
minDist = Distance( self.origin, targetEnt GetPointInBounds( 0, 0, 0 ) );
lastCenter = targetEnt GetPointInBounds( 0, 0, 0 );
while( true )
{
// UAV already destroyed
if ( !IsDefined( targetEnt ) )
center = lastCenter;
else
center = targetEnt GetPointInBounds( 0, 0, 0 );
lastCenter = center;
curDist = Distance( self.origin, center );
if ( curDist < minDist )
minDist = curDist;
if ( curDist > minDist )
{
if ( curDist > 1536 )
return;
RadiusDamage( self.origin, 1536, 600, 600, player, "MOD_EXPLOSIVE", "stinger_mp" );
PlayFX( level.stingerFXid, self.origin );
//self playSound( "remotemissile_explode" );
self Hide();
self notify("deleted");
wait ( 0.05 );
self delete();
player notify( "killstreak_destroyed" );
}
wait ( 0.05 );
}
}
addUAVModel() // self == uavmodel
{
if ( level.teamBased )
level.UAVModels[ self.team ][ level.UAVModels[ self.team ].size ] = self;
else
level.UAVModels[ self.owner.guid + "_" + GetTime() ] = self;
}
removeUAVModelOnDeath() // self == uavmodel
{
self waittill( "death" );
if( IsDefined( self.UAVRig ) )
self.UAVRig delete();
if( IsDefined( self ) )
self delete();
removeUAVModel();
}
removeUAVModel() // self == uavmodel
{
UAVModels = [];
if ( level.teamBased )
{
team = self.team;
foreach ( uavModel in level.UAVModels[team] )
{
if ( !IsDefined( uavModel ) )
continue;
UAVModels[UAVModels.size] = uavModel;
}
level.UAVModels[team] = UAVModels;
}
else
{
foreach ( uavModel in level.UAVModels )
{
if ( !IsDefined( uavModel ) )
continue;
UAVModels[UAVModels.size] = uavModel;
}
level.UAVModels = UAVModels;
}
}
addActiveUAV() // self == uav model
{
if ( level.teamBased )
{
level.activeUAVs[self.team]++;
}
else
{
level.activeUAVs[ self.owner.guid ]++;
level.activeUAVs[ self.owner.guid + "_radarStrength" ]++;
}
}
addActiveCounterUAV()
{
if ( level.teamBased )
level.activeCounterUAVs[self.team]++;
else
level.activeCounterUAVs[self.owner.guid]++;
}
removeActiveUAV() // self == uav model
{
if ( level.teamBased )
{
level.activeUAVs[self.team]--;
}
else if ( IsDefined( self.owner ) )
{
level.activeUAVs[ self.owner.guid ]--;
level.activeUAVs[ self.owner.guid + "_radarStrength" ]--;
}
}
removeActiveCounterUAV()
{
if ( level.teamBased )
{
level.activeCounterUAVs[self.team]--;
}
else if ( IsDefined( self.owner ) )
{
level.activeCounterUAVs[self.owner.guid]--;
}
}
spawnFXDelay( fxID, tag )
{
self endon( "death" );
level endon( "game_ended" );
wait( 0.5 );
PlayFXOnTag( fxID, self, tag );
}
watch3DPing( uavType, uavEnt ) // self == player
{
if( IsDefined( uavEnt ) )
uavEnt endon( "death" );
self endon( "leave" );
self endon( "killstreak_disowned" );
level endon( "game_ended" );
uavConfig = level.uavSettings[ uavType ];
// every N seconds do a ping of the world and show enemies in red
pingTime = uavConfig.pingTime;
if (level.teamBased)
{
level.activeUAVs[ self.team ]++;
}
else
{
level.activeUAVs[ self.guid ]++;
}
while( true )
{
//PrintLn( "watch3DPing: GetTime() " + GetTime() + " PingTime " + pingTime );
PlayFX( uavConfig.fxId_ping, self.origin );
self PlayLocalSound( uavConfig.sound_ping_plr );
playSoundAtPos( self.origin + ( 0, 0, 5 ), uavConfig.sound_ping_npc );
// highlight all enemies in the world that can't be seen
// 2013-08-24 wallace: in the future, instead of doing two nested for-loops, probably could sort the participants into friendly and enemy lists
// then draw the enemies for friendlies
foreach( enemy in level.participants )
{
if( !isReallyAlive( enemy ) )
continue;
if ( !(self isEnemy( enemy ) ) )
continue;
if( enemy _hasPerk( "specialty_noplayertarget" ) )
continue;
enemy maps\mp\gametypes\_damagefeedback::hudIconType( "oracle" );
foreach( friendly in level.participants )
{
if( !isReallyAlive( friendly ) )
continue;
if ( self isEnemy( friendly ) )
continue;
if( IsAI( friendly ) )
friendly ai_3d_sighting_model( enemy );
else
{
// do outline for this enemy for this friendly
// we don't use the team based version of this because we're calling it on every friendly anways.
// It was causing a bug where the outline would continue to be drawn after a friendly owner of the oracle disconnected
id = outlineEnableForPlayer( enemy, "orange", friendly, false, "killstreak" );
fadeTime = uavConfig.highlightFadeTime;
/#
fadeTime = GetDvarFloat( "scr_" + uavType + "_highlightFadeTime" );
// host migration wipes out this dvar for some reason and causes the loop to continue when it shouldn't
if( fadeTime < 1 )
fadeTime = uavConfig.highlightFadeTime;
#/
friendly thread watchHighlightFadeTime( id, enemy, fadeTime, uavEnt );
}
}
}
/#
pingTime = GetDvarFloat( "scr_" + uavType + "_pingTime" );
// host migration wipes out this dvar for some reason and causes the loop to continue when it shouldn't
if( pingTime < 1 )
pingTime = uavConfig.pingTime;
#/
waitLongDurationWithHostMigrationPause( pingTime );
}
}
watch3DPingTimeout( uavType ) // self == player
{
self endon( "killstreak_disowned" );
level endon( "game_ended" );
config = level.uavSettings[ uavType ];
useTime = config.timeOut;
/#
useTime = GetDvarInt( "scr_" + uavType + "_timeout", useTime );
#/
// save this index early, in case of player disconnect
index = self.guid;
if (level.teamBased)
{
index = self.team;
}
self thread watch_3dping_KillStreakDisowned( index );
waitLongDurationWithHostMigrationPause( useTime );
self leaderDialogOnPlayer( config.voTimeOut );
self notify( "leave" );
cleanup3dping( index );
}
watch_3dping_KillStreakDisowned( index ) // self == player
{
self endon( "leave" );
self waittill( "killstreak_disowned" );
cleanup3dping( index );
}
cleanup3dping( index )
{
level.activeUAVs[ index ]--;
if ( level.activeUAVs[ index ] < 0 )
level.activeUAVs[ index ] = 0;
}
watchHighlightFadeTime( id, ent, time, uavEnt ) // self == player
{
if( IsDefined( uavEnt ) )
uavEnt endon( "death" );
self endon( "disconnect" );
level endon( "game_ended" );
self waittill_any_timeout_no_endon_death( time, "leave" );
if( IsDefined( ent ) )
outlineDisable( id, ent );
}
/#
debugLocation()
{
self endon( "death" );
while( true )
{
Print3d( self.origin, "UAV", ( 1, 0, 0 ) );
Print3d( self.origin, "UAV origin: " + self.origin[0] + ", " + self.origin[1] + ", " + self.origin[2], ( 1, 0, 0 ) );
Print3d( level.UAVRig.origin, "UAV Rig", ( 1, 0, 0 ) );
Print3d( level.UAVRig.origin, "UAV Rig origin: " + level.UAVRig.origin[0] + ", " + level.UAVRig.origin[1] + ", " + level.UAVRig.origin[2], ( 1, 0, 0 ) );
Print3d( level.UAVRig.origin - ( 0, 0, 50), "Distance: " + Distance( level.UAVRig.origin, self.origin ), ( 1, 0, 0 ) );
Line( level.UAVRig.origin, self.origin, ( 0, 0, 1 ) );
anglesForward = AnglesToForward( level.players[0].angles );
scalar = (anglesForward[0] * 200, anglesForward[1] * 200, anglesForward[2] );
Print3d( level.players[0].origin + scalar, "Distance: " + Distance( level.players[0].origin, self.origin ), ( 1, 0, 0 ) );
wait( 0.05 );
}
}
debugTrace()
{
self endon( "death" );
while( true )
{
result = BulletTrace( level.players[0].origin, self.origin, false, undefined );
if( IsDefined( result ) && IsDefined( result[ "surfacetype" ] ) )
{
PrintLn( "UAV debugTrace: " + result[ "surfacetype" ] );
}
wait( 1.0 );
}
}
#/