Advertisement
Guest User

Missile Range Calculator

a guest
May 15th, 2018
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.87 KB | None | 0 0
  1. --[[
  2.     From the Depths Missile Range Calculator
  3.    
  4.     Based on:
  5.     Range Calculation by HerpeDerp      https://www.fromthedepthsgame.com/forum/showthread.php?tid=35722
  6.     Missile module Data from Wiki       https://fromthedepths.gamepedia.com/Missile#Missile_modules
  7.     A code example of how to traverse Lua Transceivers and Missiles from the Forum, I sadly can't find again.
  8.  
  9.     Requirements:
  10.     Launchers need a Lua Transceiver (one per Launcher-Group should be enough, no need to recalculate for the same missiles).
  11.     Missiles have to be launched and range is only calculated while flying. (Sounds stupid to calc instead of just waiting
  12.     and watching the result, but it beats firing the missiles manually and following them with a stopwatch)
  13.    
  14.     Warning:
  15.     This code has not been tested beyond the point of it printing data to the HUD, use at own risk!
  16.    
  17.     TODOs:
  18.     Missiles are drawn in the wrong order. (pretty useless feature anyways ;-)
  19.     Drag calculation might walk through missiles in the wrong order (more tests needed).
  20.     Data (drag) in missile_module_table might be outdated.
  21.     Keep showing calculated Data for some time after missiles are destroyed (already saved in missiles[]).
  22.     Option to calculate drag based on current height instead of hardcoded value.
  23.     Option to compare actual missile data to calculated values.
  24.     Check for possibility to get number of ejectors from game instead of hardcoding.
  25. --]]
  26.  
  27. -- BEGIN CONFIG AREA
  28.  
  29. -- height at which the missile will fly. The range will depend on this because the drag depends on the height.
  30. local height = 10;
  31.  
  32. -- draw Missile in addition to writing data to hud
  33. local draw_missile  = false;
  34.  
  35. -- Number of Ejectors attached to each Launchpad. Hardcoded since I have no idea how to find this in Lua.
  36. -- Actually helpful in case of using 4 ejectors, when one has to be removed for the Lua Transceiver.
  37. local numberOfEjectors = 2;
  38.  
  39. -- END CONFIG AREA
  40.  
  41.  
  42. -- Globals
  43. local API;
  44. local missiles = {};
  45.  
  46. local missile_module_table = {};
  47. missile_module_table["missile body"] =                        { name = "Body",                        drag = 0.01, icon = "[]", };
  48. missile_module_table["missile fins"] =                        { name = "Fins",                        drag = 0.05, icon = ">>", };
  49. missile_module_table["missile fuel tank"] =                   { name = "Fuel Tank",                     drag = 0.02, icon = "[O]", };
  50. missile_module_table["missile short range thruster"] =        { name = "Short Range Thruster",        drag = 0.02, icon = "+>", };
  51. missile_module_table["missile explosive warhead"] =           { name = "Explosive Warhead",             drag = 0.02, icon = "[X]", };
  52. missile_module_table["missile predicted"] =                   { name = "Target Prediction Guidance",    drag = 0.02, icon = "[tp]", };
  53. missile_module_table["missile APN"] =                         { name = "APN Guidance",                drag = 0.05, icon = "[ap]", };
  54. missile_module_table["missile IR seeker"] =                   { name = "Infra-Red Seeker",            drag = 0.05, icon = "[ir]", };
  55. missile_module_table["missile beam rider"] =                  { name = "Laser Beam Rider Receiver",     drag = 0.02, icon = "[br]", };
  56. missile_module_table["missile laser designator receiver"] =   { name = "Laser Designator Receiver",     drag = 0.05, icon = "[ls]", };
  57. missile_module_table["missile radar seeker"] =                { name = "Radar Seeker",                drag = 0.05, icon = "[rs]", };
  58. missile_module_table["missile proximity fuse"] =              { name = "Proximity Fuse",                drag = 0.05, icon = "[|]", };
  59. missile_module_table["missile fuse safety"] =                 { name = "Safety Fuse",                 drag = 0.02, icon = "[s]", };
  60. missile_module_table["missile one turn"] =                    { name = "One Turn",                    drag = 0.02, icon = "[^]", };
  61. missile_module_table["missile propeller"] =                   { name = "Torpedo Propeller",             drag = 0.02, icon = "[*]", };
  62. missile_module_table["missile sonar"] =                       { name = "Torpedo Sonar",                 drag = 0.05, icon = "[@]", };
  63. missile_module_table["missile magnet"] =                      { name = "Magnet",                        drag = 0.05, icon = "[U]", };
  64. missile_module_table["missile ballast"] =                     { name = "Ballast Tanks",                 drag = 0.02, icon = "[~]", };
  65. missile_module_table["missile regulator"] =                   { name = "Regulator",                     drag = 0.02, icon = "[+]", };
  66. missile_module_table["missile frag warhead"] =                { name = "Fragmentation Warhead",         drag = 0.02, icon = "[F]", };
  67. missile_module_table["missile camera"] =                      { name = "Camera",                        drag = 0.05, icon = "[o]", };
  68. missile_module_table["missile cable drum"] =                  { name = "Cable Drum",                    drag = 0.05, icon = "[/]", };
  69. missile_module_table["missile harpoon"] =                     { name = "Harpoon",                     drag = 0.02, icon = "[>>]", };
  70. missile_module_table["missile sticky flare"] =                { name = "Sticky Flare",                drag = 0.05, icon = "[f]", };
  71. missile_module_table["missile EMP warhead"] =                 { name = "EMP Warhead",                 drag = 0.02, icon = "[~]", };
  72. missile_module_table["missile simple IR seeker"] =            { name = "Single-Pixel IR Seeker",        drag = 0.00, icon = "[.]", };
  73. missile_module_table["missile interceptor"] =                 { name = "Missile Interceptor",         drag = 0.01, icon = "[i]", };
  74. missile_module_table["missile variable speed thruster"] =     { name = "Variable Thruster",             drag = 0.02, icon = "~>", };
  75. missile_module_table["missile thumper head"] =                { name = "Thumper Head",                drag = 0.00, icon = "}", };
  76. missile_module_table["missile lua receiver"] =                { name = "LUA Receiver",                drag = 0.01, icon = "[#]", };
  77. missile_module_table["missile radar buoy"] =                  { name = "radar buoy",                    drag = 0.02, icon = "(r)", };
  78. missile_module_table["missile sonar buoy"] =                  { name = "sonar buoy",                    drag = 0.02, icon = "(s)", };
  79.  
  80.  
  81. -- MAIN
  82. function Update(I)
  83.   API = I;
  84.   API:ClearLogs();
  85.   local message = "";
  86.   for pad = 0, API:GetLuaTransceiverCount()-1 do
  87.       for msl = 0, API:GetLuaControlledMissileCount(pad)-1 do
  88.           local missile_structure = API:GetMissileInfo(pad, msl);
  89.           local id = API:GetLuaControlledMissileInfo(pad, msl);
  90.           local text = "";
  91.           local missile = missiles[id];
  92.           if missile == nil or missile["text"] == nil then
  93.             text = GetMissileText(id, missile_structure);
  94.           else
  95.             text = missile["text"];
  96.           end
  97.           message = message .. text .. "\n";
  98.       end
  99.   end
  100.   Print(message);
  101. end
  102.  
  103.  
  104. function GetMissileText(id, missile_structure)
  105.   local Parts = missile_structure.Parts;
  106.   local text = "";
  107.   local Data = {
  108.     length = 0,
  109.     initialSpeed = numberOfEjectors * 70,
  110.     displayedThrust = 0,
  111.     thrust = 0,
  112.     drag = 0.1,
  113.     dragCoefficient = 0,
  114.     fuelTime = 0,
  115.     regulatorTime = 0,
  116.     effectiveTime = 0,
  117.     flightDistance = 0,
  118.     mass = 0,
  119.   };
  120.  
  121.   for _,Part in pairs(Parts) do
  122.     local name = Part.Name;
  123.     API:Log("Part: " .. name);
  124.     Data.length = Data.length + 1;
  125.     Data.mass = Data.mass + 0.1;
  126.     local module_data = missile_module_table[name];
  127.     Data.drag = Data.drag + module_data["drag"] / Data.length;
  128.    
  129.     if name == "missile thumper head" then
  130.       Data.mass = Data.mass + 0.2;
  131.     elseif name == "missile short range thruster" then
  132.       Data.displayedThrust = Data.displayedThrust + 1000;
  133.       Data.initialSpeed = Data.initialSpeed + 15;
  134.     elseif name == "missile variable speed thruster" then
  135.       Data.displayedThrust = Data.displayedThrust + Part.Registers[2];
  136.       Data.initialSpeed = Data.initialSpeed + 15;
  137.     elseif name == "missile torpedo propeller" then
  138.       Data.displayedThrust = Data.displayedThrust + 500;
  139.       Data.initialSpeed = Data.initialSpeed + 50;
  140.     elseif name == "missile fuel tank" then
  141.       Data.fuelTime = Data.fuelTime + 5000;
  142.     elseif name == "missile regulator" then
  143.       Data.regulatorTime  = Data.regulatorTime + 180;
  144.     end
  145.    
  146.     if draw_missile then
  147.       text = text .. DrawPart(Part);
  148.     end
  149.   end
  150.  
  151.   Data.dragCoefficient = Data.drag / 100
  152.   Data.thrust = Data.displayedThrust / 40;
  153.   Data.initialSpeed = Data.initialSpeed + 0.75 / Data.mass;
  154.   Data.fuelTime = Data.fuelTime / Data.displayedThrust;
  155.   Data.regulatorTime  = Data.regulatorTime + 60; -- was 30 for some reason
  156.   Data.effectiveTime = math.min(Data.fuelTime, Data.regulatorTime);
  157.  
  158.   Data.flightDistance = getDistanceAfterTime(Data, Data.effectiveTime, height);
  159.  
  160.   if draw_missile then
  161.     text = text .. "\n";
  162.   end
  163.   text = text .. "Range: " .. Data.flightDistance .. "m; TTL: " .. Data.effectiveTime .. "s.\n";
  164.  
  165.   for k,v in pairs(Data) do
  166.     API:Log(k .. " " .. v);
  167.   end
  168.  
  169.   local missile = {};
  170.   missile["data"] = Data;
  171.   missile["text"] = text;
  172.   missiles[id] = missile;
  173.   return text;
  174. end
  175.  
  176.  
  177. function DrawPart(Part)
  178.     local name = Part.Name;
  179.     local mod = missile_module_table[name];
  180.     if mod ~= nil then
  181.       return mod["icon"] .. " ";
  182.     else
  183.       return name .. ", ";
  184.     end
  185. end
  186.  
  187.  
  188. function Print(message)
  189.     API:LogToHud(message);
  190.     API:LogToHud(" ");
  191.     API:LogToHud("  ");
  192.     API:LogToHud("   ");
  193.     API:LogToHud("    ");
  194.     API:LogToHud("     ");
  195. end
  196.  
  197.  
  198. function getDistanceAfterTime(m, totalFlightTime, height)
  199.   local distanceTraveled = 0;
  200.   local velocityMagnitude = 0;
  201.   local timeStep = 0.025
  202.   local time = 0
  203.   while time < totalFlightTime do
  204.     local accelerationMagnitude = getAcceleration(m, height, velocityMagnitude, timeStep)
  205.     velocityMagnitude = velocityMagnitude + accelerationMagnitude * timeStep
  206.     distanceTraveled = distanceTraveled + velocityMagnitude * timeStep
  207.     time = time + timeStep
  208.   end
  209.   return distanceTraveled;
  210. end
  211.  
  212.  
  213. function getAcceleration(m, height, speed, timeStep)
  214.   local newSpeed = speed + getThrustAccelerationMagnitude(m) * timeStep;
  215.   return getThrustAccelerationMagnitude(m) - getDragAccelerationMagnitude(m, height, speed, newSpeed)
  216. end
  217.  
  218.  
  219. function getDragAccelerationMagnitude(m, height, speed, newSpeed)
  220.   local airDensity = getAirDensityAtAltitude(height)
  221.   local dragMagnitudePerVelocity = math.max(0.1, airDensity * speed * m.dragCoefficient)
  222.   local dragMagnitude = dragMagnitudePerVelocity * newSpeed
  223.   return dragMagnitude
  224. end
  225.  
  226.  
  227. function getThrustAccelerationMagnitude(m)
  228.   return m.thrust / m.mass
  229. end
  230.  
  231.  
  232. function getAirDensityAtAltitude(altitude)
  233.   if altitude < 0 then
  234.     return 7
  235.   elseif altitude < 275 then
  236.     return 1 - altitude / 550
  237.   else
  238.     return 0.5 * math.pow(0.01, (altitude - 275) / (1200 - 275));
  239.   end
  240. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement