Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Improved Missile Guidance Script v57 ("v50" + AotE Averaging Option)
- - Added optional weighted averaging between AimPointPosition and Position (CoM proxy)
- specifically for the *predictive* guidance phase. Controlled by AimPointWeight.
- - Terminal and Overshoot phases still target AimPointPosition directly for precision.
- - Added Bias Tuning.
- - Previous Features: Fixed Logic Flow, Hard G Pull, Per-Transceiver Prox, Min TTI Clamp, EWMA Accel, Iterative Pred, etc.
- ]]
- -- --- Configuration ---
- -- Core Settings
- local MainframeIndex = 0; local DetonationRadius = 8.0; local MinClosingSpeed = 1.0;
- -- Per-Transceiver Proximity Fuse Control
- local ProximityFuseEnabledPerTransceiver = {}; local DefaultProximityEnabled = true;
- -- Averaging Factor (Prediction Phase Only)
- -- Weight given to AimPointPosition vs Position (CoM proxy). 1.0 = Only AimPoint, 0.0 = Only Position, 0.5 = Halfway.
- local AimPointWeight = 1.0 -- <<< SET BETWEEN 0.0 and 1.0. Default 1.0 (current behavior).
- -- Prediction Bias Tuning -- TUNE THESE!
- local PredictionVerticalBias = 1.0 -- Subtracts Y value. Positive values counteract flying HIGH.
- local PredictionHorizontalBias = 1.0 -- Subtracts X value. Positive=West bias, Negative=East bias.
- -- Prediction Timing & Limits
- local MaxInterceptTime = 8.0; local MinInterceptTime = 0.05;
- -- Prediction Method Configuration
- local EnableAPNPrediction = true; local AccelFactor = 0.4; local MaxEstimatedAccel = 50.0;
- local EnableAccelSmoothing = true; local AccelSmoothingAlpha = 0.1;
- local EnableIterativePrediction = true;
- -- Overshoot Correction Config
- local EnableOvershootCorrection = true; local HardGPullOvershootDistance = 5.0;
- local OvershootMinRange = 20.0; local OvershootMinTargetSpeed = 5.0;
- local GentleOvershootDistance = 65.0;
- -- Terminal Guidance Config
- local EnableTerminalGuidance = true; local TerminalGuidanceRange = 35.0;
- -- --- End Configuration ---
- -- --- Global State ---
- if prevTime == nil then prevTime = 0 end; if prevTargetVel == nil then prevTargetVel = Vector3(0,0,0) end
- if prevUpdateTime == nil then prevUpdateTime = 0 end; if smoothedEstimatedTargetAccel == nil then smoothedEstimatedTargetAccel = Vector3(0,0,0) end
- -- --- End Global State ---
- --- Main Update Function ---
- function Update(I)
- local currentTime = I:GetTime(); if currentTime <= prevTime + 0.001 then return end
- local scriptDeltaTime = currentTime - prevTime; prevTime = currentTime
- local numTargets = I:GetNumberOfTargets(MainframeIndex)
- if numTargets == 0 then prevUpdateTime=0; smoothedEstimatedTargetAccel=Vector3(0,0,0); return end
- local targetInfo = I:GetTargetInfo(MainframeIndex, 0)
- if not targetInfo.Valid then prevUpdateTime=0; smoothedEstimatedTargetAccel=Vector3(0,0,0); return end
- -- Define both potential target points
- local targetAimPointPos = targetInfo.AimPointPosition
- local targetCenterPosProxy = targetInfo.Position -- Use Position as proxy for CoM/Center
- local targetVel = targetInfo.Velocity
- local targetSpeed = targetVel.magnitude
- -- --- Target Acceleration Estimation ---
- local rawEstimatedTargetAccel = Vector3(0,0,0); local actualDeltaTime = currentTime - prevUpdateTime
- if EnableAPNPrediction and prevUpdateTime > 0 and actualDeltaTime > 0.01 then
- rawEstimatedTargetAccel = (targetVel - prevTargetVel) / actualDeltaTime
- if rawEstimatedTargetAccel.magnitude > MaxEstimatedAccel then rawEstimatedTargetAccel = rawEstimatedTargetAccel.normalized * MaxEstimatedAccel end
- if EnableAccelSmoothing then smoothedEstimatedTargetAccel = rawEstimatedTargetAccel * AccelSmoothingAlpha + smoothedEstimatedTargetAccel * (1.0 - AccelSmoothingAlpha)
- else smoothedEstimatedTargetAccel = rawEstimatedTargetAccel end
- else smoothedEstimatedTargetAccel = Vector3(0,0,0) end
- prevTargetVel = targetVel; prevUpdateTime = currentTime
- -- --- End Acceleration Estimation ---
- local transceiverCount = I:GetLuaTransceiverCount()
- for trIdx = 0, transceiverCount - 1 do
- local missileCount = I:GetLuaControlledMissileCount(trIdx)
- for mIdx = 0, missileCount - 1 do
- local missileInfo = I:GetLuaControlledMissileInfo(trIdx, mIdx)
- if not missileInfo.Valid then goto NextMissile end
- local missilePos = missileInfo.Position; local missileVel = missileInfo.Velocity
- local missileSpeed = missileVel.magnitude
- -- Calculate relative kinematics based on the AimPoint primarily
- local vectorTargetToMissile = missilePos - targetAimPointPos -- Vector relative to AimPoint
- local relativeVel = missileVel - targetVel
- local range = vectorTargetToMissile.magnitude -- Range to AimPoint
- local aimPoint = targetAimPointPos -- Default aim point is target's AimPointPosition
- local guidanceModeSet = false
- local useProximity = ProximityFuseEnabledPerTransceiver[trIdx]; if useProximity == nil then useProximity = DefaultProximityEnabled end
- -- *** Guidance Logic Flow ***
- if useProximity and range <= DetonationRadius then I:DetonateLuaControlledMissile(trIdx, mIdx); guidanceModeSet = true; goto NextMissile end
- local closingSpeed = 0; local timeToIntercept = MaxInterceptTime; local canIntercept = false
- if range >= 0.01 then
- closingSpeed = Vector3.Dot(relativeVel, -vectorTargetToMissile.normalized) -- Closing speed towards AimPoint
- canIntercept = closingSpeed >= MinClosingSpeed
- if closingSpeed > 0.001 then timeToIntercept = range / closingSpeed; timeToIntercept = Mathf.Max(MinInterceptTime, Mathf.Min(timeToIntercept, MaxInterceptTime))
- else canIntercept = false; timeToIntercept = MaxInterceptTime end
- else canIntercept = false; timeToIntercept = MinInterceptTime end
- -- 2. Check Terminal Guidance (Aims DIRECTLY at AimPoint)
- if not guidanceModeSet and EnableTerminalGuidance and range <= TerminalGuidanceRange then
- aimPoint = targetAimPointPos
- guidanceModeSet = true
- end
- -- 3. Check Overshoot Correction (Aims DIRECTLY at AimPoint)
- if not guidanceModeSet and EnableOvershootCorrection and range > OvershootMinRange and targetSpeed > OvershootMinTargetSpeed then
- local targetVelNorm = targetVel.normalized
- if targetVelNorm.magnitude > 0.01 then
- local distanceAhead = Vector3.Dot(vectorTargetToMissile, targetVelNorm) -- Distance ahead relative to AimPoint
- if distanceAhead > HardGPullOvershootDistance then aimPoint = targetAimPointPos; guidanceModeSet = true
- elseif distanceAhead > GentleOvershootDistance then aimPoint = targetAimPointPos; guidanceModeSet = true end
- end
- end
- -- 4. Perform Predictive Guidance (Only if no other mode was set)
- if not guidanceModeSet then
- if not canIntercept then
- aimPoint = targetAimPointPos -- Fallback aims at AimPoint
- else
- -- *** NEW: Calculate weighted base position for prediction ***
- local baseTargetPosForPred = targetAimPointPos * AimPointWeight + targetCenterPosProxy * (1.0 - AimPointWeight)
- -- Perform prediction using baseTargetPosForPred as the reference
- local timeToIntercept1 = timeToIntercept
- local accelTerm1 = Vector3(0,0,0)
- if EnableAPNPrediction and smoothedEstimatedTargetAccel.magnitude > 0.01 then accelTerm1 = smoothedEstimatedTargetAccel * (timeToIntercept1 * timeToIntercept1 * AccelFactor) end
- local predictedInterceptPoint1 = baseTargetPosForPred + targetVel * timeToIntercept1 + accelTerm1 -- Predict from base pos
- local predictedInterceptPoint = predictedInterceptPoint1
- if EnableIterativePrediction then
- -- Recalculate range/TTI relative to the *first predicted point* (not the base avg point) for iteration 2
- local vectorToPIP1 = predictedInterceptPoint1 - missilePos
- local rangeToPIP1 = vectorToPIP1.magnitude
- local closingSpeedToPIP1 = Vector3.Dot(missileVel, vectorToPIP1.normalized) -- Closing speed towards PIP1
- local timeToIntercept2 = MaxInterceptTime
- -- Only recalculate if closing speed to PIP1 is reasonable
- if closingSpeedToPIP1 > MinClosingSpeed * 0.5 then -- Use slightly lower threshold?
- timeToIntercept2 = rangeToPIP1 / closingSpeedToPIP1
- timeToIntercept2 = Mathf.Max(MinInterceptTime, Mathf.Min(timeToIntercept2, MaxInterceptTime))
- end
- local accelTerm2 = Vector3(0,0,0)
- if EnableAPNPrediction and smoothedEstimatedTargetAccel.magnitude > 0.01 then accelTerm2 = smoothedEstimatedTargetAccel * (timeToIntercept2 * timeToIntercept2 * AccelFactor) end
- predictedInterceptPoint = baseTargetPosForPred + targetVel * timeToIntercept2 + accelTerm2 -- Predict again from base pos using new TTI
- end
- -- Apply Biases to the final predicted point
- local biasVector = Vector3(PredictionHorizontalBias, PredictionVerticalBias, 0)
- if biasVector.magnitude > 0 then aimPoint = predictedInterceptPoint - biasVector
- else aimPoint = predictedInterceptPoint end
- end
- guidanceModeSet = true
- end
- if guidanceModeSet then I:SetLuaControlledMissileAimPoint(trIdx, mIdx, aimPoint.x, aimPoint.y, aimPoint.z) end
- ::NextMissile::
- end -- End missile loop
- end -- End transceiver loop
- end -- End Update function
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement