Advertisement
Guest User

From the depths missile lua

a guest
Mar 26th, 2025
33
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.87 KB | None | 0 0
  1. --[[
  2. Improved Missile Guidance Script V2 (incorporating critiques)
  3. - Relative Vector Consistency Addressed
  4. - Smoothed Target Acceleration Estimation (EWMA)
  5. - Optional Two-Stage Iterative Prediction
  6. - Tuned Overshoot Correction
  7. - Terminal Guidance phase (direct intercept when close)
  8. ]]
  9.  
  10. -- --- Configuration ---
  11. local MainframeIndex = 0 -- Index of the AI Mainframe providing target data (0 = first mainframe)
  12. local DetonationRadius = 8.0 -- Proximity fuse radius (meters)
  13. local MinClosingSpeed = 1.0 -- Minimum closing speed (m/s) to attempt interception. Avoids division by zero/instability.
  14. local MaxInterceptTime = 20.0 -- Maximum time to predict ahead (seconds).
  15.  
  16. -- Prediction Config
  17. local EnableAPNPrediction = true -- Use target acceleration in prediction
  18. local AccelFactor = 0.5 -- How much weight to give the acceleration term (0.5 is standard kinematic)
  19. local MaxEstimatedAccel = 50.0 -- Clamp max estimated acceleration magnitude (m/s^2)
  20. local EnableAccelSmoothing = true -- Use EWMA to smooth acceleration estimate
  21. local AccelSmoothingAlpha = 0.1 -- Smoothing factor for EWMA (lower = smoother, more lag; 0.1 suggested)
  22.  
  23. local EnableIterativePrediction = true -- Use two iterations for prediction (addresses critique #4)
  24.  
  25. -- Overshoot Correction Config
  26. local EnableOvershootCorrection = true -- Try to correct if missile flies too far past target
  27. local OvershootMinRange = 75.0 -- Only check for overshoot beyond this range
  28. local OvershootMinTargetSpeed = 5.0 -- Only check if target is moving reasonably fast
  29. local OvershootDistanceAhead = 65.0 -- How far ahead of target (along its velocity vector) missile must be to trigger correction (Increased from 50 based on critique #2)
  30. -- Note on Overshoot: Sensor noise can affect accuracy. This aims back at target if missile seems far ahead along target's path.
  31.  
  32. -- Terminal Guidance Config
  33. local EnableTerminalGuidance = true -- Use direct intercept when very close
  34. local TerminalGuidanceRange = 35.0 -- Distance (m) to switch to direct intercept. MUST be > DetonationRadius.
  35.  
  36. -- --- End Configuration ---
  37.  
  38. -- --- Global State ---
  39. -- Initialize state variables lazily or ensure they exist
  40. if prevTime == nil then prevTime = 0 end
  41. if prevTargetVel == nil then prevTargetVel = Vector3(0,0,0) end
  42. if prevUpdateTime == nil then prevUpdateTime = 0 end
  43. if smoothedEstimatedTargetAccel == nil then smoothedEstimatedTargetAccel = Vector3(0,0,0) end -- For EWMA
  44. -- --- End Global State ---
  45.  
  46. --- Main Update Function ---
  47. function Update(I)
  48. local currentTime = I:GetTime()
  49. -- Avoid running multiple times in the same physics step or if time hasn't advanced
  50. if currentTime <= prevTime + 0.001 then return end
  51. local scriptDeltaTime = currentTime - prevTime
  52. prevTime = currentTime
  53.  
  54. local numTargets = I:GetNumberOfTargets(MainframeIndex)
  55. if numTargets == 0 then
  56. -- Reset history if no targets
  57. prevUpdateTime = 0
  58. smoothedEstimatedTargetAccel = Vector3(0,0,0)
  59. return
  60. end
  61.  
  62. local targetInfo = I:GetTargetInfo(MainframeIndex, 0)
  63. if not targetInfo.Valid then
  64. -- Reset history if target invalid
  65. prevUpdateTime = 0
  66. smoothedEstimatedTargetAccel = Vector3(0,0,0)
  67. return
  68. end
  69.  
  70. local targetPos = targetInfo.Position
  71. local targetVel = targetInfo.Velocity
  72. local targetSpeed = targetVel.magnitude
  73.  
  74. -- --- Estimate Target Acceleration (with Smoothing Option) ---
  75. local rawEstimatedTargetAccel = Vector3(0,0,0)
  76. local actualDeltaTime = currentTime - prevUpdateTime -- Time since last valid target update
  77.  
  78. if EnableAPNPrediction and prevUpdateTime > 0 and actualDeltaTime > 0.01 then
  79. rawEstimatedTargetAccel = (targetVel - prevTargetVel) / actualDeltaTime
  80. -- Clamp raw acceleration estimate
  81. if rawEstimatedTargetAccel.magnitude > MaxEstimatedAccel then
  82. rawEstimatedTargetAccel = rawEstimatedTargetAccel.normalized * MaxEstimatedAccel
  83. end
  84.  
  85. -- Apply EWMA smoothing if enabled (addresses critique #3)
  86. if EnableAccelSmoothing then
  87. smoothedEstimatedTargetAccel = rawEstimatedTargetAccel * AccelSmoothingAlpha + smoothedEstimatedTargetAccel * (1.0 - AccelSmoothingAlpha)
  88. else
  89. smoothedEstimatedTargetAccel = rawEstimatedTargetAccel -- Use raw if smoothing disabled
  90. end
  91. else
  92. -- Reset smoothed accel if we don't have a valid delta time or previous velocity
  93. smoothedEstimatedTargetAccel = Vector3(0,0,0)
  94. end
  95. -- Store current values for next frame's calculation
  96. prevTargetVel = targetVel
  97. prevUpdateTime = currentTime
  98. -- --- End Acceleration Estimation ---
  99.  
  100. local transceiverCount = I:GetLuaTransceiverCount()
  101. for trIdx = 0, transceiverCount - 1 do
  102. local missileCount = I:GetLuaControlledMissileCount(trIdx)
  103. for mIdx = 0, missileCount - 1 do
  104. local missileInfo = I:GetLuaControlledMissileInfo(trIdx, mIdx)
  105. if not missileInfo.Valid then goto NextMissile end -- Skip dead/invalid missiles
  106.  
  107. local missilePos = missileInfo.Position
  108. local missileVel = missileInfo.Velocity
  109. local missileSpeed = missileVel.magnitude
  110.  
  111. -- Calculate vectors FROM target TO missile (addresses critique #1 consistency)
  112. local relativePos = missilePos - targetPos
  113. local relativeVel = missileVel - targetVel -- Velocity of missile relative to target
  114. local range = relativePos.magnitude
  115.  
  116. -- *** Order of Checks: Detonation -> Terminal -> Overshoot -> Prediction ***
  117.  
  118. -- 1. Check for Detonation Proximity
  119. if range <= DetonationRadius then
  120. -- I:Log(string.format("Missile [%d,%d] Detonating. Range: %.1f", trIdx, mIdx, range)) -- Debug
  121. I:DetonateLuaControlledMissile(trIdx, mIdx)
  122. goto NextMissile
  123. end
  124.  
  125. -- 2. Check for Terminal Guidance Phase
  126. if EnableTerminalGuidance and range <= TerminalGuidanceRange then
  127. -- Aim directly at the target's current position for final approach
  128. -- I:Log(string.format("Missile [%d,%d] Terminal Phase. Range: %.1f", trIdx, mIdx, range)) -- Debug
  129. I:SetLuaControlledMissileAimPoint(trIdx, mIdx, targetPos.x, targetPos.y, targetPos.z)
  130. goto NextMissile -- Skip prediction and overshoot logic
  131. end
  132.  
  133. -- 3. Check for Overshoot Condition (Only if not in terminal phase)
  134. -- Corrects if missile is significantly ahead of target along target's path
  135. if EnableOvershootCorrection and range > OvershootMinRange and targetSpeed > OvershootMinTargetSpeed then
  136. local targetVelNorm = targetVel.normalized
  137. if targetVelNorm.magnitude > 0.01 then -- Ensure target has a clear direction
  138. -- Vector from target to missile (already calculated as relativePos)
  139. -- Project this vector onto the target's velocity direction
  140. local distanceAhead = Vector3.Dot(relativePos, targetVelNorm)
  141. -- If missile is further ahead than the threshold, aim back directly at target
  142. if distanceAhead > OvershootDistanceAhead then
  143. -- I:Log(string.format("Missile [%d,%d] Overshoot detected (%.1f > %.1f). Correcting.", trIdx, mIdx, distanceAhead, OvershootDistanceAhead)) -- Debug
  144. I:SetLuaControlledMissileAimPoint(trIdx, mIdx, targetPos.x, targetPos.y, targetPos.z)
  145. goto NextMissile
  146. end
  147. end
  148. end
  149.  
  150. -- 4. Proceed with Predictive Guidance
  151. if range < 0.01 then -- Safety check (should be caught earlier)
  152. I:DetonateLuaControlledMissile(trIdx, mIdx)
  153. goto NextMissile
  154. end
  155.  
  156. -- Calculate closing speed using consistent vectors (addresses critique #1)
  157. -- Closing speed is component of relative velocity ALONG the line from target to missile
  158. local closingSpeed = Vector3.Dot(relativeVel, relativePos.normalized)
  159.  
  160. -- Check if missile can realistically close the distance
  161. if closingSpeed < MinClosingSpeed then
  162. -- Fallback: Aim directly at current target position if cannot close effectively
  163. -- I:Log(string.format("Missile [%d,%d] Low closing speed: %.1f. Aiming direct.", trIdx, mIdx, closingSpeed)) -- Debug
  164. I:SetLuaControlledMissileAimPoint(trIdx, mIdx, targetPos.x, targetPos.y, targetPos.z)
  165. goto NextMissile
  166. end
  167.  
  168. -- --- Prediction Calculation ---
  169. local predictedInterceptPoint
  170.  
  171. -- Iteration 1 (or only iteration if IterativePrediction disabled)
  172. local timeToIntercept1 = range / closingSpeed
  173. timeToIntercept1 = Mathf.Min(timeToIntercept1, MaxInterceptTime) -- Clamp prediction time
  174.  
  175. local accelTerm1 = Vector3(0,0,0)
  176. if EnableAPNPrediction and smoothedEstimatedTargetAccel.magnitude > 0.01 then
  177. -- Standard kinematic prediction: s = ut + 0.5at^2
  178. accelTerm1 = smoothedEstimatedTargetAccel * (timeToIntercept1 * timeToIntercept1 * AccelFactor)
  179. end
  180. local predictedInterceptPoint1 = targetPos + targetVel * timeToIntercept1 + accelTerm1
  181.  
  182. if EnableIterativePrediction then
  183. -- Iteration 2 (Refine TTI based on distance to first PIP) - addresses critique #4
  184. local rangeToPIP1 = (predictedInterceptPoint1 - missilePos).magnitude
  185. local timeToIntercept2 = rangeToPIP1 / closingSpeed -- Use same closing speed, but new range
  186. timeToIntercept2 = Mathf.Min(timeToIntercept2, MaxInterceptTime) -- Clamp again
  187.  
  188. local accelTerm2 = Vector3(0,0,0)
  189. if EnableAPNPrediction and smoothedEstimatedTargetAccel.magnitude > 0.01 then
  190. accelTerm2 = smoothedEstimatedTargetAccel * (timeToIntercept2 * timeToIntercept2 * AccelFactor)
  191. end
  192. predictedInterceptPoint = targetPos + targetVel * timeToIntercept2 + accelTerm2
  193. else
  194. -- Use the result from the first iteration if iterative prediction is off
  195. predictedInterceptPoint = predictedInterceptPoint1
  196. end
  197. -- --- End Prediction Calculation ---
  198.  
  199. -- Aim the missile at the final predicted point
  200. I:SetLuaControlledMissileAimPoint(trIdx, mIdx, predictedInterceptPoint.x, predictedInterceptPoint.y, predictedInterceptPoint.z)
  201.  
  202. -- Label for goto statement to jump to the next missile
  203. ::NextMissile::
  204. end -- End missile loop (mIdx)
  205. end -- End transceiver loop (trIdx)
  206.  
  207. end -- End Update function
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement