#include maps\mp\_utility; #include common_scripts\utility; InitJavelinUsage() { self.javelinStage = undefined; self.javelinPoints = undefined; self.javelinNormals = undefined; self.javelinLockMisses = undefined; self.javelinTargetPoint = undefined; self.javelinTargetNormal = undefined; self.javelinLockStartTime = undefined; } ResetJavelinLocking() { if ( !IsDefined( self.javelinUseEntered ) ) return; self.javelinUseEntered = undefined; self notify( "stop_lockon_sound" ); self WeaponLockFree(); self WeaponLockTargetTooClose( false ); self WeaponLockNoClearance( false ); self.currentlyLocking = false; self.currentlyLocked = false; self.javelinTarget = undefined; self StopLocalSound( "javelin_clu_lock" ); self StopLocalSound( "javelin_clu_aquiring_lock" ); InitJavelinUsage(); } /# DrawStar( point, color ) { Line( point + (10,0,0), point - (10,0,0), color ); Line( point + (0,10,0), point - (0,10,0), color ); Line( point + (0,0,10), point - (0,0,10), color ); } #/ EyeTraceForward() { origin = self GetEye(); angles = self GetPlayerAngles(); forward = AnglesToForward( angles ); endpoint = origin + forward * 15000; res = BulletTrace( origin, endpoint, false, undefined ); if ( res["surfacetype"] == "none" ) return undefined; if ( res["surfacetype"] == "default" ) return undefined; ent = res["entity"]; if ( IsDefined( ent ) ) { if ( ent == level.ac130.planeModel ) return undefined; } results = []; results[0] = res["position"]; results[1] = res["normal"]; return results; } LockMissesReset() { self.javelinLockMisses = undefined; } LockMissesIncr() { if ( !IsDefined( self.javelinLockMisses ) ) self.javelinLockMisses = 1; else self.javelinLockMisses++; } LockMissesPassedThreshold() { MAX_MISSES = 4; if ( IsDefined( self.javelinLockMisses ) && (self.javelinLockMisses >= MAX_MISSES) ) return true; return false; } TargetPointTooClose( targetPoint ) { MY_MIN_DIST = 1100; dist = Distance( self.origin, targetPoint ); if ( dist < MY_MIN_DIST ) return true; return false; } LoopLocalSeekSound( alias, interval ) { self endon ( "death" ); self endon ( "disconnect" ); self endon ( "stop_lockon_sound" ); for ( ;; ) { self PlayLocalSound( alias ); wait interval; } } TopAttackPasses( targPoint, targNormal ) { origin = targPoint + (targNormal * 10.0); endpoint = origin + (0,0,2000); result = BulletTrace( origin, endpoint, false, undefined ); if ( BulletTracePassed( origin, endpoint, false, undefined ) ) return true; return false; } JavelinUsageLoop() { self endon("death"); self endon("disconnect"); LOCK_LENGTH = 1150; GATHER_DELAY = 25; ADS_DELAY = 100; MAX_POINT_PEER_DIST = 400; POINTS_NEEDED_TO_START_LOCK = 12; lastGatherTime = 0; lastOutOfADS = 0; self.javelinTarget = undefined; InitJavelinUsage(); for( ;; ) { wait 0.05; debugDraw = false; if ( GetDVar( "missileDebugDraw" ) == "1" ) debugDraw = true; debugText = false; if ( GetDVar( "missileDebugText" ) == "1" ) debugText = true; weapon = self getCurrentWeapon(); if ( !isSubStr( weapon, "javelin" ) || self isEMPed() ) { ResetJavelinLocking(); continue; } if ( self PlayerADS() < 0.95 ) { lastOutOfADS = GetTime(); ResetJavelinLocking(); continue; } self.javelinUseEntered = true; if ( !IsDefined( self.javelinStage ) ) self.javelinStage = 1; if ( self.javelinStage == 1 ) // SCANNING: try to find a good point to lock to { targets = GetTargetList(); if ( targets.size != 0 ) { targetsInReticle = []; foreach ( target in targets ) { insideReticle = self WorldPointInReticle_Circle( target.origin, 65, 40 ); if ( insideReticle ) targetsInReticle[targetsInReticle.size] = target; } if ( targetsInReticle.size != 0 ) { sortedTargets = SortByDistance( targetsInReticle, self.origin ); if ( !( self VehicleLockSightTest( sortedTargets[0] ) ) ) continue; if ( debugText ) PrintLn( "Javeling found a vehicle target to lock to." ); self.javelinTarget = sortedTargets[0]; if ( !isDefined( self.javelinLockStartTime ) ) self.javelinLockStartTime = GetTime(); self.javelinStage = 2; self.javelinLostSightlineTime = 0; self javelinLockVehicle( LOCK_LENGTH ); self.javelinStage = 1; continue; } } if ( LockMissesPassedThreshold() ) { ResetJavelinLocking(); continue; } timePassed = GetTime() - lastOutOfADS; if ( timePassed < ADS_DELAY ) continue; /# if ( debugDraw && IsDefined( self.javelinPoints ) ) { foreach( javPoint in self.javelinPoints ) DrawStar( javPoint, (0.8, 1.0, 0.8) ); DrawStar( self.javelinPoints[self.javelinPoints.size - 1], (1, 1, 0.2) ); DrawStar( AveragePoint( self.javelinPoints ), (0.2, 0.2, 1) ); } #/ timePassed = GetTime() - lastGatherTime; if ( timePassed < GATHER_DELAY ) continue; lastGatherTime = GetTime(); traceRes = (self EyeTraceForward()); if ( !IsDefined( traceRes ) ) { self LockMissesIncr(); continue; } if ( self TargetPointTooClose( traceRes[0] ) ) { self WeaponLockTargetTooClose( true ); continue; } else { self WeaponLockTargetTooClose( false ); } // make sure we haven't strayed too far if ( IsDefined( self.javelinPoints ) ) { prevAvgPoint = AveragePoint( self.javelinPoints ); dist = Distance( prevAvgPoint, traceRes[0] ); //PrintLn( "[", self.javelinPoints.size, "] - Dist: ", dist ); if ( dist > MAX_POINT_PEER_DIST ) { LockMissesIncr(); continue; } } else { self.javelinPoints = []; self.javelinNormals = []; } self.javelinPoints[self.javelinPoints.size] = traceRes[0]; self.javelinNormals[self.javelinNormals.size] = traceRes[1]; self LockMissesReset(); if ( self.javelinPoints.size < POINTS_NEEDED_TO_START_LOCK ) continue; // Go to stage 2: self.javelinTargetPoint = AveragePoint( self.javelinPoints );; self.javelinTargetNormal = AverageNormal( self.javelinNormals );; self.javelinLockMisses = undefined; self.javelinPoints = undefined; self.javelinNormals = undefined; self.javelinLockStartTime = GetTime(); self WeaponLockStart( self.javelinTargetPoint ); self thread LoopLocalSeekSound( "javelin_clu_aquiring_lock", 0.6 ); self.javelinStage = 2; } if ( self.javelinStage == 2 ) // LOCKING: complete lockon to point { /# if ( debugDraw ) DrawStar( self.javelinTargetPoint, (0.5, 1.0, 0.6) ); #/ insideReticle = self WorldPointInReticle_Circle( self.javelinTargetPoint, 65, 45 ); if ( !insideReticle ) { ResetJavelinLocking(); continue; } if ( self TargetPointTooClose( self.javelinTargetPoint ) ) self WeaponLockTargetTooClose( true ); else self WeaponLockTargetTooClose( false ); timePassed = getTime() - self.javelinLockStartTime; //PrintLn( "Locking [", timePassed, "]..." ); if ( timePassed < LOCK_LENGTH ) continue; self WeaponLockFinalize( self.javelinTargetPoint, (0,0,0), true ); self notify( "stop_lockon_sound" ); self PlayLocalSound( "javelin_clu_lock" ); self.javelinStage = 3; } if ( self.javelinStage == 3 ) // LOCKED: try and hold it { /# if ( debugDraw ) DrawStar( self.javelinTargetPoint, (0.1, 0.15, 1.0) ); #/ insideReticle = self WorldPointInReticle_Circle( self.javelinTargetPoint, 65, 45 ); if ( !insideReticle ) { ResetJavelinLocking(); continue; } if ( self TargetPointTooClose( self.javelinTargetPoint ) ) self WeaponLockTargetTooClose( true ); else self WeaponLockTargetTooClose( false ); continue; } } } GetTargetList() { targets = []; if ( level.teamBased ) { if ( IsDefined( level.chopper ) && ( level.chopper.team != self.team || level.chopper.owner == self ) ) ///check for teams targets[targets.size] = level.chopper; if ( isDefined( level.harriers) ) { foreach( harrier in level.harriers ) { if ( isDefined( harrier ) && ( harrier.team != self.team || ( isDefined( harrier.owner ) && harrier.owner == self ) ) ) targets[targets.size] = harrier; } } if ( level.UAVModels[level.otherTeam[self.team]].size ) { foreach ( UAV in level.UAVModels[level.otherTeam[self.team]] ) targets[targets.size] = UAV; } if ( isDefined(level.ac130player) && ( level.ac130player.team != self.team ) ) targets[targets.size] = level.ac130.planeModel; } else { if ( IsDefined( level.chopper ) && ( level.chopper.owner != self ) ) ///check for teams targets[targets.size] = level.chopper; if ( isDefined(level.ac130player) ) targets[targets.size] = level.ac130; if ( isDefined( level.harriers) ) { foreach( harrier in level.harriers ) { if ( isDefined( harrier ) ) targets[targets.size] = harrier; } } if ( level.UAVModels.size ) { foreach ( ownerGuid, UAV in level.UAVModels ) { if ( isDefined( UAV.owner ) && UAV.owner == self ) continue; targets[targets.size] = UAV; } } } return targets; } DebugSightLine( start, end, passed ) { /# if ( GetDVar( "missileDebugDraw" ) != "1" ) return; if ( passed ) color = ( 0.3, 1.0, 0.3 ); else color = ( 1.0, 0.2, 0.2 ); MY_OFFSET = ( 0, 0, 5 ); Line( start + MY_OFFSET, end, color ); #/ } VehicleLockSightTest( target ) { eyePos = self GetEye(); center = target GetPointInBounds( 0, 0, 0 ); passed = BulletTracePassed( eyePos, center, false, target ); DebugSightLine( eyePos, center, passed ); if ( passed ) return true; front = target GetPointInBounds( 1, 0, 0 ); passed = BulletTracePassed( eyePos, front, false, target ); DebugSightLine( eyePos, front, passed ); if ( passed ) return true; back = target GetPointInBounds( -1, 0, 0 ); passed = BulletTracePassed( eyePos, back, false, target ); DebugSightLine( eyePos, back, passed ); if ( passed ) return true; return false; } javelinLockVehicle( lockLength ) { if ( self.javelinStage == 2 ) // locking on to a target { self WeaponLockStart( self.javelinTarget ); if ( !(self StillValidJavelinLock( self.javelinTarget ) ) ) { ResetJavelinLocking(); self.javelinLockStartTime = undefined; return; } passed = SoftSightTest(); if ( !passed ) { self.javelinLockStartTime = undefined; return; } if ( !isDefined( self.currentlyLocking ) || !self.currentlyLocking ) { self thread LoopLocalSeekSound( "javelin_clu_aquiring_lock", 0.6 ); self.currentlyLocking = true; } timePassed = getTime() - self.javelinLockStartTime; if ( timePassed < lockLength ) return; //strangely buggy with the moving target... //javTarg = eyeTraceForward(); //if ( !isDefined( javTarg ) ) // return; //topAttack = TopAttackPasses( javTarg[0], javTarg[1] ); self WeaponLockFinalize( self.javelinTarget, (0,0,0), false ); self notify( "stop_lockon_sound" ); if ( !isDefined( self.currentlyLocked ) || !self.currentlyLocked ) { self PlayLocalSound( "javelin_clu_lock" ); self.currentlyLocked = true; } self.javelinStage = 3; } if ( self.javelinStage == 3 ) // target locked { passed = SoftSightTest(); if ( !passed ) return; if ( !(self StillValidJavelinLock( self.javelinTarget ) ) ) { ResetJavelinLocking(); return; } } } StillValidJavelinLock( ent ) { assert( IsDefined( self ) ); if ( !IsDefined( ent ) ) return false; if ( !(self WorldPointInReticle_Circle( ent.origin, 65, 85 )) ) return false; return true; } SoftSightTest() { LOST_SIGHT_LIMIT = 500; if ( self VehicleLockSightTest( self.javelinTarget ) ) { self.javelinLostSightlineTime = 0; return true; } if ( self.javelinLostSightlineTime == 0 ) self.javelinLostSightlineTime = getTime(); timePassed = GetTime() - self.javelinLostSightlineTime; if ( timePassed >= LOST_SIGHT_LIMIT ) { ResetJavelinLocking(); return false; } return true; }