#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); } } #/