CheezusCrust

Untitled

Jan 29th, 2018
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.35 KB | None | 0 0
  1. ####
  2. ## ACF Bulletometer - An RK4 trajectory predictor for ACF guns.
  3. ## By Bubbus (with thanks to Frankess, Tolyzor, RedReaper and Frohman @ wiremod.com, and doswa.com for RK4 details)
  4. ## Problems? PM me at wiremod.com (username Splambob)
  5. #### Description:
  6. ## This chip will calculate the trajectory of an ACF projectile.
  7. ## It can calculate most trajectories with reasonable accuracy if the inputs are accurate.
  8. ## Use the EndPos output with any kind of hologram or HUD chip to see where the shot will land.
  9. ## Use the Correction input with a wire Adv. Input chip to easily find a number for any inaccuracy.
  10. ## This chip will calculate continuously (every Interval seconds) while Solve is not 0 and the gun is moving.
  11. ## Use the DoHolos input to visualize predicted trajectory and velocity (relative to muzzle velocity).
  12. ## Use the Precision input to control the coarseness of the predictor.
  13. #### Inputs:
  14. ## Solve boolean Trigger trajectory calculation.
  15. ## Gun entity The ACF weapon to calculate from.
  16. ## Correction m/s Additive fine-tuning of the MuzzleVel
  17. ## DoHolos boolean Spawn holograms along the predicted trajectory.
  18. ## This will slow down calculation to accelerated-time, do not use for combat.
  19. ## Interval s Seconds between calculation completion and next calculation (default 0.334)
  20. ## Tolerance number The gun movement tolerance. Larger values allow the gun to move more before a recalculation.
  21. ## Useful for vehicles or wobbly/jittery turrets. (default 1)
  22. ## Precision number Coarseness of the prediction algorithm. Bigger numbers mean better precision but more ops.
  23. ## Big values will "time out" the calculation. (default 0.75)
  24. #### Outputs:
  25. ## Run boolean 1 if chip is calculating a trajectory, else 0
  26. ## Hit boolean 1 if the virtual projectile has hit a surface, else 0
  27. ## Time s The amount of time the virtual projectile has currently spent flying.
  28. ## EndPos vector The ending position of the predicted projectile (first collision).
  29. ##
  30. ## The following outputs describe end-conditions of the projectile EXCEPT during DoHolos or a very long calculation!
  31. ## Pos vector The current position of the virtual projectile.
  32. ## Vel vector The current velocity of the virtual projectile.
  33. ####
  34.  
  35.  
  36. @name ACF Bulletometer
  37. @inputs Solve Gun:entity Correction DoHolos Interval Tolerance Precision
  38. @outputs Run Hit Time [EndPos Pos Vel]:vector
  39. @persist Mass MuzzleVel Caliber CaliberS:string
  40. @persist StateRK4:array Grav:vector DragCoef SpeedLimit
  41. @persist DragDiv PBase MVScale
  42. @persist LastIters OptimalIters MaxIters DT MSMVel HoloBurst
  43. @persist [LastGunPos LastGunDir]:vector
  44. @trigger Solve Gun Correction DoHolos
  45.  
  46.  
  47. if (dupefinished())
  48. {reset()}
  49.  
  50. if (first())
  51. {
  52. CaliberS = Gun:acfNameShort():matchFirst("^%d+")
  53. Caliber = CaliberS:toNumber()
  54. print("Caliber:" + Caliber)
  55.  
  56. Grav = propGravity()
  57. SpeedLimit = speedLimit()
  58. HoloBurst = 10 # conservative holos per second
  59.  
  60. ## ACF constants
  61. DragDiv = 39.97 # thanks RedReaper!
  62. PBase = 1050 # 1 KG of propellant produces this much kinetic energy at the muzzle, in KJ
  63. MVScale = 0.5 # Propellant to muzzle vel conversion exponential
  64.  
  65. OptimalIters = 5 # initial optimal iteration count per calculation
  66. MaxIters = 30 # iteration limit in case someone pokes the gun outside the map
  67. LastIters = OptimalIters
  68. DT = 1 # Initial timestep of 1 second
  69.  
  70. function vector accel(X:vector, V:vector, DT) # thanks Tolyzor!
  71. {
  72. return Grav - (DragCoef * V * V:length() / DragDiv)
  73. }
  74.  
  75. function array rk4(State:array, DT) # thanks Tolyzor and doswa.com!
  76. {
  77. X1 = State[1, vector]
  78. V1 = State[2, vector]
  79. A1 = accel(X1, V1, 0)
  80.  
  81. X2 = X1 + 0.5*V1*DT
  82. V2 = V1 + 0.5*A1*DT
  83. A2 = accel(X2, V2, DT/2)
  84.  
  85. X3 = X1 + 0.5*V2*DT
  86. V3 = V1 + 0.5*A2*DT
  87. A3 = accel(X3, V3, DT/2)
  88.  
  89. X4 = X1 + V3*DT
  90. V4 = V1 + A3*DT
  91. A4 = accel(X4, V4, DT)
  92.  
  93. Xf = X1 + (DT/6.0)*(V1 + 2*V2 + 2*V3 + V4)
  94. Vf = V1 + (DT/6.0)*(A1 + 2*A2 + 2*A3 + A4)
  95.  
  96. return array(Xf, Vf)
  97. }
  98.  
  99.  
  100. function void runBody()
  101. {
  102. LastIters++
  103.  
  104. PosBefore = StateRK4[1, vector]
  105. StateRK4 = rk4(StateRK4, DT)
  106. Pos = StateRK4[1, vector]
  107. Vel = StateRK4[2, vector]
  108.  
  109. Time += DT
  110.  
  111. local Trace = rangerOffset(PosBefore, Pos)
  112. if (Trace:hit())
  113. {
  114. Pos = Trace:pos()
  115. EndPos = Pos
  116. Hit = 1
  117. }
  118.  
  119. if (DoHolos)
  120. {
  121. local Colour = hsv2rgb(120 * (Pos - PosBefore):length() / (MSMVel * DT), 1, 1)
  122. holoCreate(LastIters, Pos, vec(2), ang(), Colour)
  123. holoModel(LastIters, "sphere")
  124. holoMaterial(LastIters, "lights/white001")
  125. }
  126. if (LastIters >= (DoHolos ? 128 : MaxIters))
  127. {
  128. Hit = 1
  129. EndPos = StateRK4[1, vector]
  130. return
  131. }
  132. }
  133.  
  134. rangerPersist(1)
  135. }
  136.  
  137. if (~Solve & !Solve)
  138. {LastGunPos = randvec()*133337} # force recalculation
  139. if (~DoHolos)
  140. {LastGunPos = randvec()*133337, holoDeleteAll(), DT = 1}
  141.  
  142. if (Solve & Gun & (!Run | ~Correction | ~Gun)) {
  143.  
  144. local GunPos = Gun:attachmentPos("muzzle") # thanks Frankess!
  145. local GunDir = Gun:forward()
  146.  
  147. Tolerance = Tolerance ?: 1
  148. if (((GunPos - LastGunPos):length() > 5*Tolerance | (GunDir - LastGunDir):length() > 0.005*Tolerance | ~Correction & !Run) & Gun:acfAmmoType() != "Empty")
  149. {
  150. rangerFilter(Gun)
  151. # Assign physics environmment constants
  152. CaliberS = Gun:acfNameShort():matchFirst("^%d+")
  153. Caliber = CaliberS:toNumber()
  154.  
  155. Mass = Gun:acfProjectileMass()
  156.  
  157. FrontalArea = (3.1416 * (Caliber/20) ^ 2)
  158. DragCoef = FrontalArea/10000/Mass # linear coefficient of drag
  159.  
  160. MuzzleVel = Correction + Gun:acfMuzzleVel()#(PBase * Propellant * 2000/Mass) ^ MVScale
  161.  
  162. #print("Info " + Caliber + " " + Mass + " " + MuzzleVel)
  163.  
  164. MSMVel = MuzzleVel * 39.37
  165.  
  166. Time = Time ?: 5
  167. OptimalIters = ceil(Time * (Precision ?: 2)) # ~7 iterations at max map range
  168.  
  169. if (DoHolos)
  170. {DT = 0.25}
  171. elseif (LastIters != OptimalIters)
  172. {
  173. Ratio = LastIters / OptimalIters
  174. DT *= Ratio
  175. }
  176.  
  177. holoDeleteAll()
  178.  
  179. Time = DT
  180.  
  181. local GunVel = Gun:vel()
  182. Pos = GunPos #+ Gun:forward() * 50 #helps with movement
  183. Vel = GunDir * MuzzleVel * 39.37 + GunVel
  184.  
  185. StateRK4 = array(Pos, Vel)
  186.  
  187. Hit = 0
  188. Run = 1
  189.  
  190. LastIters = 0
  191. LastGunPos = GunPos
  192. LastGunDir = GunDir
  193. }
  194. else
  195. {interval((Interval ?: 0.334) * 1000)}
  196.  
  197. }
  198.  
  199. if (Run)
  200. {
  201. if (DoHolos & !Hit)
  202. {runBody()}
  203. else
  204. {
  205. while (perf() & !Hit)
  206. {runBody()}
  207. }
  208.  
  209. if (Hit)
  210. {
  211. Run = 0
  212. interval((Interval ?: 0.334) * 1000)
  213. }
  214. else
  215. {interval(DoHolos ? 1000/HoloBurst : 15)}
  216. }
Add Comment
Please, Sign In to add comment