boiii-scripts/shared/weapons/_hacker_tool.gsc
2023-04-13 17:30:38 +02:00

1152 lines
39 KiB
Plaintext

#using scripts\codescripts\struct;
#using scripts\shared\callbacks_shared;
#using scripts\shared\clientfield_shared;
#using scripts\shared\killstreaks_shared;
#using scripts\shared\scoreevents_shared;
#using scripts\shared\system_shared;
#using scripts\shared\util_shared;
#using scripts\shared\weapons\_heatseekingmissile;
#using scripts\shared\weapons\_weaponobjects;
#precache( "triggerstring", "MP_GENERIC_HACKING" );
#namespace hacker_tool;
function init_shared()
{
level.weaponHackerTool = GetWeapon( "pda_hack" );
level.hackerToolLostSightLimitMs = 1000;
level.hackerToolLockOnRadius = 25;
level.hackerToolLockOnFOV = 65;
level.hackerToolHackTimeMs = 0.4;
// equipment
level.equipmentHackerToolRadius = 20;
level.equipmentHackerToolTimeMs = 100;
// care packages
level.carePackageHackerToolRadius = 60;
level.carePackageHackerToolTimeMs = GetGametypeSetting("crateCaptureTime") * 500;
level.carePackageFriendlyHackerToolTimeMs = GetGametypeSetting("crateCaptureTime") * 2000 ;
level.carePackageOwnerHackerToolTimeMs = 250;
// vehicles
level.vehicleHackerToolRadius = 80;
level.vehicleHackerToolTimeMs = 5000;
clientfield::register( "toplayer", "hacker_tool", 1, 2, "int" );
//thread tunables();
callback::on_spawned( &on_player_spawned );
}
//******************************************************************
// *
// *
//******************************************************************
function on_player_spawned()
{
self endon( "disconnect" );
self clearHackerTarget( undefined, false, true);
self thread watchHackerToolUse();
self thread watchHackerToolFired();
}
//******************************************************************
// *
// *
//******************************************************************
function clearHackerTarget( weapon, successfulHack, spawned ) // self == player
{
self notify( "stop_lockon_sound" );
self notify( "stop_locked_sound" );
self notify( "clearHackerTarget" );
self.stingerlocksound = undefined;
self StopRumble( "stinger_lock_rumble" );
self.hackerToolLockStartTime = 0;
self.hackerToolLockStarted = false;
self.hackerToolLockFinalized = false;
self.hackerToolLockTimeElapsed = 0.0;
if ( isdefined( weapon ) )
{
if ( weapon.isHackToolWeapon )
{
self SetWeaponHackPercent( weapon, 0.0 );
}
if( isdefined( self.hackerToolTarget ))
{
heatseekingmissile::setFriendlyFlags( weapon, self.hackerToolTarget );
}
}
if ( successfulHack == false )
{
if ( spawned == false )
{
if( isdefined( self.hackerToolTarget ) )
self playsoundtoplayer( "evt_hacker_hack_lost", self ); // hacking failed
}
self clientfield::set_to_player( "hacker_tool", 0 );
self stopHackerToolSoundLoop();
}
if( isdefined( self.hackerToolTarget ))
{
heatseekingmissile::TargetingHacking( self.hackerToolTarget, false );
}
self.hackerToolTarget = undefined;
self WeaponLockFree();
self WeaponLockTargetTooClose( false );
self WeaponLockNoClearance( false );
self StopLocalSound( game["locking_on_sound"] );
self StopLocalSound( game["locked_on_sound"] );
self heatseekingmissile::DestroyLockOnCanceledMessage();
}
//******************************************************************
// *
// *
//******************************************************************
function watchHackerToolFired() // self == player
{
self endon( "disconnect" );
self endon ( "death" );
self endon ("killHackerMonitor");
while ( true )
{
self waittill( "hacker_tool_fired", hackerToolTarget, weapon );
if( isdefined( hackerToolTarget ))
{
if ( isEntityHackableCarePackage( hackerToolTarget ) )
{
scoreevents::giveCrateCaptureMedal( hackerToolTarget, self );
hackerToolTarget notify( "captured", self, true );
if ( isdefined( hackerToolTarget.owner ) && isplayer( hackerToolTarget.owner ) && hackerToolTarget.owner.team != self.team && isdefined( level.play_killstreak_hacked_dialog ) )
{
hackerToolTarget.owner [[level.play_killstreak_hacked_dialog]]( hackerToolTarget.killstreakType,hackerToolTarget.killstreakId, self );
}
}
else if ( isEntityHackableWeaponObject( hackerToolTarget ) && isdefined( hackerToolTarget.hackerTrigger ))
{
// turrets and weapon objects
hackerToolTarget.hackerTrigger notify( "trigger", self, true );
hackerToolTarget.previouslyHacked = true;
self.throwinggrenade = false;
}
else if ( isdefined( hackerToolTarget.killstreak_hackedCallback ) && ( !isdefined( hackerToolTarget.killstreakTimedOut ) || hackerToolTarget.killstreakTimedOut == false ) )
{
if ( hackerToolTarget.killstreak_hackedProtection == false )
{
if ( isdefined( hackerToolTarget.owner ) && isplayer( hackerToolTarget.owner ) )
{
// Hack complete
if ( isdefined( level.play_killstreak_hacked_dialog ) )
{
hackerToolTarget.owner [[level.play_killstreak_hacked_dialog]]( hackerToolTarget.killstreakType,hackerToolTarget.killstreakId, self );
}
}
self playsoundtoplayer( "evt_hacker_fw_success", self ); // hacked firewall successfully
hackerToolTarget notify( "killstreak_hacked", self );
hackerToolTarget.previouslyHacked = true;
hackerToolTarget [[ hackerToolTarget.killstreak_hackedCallback ]]( self );
if ( self util::has_blind_eye_perk_purchased_and_equipped() || self util::has_hacker_perk_purchased_and_equipped() )
{
self AddPlayerStat( "hack_streak_with_blindeye_or_engineer", 1 );
}
}
else
{
if ( isdefined( hackerToolTarget.owner ) && isplayer( hackerToolTarget.owner ) )
{
// Breach complete
if ( isdefined( level.play_killstreak_firewall_hacked_dialog ) )
{
self.hackerToolTarget.owner [[level.play_killstreak_firewall_hacked_dialog]]( self.hackerToolTarget.killstreakType, self.hackerToolTarget.killstreakId );
}
}
self playsoundtoplayer( "evt_hacker_ks_success", self ); // hacked killstreak successfully
scoreevents::processscoreevent( "hacked_killstreak_protection", self, hackerToolTarget, level.weaponHackerTool );
}
hackerToolTarget.killstreak_hackedProtection = false;
}
else
{
if ( isdefined( hackerToolTarget.classname ) && hackerToolTarget.classname == "grenade" )
{
damage = 1;
}
else if ( isdefined( hackerToolTarget.hackerToolDamage ))
{
damage = hackerToolTarget.hackerToolDamage;
}
else if ( isdefined( hackerToolTarget.maxhealth ))
{
damage = hackerToolTarget.maxhealth + 1;
}
else
{
damage = 999999;
}
if ( isdefined( hackerToolTarget.numFlares ) && hackerToolTarget.numFlares > 0 )
{
damage = 1;
hackerToolTarget.numFlares--;
hackerToolTarget heatseekingmissile::MissileTarget_PlayFlareFx();
}
hackerToolTarget DoDamage( damage, self.origin, self, self, 0, "MOD_UNKNOWN", 0, weapon );
}
if ( self util::is_item_purchased( "pda_hack" ) )
{
self AddPlayerStat( "hack_enemy_target", 1 );
}
self AddWeaponStat( weapon, "used", 1 );
}
clearHackerTarget( weapon, true, false );
self forceoffhandend();
if ( GetDvarint( "player_sustainAmmo" ) == 0 )
{
clip_ammo = self GetWeaponAmmoClip( weapon );
clip_ammo--;
/#assert( clip_ammo >= 0);#/
self setWeaponAmmoClip( weapon, clip_ammo );
}
self killstreaks::switch_to_last_non_killstreak_weapon(); // won't switch weapons while the shoulder button is held
}
}
//******************************************************************
// *
// *
//******************************************************************
function watchHackerToolUse() // self == player
{
self endon( "disconnect" );
self endon ( "death" );
for (;;)
{
self waittill ( "grenade_pullback", weapon );
if ( weapon.rootWeapon == level.weaponHackerTool )
{
{wait(.05);};
currentOffhand = self getCurrentOffhand();
if ( self isUsingOffhand() && ( currentOffhand.rootWeapon == level.weaponHackerTool ) )
{
self thread hackerToolTargetLoop( weapon );
self thread watchHackerToolEnd( weapon );
self thread watchForGrenadeFire( weapon );
self thread watchHackerToolInterrupt(weapon );
}
}
}
}
//******************************************************************
// *
// *
//******************************************************************
function watchHackerToolInterrupt( weapon ) // self == player
{
self endon( "disconnect" );
self endon( "hacker_tool_fired" );
self endon( "death" );
self endon( "weapon_change" );
self endon( "grenade_fire" );
while( true )
{
level waittill( "use_interrupt", interruptTarget );
if( self.hackerToolTarget == interruptTarget )
{
clearHackerTarget( weapon, false, false );
}
{wait(.05);};
}
}
function watchHackerToolEnd( weapon ) // self == player
{
self endon( "disconnect" );
self endon( "hacker_tool_fired" );
msg = self util::waittill_any_return( "weapon_change", "death", "hacker_tool_fired", "disconnect" );
clearHackerTarget( weapon, false, false );
self clientfield::set_to_player( "hacker_tool", 0 );
self stopHackerToolSoundLoop();
}
function watchForGrenadeFire( weapon ) // self == player
{
self endon( "disconnect" );
self endon( "hacker_tool_fired" );
self endon( "weapon_change" );
self endon( "death" );
while( true )
{
//This notify will be called when a weapon object gets hacked to reboot the watcher. We don't want to give the player ammo for this.
self waittill( "grenade_fire", grenade_instance, grenade_weapon, respawnFromHack );
if( isDefined( respawnFromHack ) && respawnFromHack )
continue;
clearHackerTarget( grenade_weapon, false, false );
clip_ammo = self GetWeaponAmmoClip( grenade_weapon );
clip_max_ammo = grenade_weapon.clipSize;
if( clip_ammo < clip_max_ammo )
{
clip_ammo++;
}
self setWeaponAmmoClip( grenade_weapon, clip_ammo );
break;
}
}
function playHackerToolSoundLoop() // self == player
{
if ( !isdefined( self.hacker_sound_ent ) || ( isdefined( self.hacker_alreadyhacked ) && self.hacker_alreadyhacked == true ) )
{
self playloopsound ("evt_hacker_device_loop");
self.hacker_sound_ent = true;
self.hacker_alreadyhacked = false;
}
}
function stopHackerToolSoundLoop() // self == player
{
self StopLoopSound( 0.5 );
self.hacker_sound_ent = undefined;
self.hacker_alreadyhacked = undefined;
}
function hackerToolTargetLoop( weapon ) // self == player
{
self endon( "disconnect" );
self endon( "death" );
self endon( "weapon_change" );
self endon( "grenade_fire" );
self clientfield::set_to_player( "hacker_tool", 1 );
self playHackerToolSoundLoop();
while ( true )
{
{wait(.05);};
{wait(.05);};
if ( self.hackerToolLockFinalized )
{
if ( !self isValidHackerToolTarget( self.hackerToolTarget, weapon, false ))
{
self clearHackerTarget( weapon, false, false );
continue;
}
passed = self hackerSoftSightTest( weapon );
if ( !passed )
{
continue;
}
self clientfield::set_to_player( "hacker_tool", 0 );
self stopHackerToolSoundLoop();
heatseekingmissile::TargetingHacking( self.hackerToolTarget, false);
heatseekingmissile::setFriendlyFlags( weapon, self.hackerToolTarget );
thread heatseekingmissile::LoopLocalLockSound( game["locked_on_sound"], 0.75 );
self notify( "hacker_tool_fired", self.hackerToolTarget, weapon );
return;
}
if ( self.hackerToolLockStarted )
{
if ( !self isValidHackerToolTarget( self.hackerToolTarget, weapon, false ) )
{
self clearHackerTarget( weapon, false, false );
continue;
}
lockOnTime = self getLockOnTime( self.hackerToolTarget, weapon );
if ( lockOnTime == 0 )
{
self clearHackerTarget( weapon, false, false );
continue;
}
if ( self.hackerToolLockTimeElapsed == 0.0 )
{
self PlayLocalSound ( "evt_hacker_hacking" );
if ( isdefined( self.hackerToolTarget.owner ) && isplayer( self.hackerToolTarget.owner ) )
{
if ( isdefined( self.hackerToolTarget.killstreak_hackedCallback ) && ( !isdefined( self.hackerToolTarget.killstreakTimedOut ) || self.hackerToolTarget.killstreakTimedOut == false ) )
{
if ( self.hackerToolTarget.killstreak_hackedProtection == false )
{
// hacking started, regular hack
//self.hackerToolTarget.owner
if ( isdefined( level.play_killstreak_being_hacked_dialog ) )
{
self.hackerToolTarget.owner [[level.play_killstreak_being_hacked_dialog]]( self.hackerToolTarget.killstreakType, self.hackerToolTarget.killstreakId );
}
}
else
{
// breaching firewall started
if ( isdefined( level.play_killstreak_firewall_being_hacked_dialog ) )
{
self.hackerToolTarget.owner [[level.play_killstreak_firewall_being_hacked_dialog]]( self.hackerToolTarget.killstreakType, self.hackerToolTarget.killstreakId );
}
}
}
}
}
self WeaponLockStart( self.hackerToolTarget );
self playHackerToolSoundLoop();
if ( isdefined( self.hackerToolTarget.killstreak_hackedProtection ) && self.hackerToolTarget.killstreak_hackedProtection == true )
{
self clientfield::set_to_player( "hacker_tool", 3 );
}
else
{
self clientfield::set_to_player( "hacker_tool", 2 );
}
heatseekingmissile::TargetingHacking( self.hackerToolTarget, true );
heatseekingmissile::setFriendlyFlags( weapon, self.hackerToolTarget );
passed = self hackerSoftSightTest( weapon );
if ( !passed )
{
continue;
}
if ( self.hackerToolLostSightlineTime == 0 )
{
self.hackerToolLockTimeElapsed += 0.1 * hackingTimeScale( self.hackerToolTarget );
hackPercentage = (self.hackerToolLockTimeElapsed / ( lockOnTime )) * 100;
self SetWeaponHackPercent( weapon, hackPercentage );
heatseekingmissile::setFriendlyFlags( weapon, self.hackerToolTarget );
}
else
{
self.hackerToolLockTimeElapsed -= 0.1 * hackingTimeNoLineOfSightScale( self.hackerToolTarget );
if ( self.hackerToolLockTimeElapsed < 0 )
{
self.hackerToolLockTimeElapsed = 0;
self clearHackerTarget( weapon, false, false );
continue;
}
hackPercentage = (self.hackerToolLockTimeElapsed / ( lockOnTime )) * 100;
self SetWeaponHackPercent( weapon, hackPercentage );
heatseekingmissile::setFriendlyFlags( weapon, self.hackerToolTarget );
}
if ( self.hackerToolLockTimeElapsed < lockOnTime )
{
continue;
}
assert( isdefined( self.hackerToolTarget ));
self notify( "stop_lockon_sound" );
self.hackerToolLockFinalized = true;
self WeaponLockFinalize( self.hackerToolTarget );
continue;
}
if ( self IsEMPJammed() )
{
self heatseekingmissile::DestroyLockOnCanceledMessage();
continue;
}
bestTarget = self getBestHackerToolTarget( weapon );
if ( !isdefined( bestTarget ))
{
self stopHackerToolSoundLoop();
self heatseekingmissile::DestroyLockOnCanceledMessage();
continue;
}
if ( !self heatseekingmissile::LockSightTest( bestTarget ) )
{
self stopHackerToolSoundLoop();
self heatseekingmissile::DestroyLockOnCanceledMessage();
continue;
}
//check for delay allowing helicopters to enter the play area
if( self heatseekingmissile::LockSightTest( bestTarget ) && isdefined( bestTarget.lockOnDelay ) && bestTarget.lockOnDelay )
{
self stopHackerToolSoundLoop();
self heatseekingmissile::DisplayLockOnCanceledMessage();
continue;
}
self heatseekingmissile::DestroyLockOnCanceledMessage();
if ( isEntityPreviouslyHacked( bestTarget ) )
{
if ( !isdefined( self.hacker_sound_ent ) || ( isdefined( self.hacker_alreadyhacked ) && self.hacker_alreadyhacked == false ) )
{
self.hacker_sound_ent = true;
self.hacker_alreadyhacked = true;
self playloopsound( "evt_hacker_unhackable_loop" );
}
continue;
}
else
{
self stopHackerToolSoundLoop();
}
heatseekingmissile::InitLockField( bestTarget );
self.hackerToolTarget = bestTarget;
self thread watchTargetEntityUpdate( bestTarget );
self.hackerToolLockStartTime = getTime();
self.hackerToolLockStarted = true;
self.hackerToolLostSightlineTime = 0;
self.hackerToolLockTimeElapsed = 0.0;
self SetWeaponHackPercent( weapon, 0.0 );
if ( isdefined( self.hackerToolTarget ) )
{
heatseekingmissile::setFriendlyFlags( weapon, self.hackerToolTarget );
}
}
}
function watchTargetEntityUpdate( bestTarget )
{
self endon( "death" );
self endon( "disconnect" );
self notify( "watchTargetEntityUpdate" );
self endon( "watchTargetEntityUpdate" );
self endon( "clearHackerTarget" );
bestTarget endon( "death" );
bestTarget waittill( "hackertool_update_ent", newEntity );
heatseekingmissile::InitLockField( newEntity );
self.hackerToolTarget = newEntity;
}
function getBestHackerToolTarget( weapon )
{
targetsValid = [];
targetsAll = ArrayCombine( target_getArray(), level.MissileEntities, false, false );
targetsAll = ArrayCombine( targetsAll, level.hackerToolTargets, false, false );
for ( idx = 0; idx < targetsAll.size; idx++ )
{
target_ent = targetsAll[ idx ];
if ( !isdefined( target_ent ) || !isdefined( target_ent.owner ) )
{
continue;
}
/#
//This variable is set and managed by the 'dev_friendly_lock' function, which works with the dev_gui
if( GetDvarString( "scr_freelock") == "1" )
{
//If the dev_gui dvar is set, only check if the target is in the reticule.
if( self isWithinHackerToolReticle( targetsAll[idx], weapon ) )
{
targetsValid[targetsValid.size] = targetsAll[idx];
}
continue;
}
#/
if ( level.teamBased || level.use_team_based_logic_for_locking_on === true ) //team based game modes
{
if ( isEntityHackableCarePackage( target_ent ))
{
if ( self canTargetEntity( target_ent, weapon ) )
{
targetsValid[ targetsValid.size ] = target_ent;
}
}
else if ( isdefined( target_ent.team ))
{
if ( target_ent.team != self.team )
{
if ( self canTargetEntity( target_ent, weapon ) )
{
targetsValid[ targetsValid.size ] = target_ent;
}
}
}
else if ( isdefined( target_ent.owner.team ) )
{
if ( target_ent.owner.team != self.team )
{
if ( self canTargetEntity( target_ent, weapon ) )
{
targetsValid[ targetsValid.size ] = target_ent;
}
}
}
}
else
{
if( self isWithinHackerToolReticle( target_ent, weapon )) //Free for all
{
if ( isEntityHackableCarePackage( target_ent ))
{
if ( self canTargetEntity( target_ent, weapon ) )
{
targetsValid[ targetsValid.size ] = target_ent;
}
}
else if( isdefined( target_ent.owner ) && self != target_ent.owner )
{
if ( self canTargetEntity( target_ent, weapon ) )
{
targetsValid[ targetsValid.size ] = target_ent;
}
}
}
}
}
chosenEnt = undefined;
if ( targetsValid.size != 0 )
{
//TODO: find the closest
chosenEnt = targetsValid[0];
}
return chosenEnt;
}
function canTargetEntity( target, weapon )
{
if ( !self isWithinHackerToolReticle( target, weapon ) )
return false;
if ( !isValidHackerToolTarget( target, weapon, true ) )
return false;
return true;
}
function isWithinHackerToolReticle( target, weapon )
{
radiusInner = getHackerToolInnerRadius( target );
radiusOuter = getHackerToolOuterRadius( target );
if( Target_ScaleMinMaxRadius( target, self, level.hackerToolLockOnFOV, radiusInner, radiusOuter ) > 0.0 )
{
return true;
}
return Target_BoundingIsUnderReticle( self, target, weapon.lockOnMaxRange );
}
//******************************************************************
// *
// *
//******************************************************************
function hackingTimeScale( target )
{
hackRatio = 1;
radiusInner = getHackerToolInnerRadius( target );
radiusOuter = getHackerToolOuterRadius( target );
if ( radiusInner != radiusOuter )
{
scale = Target_ScaleMinMaxRadius( target, self, level.hackerToolLockOnFOV, radiusInner, radiusOuter );
scale = scale * scale * scale * scale;
hackTime = LerpFloat( getHackOuterTime( target ), getHackTime( target ), scale );
/#
hackerToolDebugText = GetDvarInt( "hackertoolDebugText", 0 ) ;
if ( hackerToolDebugText )
{
print3d( target.origin, "scale: " + scale + "\nInner: " + radiusInner + " Outer: " + radiusOuter, ( 0, 0, 0 ), 1, hackerToolDebugText, 2 );
}
assert( hacktime > 0 );
#/
hackRatio = getHackTime( target ) / hackTime;
if ( !isdefined( hackRatio ) )
{
hackRatio = 1;
}
}
return hackRatio;
}
function hackingTimeNoLineOfSightScale( target )
{
hackRatio = 1;
if ( isdefined( target.killstreakHackLostLineOfSightTimeMs ) && target.killstreakHackLostLineOfSightTimeMs > 0 )
{
/#
assert( target.killstreakHackLostLineOfSightTimeMs > 0 );
#/
hackRatio = 1000 / target.killstreakHackLostLineOfSightTimeMs;
}
return hackRatio;
}
//******************************************************************
// *
// *
//******************************************************************
function isEntityHackableWeaponObject( entity )
{
if ( isdefined( entity.classname ) && entity.classname == "grenade" )
{
if ( isdefined( entity.weapon ) )
{
watcher = weaponobjects::getWeaponObjectWatcherByWeapon( entity.weapon );
if ( isdefined( watcher ))
{
if ( watcher.hackable )
{
/#
assert( isdefined( watcher.hackerToolRadius ));
assert( isdefined( watcher.hackerToolTimeMs ));
#/
return true;
}
}
}
}
return false;
}
//******************************************************************
// *
// *
//******************************************************************
function getWeaponObjectHackerRadius( entity )
{
/#
assert( isdefined( entity.classname ));
assert( isdefined( entity.weapon ));
#/
watcher = weaponobjects::getWeaponObjectWatcherByWeapon( entity.weapon );
/#
assert( watcher.hackable );
assert( isdefined( watcher.hackerToolRadius ));
#/
return watcher.hackerToolRadius;
}
//******************************************************************
// *
// *
//******************************************************************
function getWeaponObjectHackTimeMs( entity )
{
/#
assert( isdefined( entity.classname ));
assert( isdefined( entity.weapon ));
#/
watcher = weaponobjects::getWeaponObjectWatcherByWeapon( entity.weapon );
/#
assert( watcher.hackable );
assert( isdefined( watcher.hackerToolTimeMs ));
#/
return watcher.hackerToolTimeMs;
}
//******************************************************************
// *
// *
//******************************************************************
function isEntityHackableCarePackage( entity )
{
if ( isdefined( entity.model ))
{
return entity.model == "wpn_t7_care_package_world";
}
else
{
return false;
}
}
//******************************************************************
// *
// *
//******************************************************************
function isValidHackerToolTarget( ent, weapon, allowHacked ) // self == hacking player
{
if ( !isdefined( ent ))
{
return false;
}
if ( self util::isUsingRemote() )
{
return false;
}
if ( self IsEMPJammed() )
{
return false;
}
if ( !( target_isTarget( ent ) || isdefined( ent.allowHackingAfterCloak ) && ent.allowHackingAfterCloak == true )
&& !isEntityHackableWeaponObject( ent )
&& !IsInArray( level.hackerToolTargets, ent ) )
{
return false;
}
if ( isEntityHackableWeaponObject( ent ))
{
if ( DistanceSquared( self.origin, ent.origin ) > ( weapon.lockOnMaxRange * weapon.lockOnMaxRange ) )
{
return false;
}
}
if ( allowHacked == false && isEntityPreviouslyHacked( ent ) )
{
return false;
}
return true;
}
function isEntityPreviouslyHacked( entity )
{
if ( ( isdefined( entity.previouslyHacked ) && entity.previouslyHacked ) )
{
return true;
}
return false;
}
//******************************************************************
// *
// *
//******************************************************************
function hackerSoftSightTest( weapon ) // self == player
{
passed = true;
lockOnTime = 0;
if ( isdefined( self.hackerToolTarget ) )
{
lockOnTime = self getLockOnTime( self.hackerToolTarget, weapon );
}
if ( lockOnTime == 0 || self IsEMPJammed() )
{
self clearHackerTarget( weapon, false, false );
passed = false;
}
else
{
if ( isWithinHackerToolReticle( self.hackerToolTarget, weapon ) && self heatseekingmissile::LockSightTest( self.hackerToolTarget ) )
{
self.hackerToolLostSightlineTime = 0;
}
else
{
if ( self.hackerToolLostSightlineTime == 0 )
{
// pause the progress bar
self.hackerToolLostSightlineTime = getTime();
}
timePassed = GetTime() - self.hackerToolLostSightlineTime;
lostLineOfSightTimeLimitMsec = level.hackerToolLostSightLimitMs;
if ( isdefined( self.hackerToolTarget.killstreakHackLostLineOfSightLimitMs ) )
{
lostLineOfSightTimeLimitMsec = self.hackerToolTarget.killstreakHackLostLineOfSightLimitMs;
}
if ( timePassed >= lostLineOfSightTimeLimitMsec )
{
self clearHackerTarget( weapon, false, false );
passed = false;
}
}
}
return passed;
}
//******************************************************************
// *
// *
//******************************************************************
function registerWithHackerTool( radius, hackTimeMs ) // self == some hackable entity
{
self endon( "death" );
if ( isdefined( radius ))
{
self.hackerToolRadius = radius;
}
else
{
self.hackerToolRadius = level.hackerToolLockOnRadius;
}
if ( isdefined( hackTimeMs ))
{
self.hackerToolTimeMs = hackTimeMs;
}
else
{
self.hackerToolTimeMs = level.hackerToolHackTimeMs;
}
self thread watchHackableEntityDeath();
level.hackerToolTargets[ level.hackerToolTargets.size ] = self;
}
//******************************************************************
// *
// *
//******************************************************************
function watchHackableEntityDeath()
{
self waittill( "death" );
ArrayRemoveValue( level.hackerToolTargets, self );
}
//******************************************************************
// *
// *
//******************************************************************
function getHackerToolInnerRadius( target )
{
radius = level.hackerToolLockOnRadius;
if ( isEntityHackableCarePackage( target ))
{
/#assert( isdefined( target.hackerToolRadius ));#/
radius = target.hackerToolRadius;
}
else if ( isEntityHackableWeaponObject( target ))
{
radius = getWeaponObjectHackerRadius( target );
}
else if ( isdefined( target.hackerToolInnerRadius ))
{
radius = target.hackerToolInnerRadius;
}
else if ( isdefined( target.hackerToolRadius ))
{
radius = target.hackerToolRadius;
}
return radius;
}
//******************************************************************
// *
// *
//******************************************************************
function getHackerToolOuterRadius( target )
{
radius = level.hackerToolLockOnRadius;
if ( isEntityHackableCarePackage( target ))
{
/#assert( isdefined( target.hackerToolRadius ));#/
radius = target.hackerToolRadius;
}
else if ( isEntityHackableWeaponObject( target ))
{
radius = getWeaponObjectHackerRadius( target );
}
else if ( isdefined( target.hackerToolOuterRadius ))
{
radius = target.hackerToolOuterRadius;
}
else if ( isdefined( target.hackerToolRadius ))
{
radius = target.hackerToolRadius;
}
return radius;
}
//******************************************************************
// *
// *
//******************************************************************
function getHackTime( target ) // self == player
{
time = 500;
if ( isEntityHackableCarePackage( target ))
{
/#assert( isdefined( target.hackerToolTimeMs ));#/
//time = target.hackerToolTimeMs;
if ( isdefined( target.owner ) && ( target.owner == self ))
{
time = level.carePackageOwnerHackerToolTimeMs;
}
else if ( isdefined(target.owner) && (target.owner.team == self.team) )
{
time = level.carePackageFriendlyHackerToolTimeMs;
}
else
{
time = level.carePackageHackerToolTimeMs;
}
}
else if ( isEntityHackableWeaponObject( target ))
{
time = getWeaponObjectHackTimeMs( target );
}
else if ( isdefined( target.hackerToolInnerTimeMs ))
{
time = target.hackerToolInnerTimeMs;
}
else
{
// vehicles/targets from the target array
time = level.vehicleHackerToolTimeMs;
}
return time;
}
function getHackOuterTime( target ) // self == player
{
time = 500;
if ( isEntityHackableCarePackage( target ))
{
/#assert( isdefined( target.hackerToolTimeMs ));#/
//time = target.hackerToolTimeMs;
if ( isdefined( target.owner ) && ( target.owner == self ))
{
time = level.carePackageOwnerHackerToolTimeMs;
}
else if ( isdefined(target.owner) && (target.owner.team == self.team) )
{
time = level.carePackageFriendlyHackerToolTimeMs;
}
else
{
time = level.carePackageHackerToolTimeMs;
}
}
else if ( isEntityHackableWeaponObject( target ))
{
time = getWeaponObjectHackTimeMs( target );
}
else if ( isdefined( target.hackerToolOuterTimeMs ))
{
time = target.hackerToolOuterTimeMs;
}
else
{
// vehicles/targets from the target array
time = level.vehicleHackerToolTimeMs;
}
return time;
}
function getLockOnTime( target, weapon ) // self is the player, weapon is the hacker tool
{
lockLengthMs = self getHackTime( self.hackerToolTarget );
if ( lockLengthMs == 0 )
{
return 0;
}
lockOnSpeed = weapon.lockOnSpeed;
if ( lockOnSpeed <= 0 )
{
lockOnSpeed = 1000;
}
return lockLengthMs / lockOnSpeed;
}
/#
function tunables()
{
while(1)
{
level.hackerToolLostSightLimitMs = GetDvarInt( "scr_hackerToolLostSightLimitMs", 1000 );
level.hackerToolLockOnRadius = GetDvarFloat( "scr_hackerToolLockOnRadius", 20 );
level.hackerToolLockOnFOV = GetDvarInt( "scr_hackerToolLockOnFOV", 65 );
wait(1.0);
}
}
#/