Advertisement
klassekatze

SE SpeedMatch WeaponCore

Apr 26th, 2022 (edited)
1,819
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 24.38 KB | None | 0 0
  1.  
  2.  
  3. /*
  4.          * Same idea and thrust logic code from Whip's Speed Matcher Script https://steamcommunity.com/sharedfiles/filedetails/?id=1109204252
  5.          * Adapted for straightforward use with WeaponCore rather than camera raycasts.
  6.          *
  7.          * This program does thrust overrides. It does not turn thrusters on/off.
  8.          * Player WASD/whatever control is *not* blocked, Whip's logic accounts for it, so you can adjust your position freely with your controls while otherwise dampening to match your target.
  9.          *
  10.          * COMMAND ARGUMENTS ARE AS FOLLOWS:
  11.         matchclosest
  12.             Will speed dampen relative to the closest entity detected by weaponcore weapon(s). This will generally need to be an enemy, or at least owned by somebody else.
  13.         matchfocus
  14.             Will speed dampen relative to the entity being explicitly targeted by your ship, as in has a big reticle and you're getting stats on it on top of the screen.
  15.  
  16.         STATE LIGHTING
  17.  
  18.         Light blocks in the block group named "indicators" will turn blue when there is an active speed match, and green when normal behavior is in effect.
  19.  
  20.         CUSTOMDATA OPTION:
  21.  
  22.         automatchfocus
  23.             If automatchfocus is in the CustomData of the program block, then any time you focus a ship in WeaponCore, it will automatically trigger the same logic as matchfocus.
  24.             This may be undesirable if you use thruster overrides as part of your general or combat routine. OTOH, if you don't and are lazy, there ya go, it 'just works' without using a toolbar slot.
  25.          */
  26.  
  27. public Program()
  28. {
  29.     chkInitializations();
  30.     toggleMatchSpeed();
  31.     toggleMatchSpeed();
  32. }
  33.  
  34. public WcPbApi modAPIWeaponCore = null;
  35. public bool modAPIWeaponCoreReady = false;
  36.  
  37. public List<IMyShipController> controllers = new List<IMyShipController>();
  38. public List<IMyThrust> thrusters = new List<IMyThrust>();
  39.  
  40. public List<IMyLightingBlock> indicators = new List<IMyLightingBlock>();
  41.  
  42. public void setlight(Color c)
  43. {
  44.     foreach(IMyLightingBlock b in indicators)
  45.     {
  46.         b.Color = c;
  47.     }
  48. }
  49.  
  50. public bool autoMatchFocus = false;
  51.  
  52. public void loadBlocks()
  53. {
  54.     if (!modAPIWeaponCoreReady) return;
  55.  
  56.     controllers.Clear();
  57.     GridTerminalSystem.GetBlocksOfType<IMyShipController>(controllers, b => b.CubeGrid == Me.CubeGrid);
  58.  
  59.     thrusters.Clear();
  60.     GridTerminalSystem.GetBlocksOfType<IMyThrust>(thrusters, b => b.CubeGrid == Me.CubeGrid);
  61.  
  62.     IMyBlockGroup ind = GridTerminalSystem.GetBlockGroupWithName("indicators");
  63.     if(ind != null)
  64.     {
  65.         ind.GetBlocksOfType<IMyLightingBlock>(indicators);
  66.     }
  67.  
  68.  
  69.     if (Me.CustomData.Contains("automatchfocus")) autoMatchFocus = true;
  70.     else autoMatchFocus = false;
  71. }
  72.  
  73. DateTime apiCheckCode = DateTime.MinValue;
  74.  
  75. DateTime blockCheck = DateTime.MinValue;
  76.  
  77. public bool matchingSpeed = false;
  78.  
  79.  
  80. class TargetData
  81. {
  82.     public long EntityId;
  83.     public string Name;
  84.     public Vector3D Position;
  85.     public Vector3D Velocity;
  86.     public TargetData() { }
  87.     public TargetData(MyDetectedEntityInfo i)
  88.     {
  89.         setFromDetected(i);
  90.     }
  91.     public void setFromDetected(MyDetectedEntityInfo i)
  92.     {
  93.         EntityId = i.EntityId;
  94.         Name = i.Name;
  95.         Position = i.Position;
  96.         Velocity = i.Velocity;
  97.     }
  98. }
  99. TargetData matchTarget = null;
  100.  
  101.  
  102.  
  103. public IMyShipController getShipController()
  104. {
  105.     foreach (IMyShipController c in controllers)
  106.     {
  107.         if (c.IsMainCockpit && c.CanControlShip) return c;
  108.     }
  109.     foreach (IMyShipController c in controllers)
  110.     {
  111.         if (c.IsMainCockpit) return c;
  112.     }
  113.     foreach (IMyShipController c in controllers)
  114.     {
  115.         if (c.CanControlShip) return c;
  116.     }
  117.     return controllers.Count > 0 ? controllers[0] : null;
  118. }
  119. void toggleMatchSpeed()
  120. {
  121.     matchingSpeed = !matchingSpeed;
  122.     if (matchingSpeed)
  123.     {
  124.         Runtime.UpdateFrequency = UpdateFrequency.Update1;
  125.         setlight(Color.Blue);
  126.     }
  127.     else
  128.     {
  129.         Runtime.UpdateFrequency = UpdateFrequency.Update10;
  130.         matchTarget = null;
  131.         setlight(Color.Green);
  132.         foreach (var thisThrust in thrusters)
  133.         {
  134.             thisThrust.ThrustOverridePercentage = 0;
  135.         }
  136.     }
  137. }
  138.  
  139. public static bool hasTimeElapsedSet(ref DateTime last, int seconds)
  140. {
  141.     var now = DateTime.Now;
  142.     if ((now - last).TotalSeconds > seconds)
  143.     {
  144.         last = now;
  145.         return true;
  146.     }
  147.     return false;
  148. }
  149.  
  150. public void chkInitializations()
  151. {
  152.  
  153.     if (hasTimeElapsedSet(ref blockCheck, 25))
  154.     {
  155.         loadBlocks();
  156.     }
  157.  
  158.     if (hasTimeElapsedSet(ref apiCheckCode, 5))
  159.     {
  160.         if (modAPIWeaponCore == null) try { modAPIWeaponCore = new WcPbApi(); } catch (Exception) { }
  161.         if (modAPIWeaponCore != null && !modAPIWeaponCoreReady)
  162.         {
  163.             try
  164.             {
  165.                 if (modAPIWeaponCore.Activate(Me))
  166.                 {
  167.                     modAPIWeaponCoreReady = true;
  168.                     blockCheck = new DateTime();
  169.                     loadBlocks();
  170.                 }
  171.             }
  172.             catch (Exception) { }
  173.         }
  174.     }
  175.     if (!modAPIWeaponCoreReady) return;
  176.  
  177.  
  178. }
  179. public void Main(string argument, UpdateType updateSource)
  180. {
  181.     chkInitializations();
  182.  
  183.     if (argument.StartsWith("match"))
  184.     {
  185.         toggleMatchSpeed();
  186.         if (matchingSpeed)
  187.         {
  188.             if (argument == "matchclosest")
  189.             {
  190.                 Dictionary<MyDetectedEntityInfo, float> threatList = new Dictionary<MyDetectedEntityInfo, float>();
  191.                 modAPIWeaponCore.GetSortedThreats(Me, threatList);
  192.                 List<KeyValuePair<MyDetectedEntityInfo, float>> tmpa = new List<KeyValuePair<MyDetectedEntityInfo, float>>();
  193.                 foreach (KeyValuePair<MyDetectedEntityInfo, float> kvp in threatList) tmpa.Add(kvp);
  194.  
  195.  
  196.                 if (tmpa.Count > 0)
  197.                 {
  198.                     matchTarget = new TargetData(tmpa[0].Key);
  199.                 }
  200.                 else toggleMatchSpeed();
  201.  
  202.             }
  203.             if (argument == "matchfocus")
  204.             {
  205.                 MyDetectedEntityInfo? focus = modAPIWeaponCore.GetAiFocus(Me.CubeGrid.EntityId);
  206.                 if (focus.HasValue && !focus.Value.IsEmpty())
  207.                 {
  208.                     matchTarget = new TargetData(focus.Value);
  209.                 }
  210.                 else toggleMatchSpeed();
  211.             }
  212.         }
  213.         else matchTarget = null;
  214.     }
  215.     if (updateSource == UpdateType.Update1 || updateSource == UpdateType.Update10)
  216.     {
  217.         if (!matchingSpeed && autoMatchFocus)
  218.         {
  219.             MyDetectedEntityInfo? focus = modAPIWeaponCore.GetAiFocus(Me.CubeGrid.EntityId);
  220.             if (focus.HasValue && !focus.Value.IsEmpty())
  221.             {
  222.                 toggleMatchSpeed();
  223.                 matchTarget = new TargetData(focus.Value);
  224.             }
  225.         }
  226.  
  227.         if (matchingSpeed)
  228.         {
  229.             Dictionary<MyDetectedEntityInfo, float> threatList = new Dictionary<MyDetectedEntityInfo, float>();
  230.             modAPIWeaponCore.GetSortedThreats(Me, threatList);
  231.             List<KeyValuePair<MyDetectedEntityInfo, float>> tmpa = new List<KeyValuePair<MyDetectedEntityInfo, float>>();
  232.             bool canTrack = false;
  233.             MyDetectedEntityInfo? focus = modAPIWeaponCore.GetAiFocus(Me.CubeGrid.EntityId);
  234.  
  235.             if (focus.HasValue && focus.Value.EntityId == matchTarget.EntityId)
  236.             {
  237.                 matchTarget.setFromDetected(focus.Value);
  238.                 //matchTarget = focus.Value;
  239.                 canTrack = true;
  240.             }
  241.             if (!canTrack)
  242.             {
  243.                 foreach (KeyValuePair<MyDetectedEntityInfo, float> kvp in threatList)
  244.                 {
  245.                     if (kvp.Key.EntityId == matchTarget.EntityId)
  246.                     {
  247.                         matchTarget.setFromDetected(kvp.Key);
  248.                         canTrack = true;
  249.                         break;
  250.                     }
  251.                 }
  252.             }
  253.  
  254.             if (!canTrack || matchTarget == null)
  255.             {
  256.                 toggleMatchSpeed();
  257.             }else
  258.             {
  259.                 targetVelocityVec = matchTarget.Velocity;
  260.             }
  261.         }
  262.     }
  263.  
  264.     if (matchingSpeed)
  265.     {
  266.         Echo("m: " + matchTarget.Name);
  267.  
  268.         //Vector3D targetVelocityVec
  269.  
  270.         var myVelocityVec = getShipController().GetShipVelocities().LinearVelocity;
  271.         Echo("mv: " + myVelocityVec.X.ToString("0.0") + "," + myVelocityVec.Y.ToString("0.0")+","+ myVelocityVec.Z.ToString("0.0"));
  272.         Echo("tv: " + targetVelocityVec.X.ToString("0.0") + "," + targetVelocityVec.Y.ToString("0.0") + "," + targetVelocityVec.Z.ToString("0.0"));
  273.         SpeedMatcher();
  274.     }
  275.     else Echo("not match");
  276.  
  277.     Echo("\nautoMatchFocus=" + autoMatchFocus);
  278. }
  279.  
  280.  
  281. //taken mostly wholesale from https://github.com/Whiplash141/SpaceEngineersScripts/blob/master/Released/speed_matcher.cs
  282. Vector3D targetVelocityVec = new Vector3D(0, 0, 0);
  283. void SpeedMatcher()
  284. {
  285.     /*if (!shouldMatch)
  286.             {
  287.                 foreach (var thisThrust in allThrust)
  288.                 {
  289.                     SetThrusterOverride(thisThrust, 0f);
  290.                 }
  291.                 return;
  292.             }*/
  293.  
  294.     var thisController = getShipController();// GetControlledShipController(allShipControllers);
  295.     var myVelocityVec = thisController.GetShipVelocities().LinearVelocity;
  296.     var inputVec = thisController.MoveIndicator;
  297.     var desiredDirectionVec = Vector3D.TransformNormal(inputVec, thisController.WorldMatrix); //world relative input vector
  298.     var relativeVelocity = myVelocityVec - targetVelocityVec;
  299.  
  300.     //if (!shouldScan) //if the scan is finished
  301.     //thisController.DampenersOverride = false;
  302.  
  303.     ApplyThrust(thrusters, relativeVelocity, desiredDirectionVec, thisController);
  304. }
  305.  
  306. void ApplyThrust(List<IMyThrust> thrusters, Vector3D travelVec, Vector3D desiredDirectionVec, IMyShipController thisController)
  307. {
  308.     var mass = thisController.CalculateShipMass().PhysicalMass;
  309.     var gravity = thisController.GetNaturalGravity();
  310.  
  311.     var desiredThrust = mass * (2 * travelVec + gravity);
  312.     var thrustToApply = desiredThrust;
  313.     if (!Vector3D.IsZero(desiredDirectionVec))
  314.     {
  315.         thrustToApply = VectorRejection(desiredThrust, desiredDirectionVec);
  316.     }
  317.  
  318.     //convert desired thrust vector to local
  319.     //thrustToApply = Vector3D.TransformNormal(thrustToApply, MatrixD.Transpose(thisController.WorldMatrix));
  320.  
  321.     foreach (IMyThrust thisThrust in thrusters)
  322.     {
  323.         if (Vector3D.Dot(thisThrust.WorldMatrix.Backward, desiredDirectionVec) > .7071) //thrusting in desired direction
  324.         {
  325.             thisThrust.ThrustOverridePercentage = 1f;
  326.         }
  327.         else if (Vector3D.Dot(thisThrust.WorldMatrix.Forward, thrustToApply) > 0 && thisController.DampenersOverride)
  328.         {
  329.             var neededThrust = Vector3D.Dot(thrustToApply, thisThrust.WorldMatrix.Forward);
  330.             var outputProportion = MathHelper.Clamp(neededThrust / thisThrust.MaxEffectiveThrust, 0, 1);
  331.             thisThrust.ThrustOverridePercentage = (float)outputProportion;
  332.             thrustToApply -= thisThrust.WorldMatrix.Forward * outputProportion * thisThrust.MaxEffectiveThrust;
  333.         }
  334.         else
  335.         {
  336.             thisThrust.ThrustOverridePercentage = 0.000001f;
  337.         }
  338.     }
  339. }
  340.  
  341. public Vector3D VectorRejection(Vector3D a, Vector3D b) //reject a on b
  342. {
  343.     if (Vector3D.IsZero(b))
  344.         return Vector3D.Zero;
  345.  
  346.     return a - a.Dot(b) / b.LengthSquared() * b;
  347. }
  348.  
  349. }
  350. public class Utility
  351. {
  352.  
  353.  
  354.     /// <summary>
  355.         /// if seconds since last, replace last with now and return true
  356.         /// </summary>
  357.  
  358.  
  359. }
  360.  
  361. public class MD5
  362. {
  363.     /*
  364.          * Round shift values
  365.          */
  366.     static int[] s = new int[64] {
  367.         7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,
  368.         5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,
  369.         4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,
  370.         6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21
  371.     };
  372.  
  373.     /*
  374.          * Constant K Values
  375.          */
  376.     static uint[] K = new uint[64] {
  377.         0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
  378.         0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
  379.         0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
  380.         0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
  381.         0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
  382.         0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
  383.         0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
  384.         0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
  385.         0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
  386.         0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
  387.         0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
  388.         0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
  389.         0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
  390.         0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
  391.         0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
  392.         0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
  393.     };
  394.  
  395.     public static uint leftRotate(uint x, int c)
  396.     {
  397.         return (x << c) | (x >> (32 - c));
  398.     }
  399.  
  400.     // assumes whole bytes as input
  401.     public static string Calculate(byte[] input)
  402.     {
  403.         uint a0 = 0x67452301;   // A
  404.         uint b0 = 0xefcdab89;   // B
  405.         uint c0 = 0x98badcfe;   // C
  406.         uint d0 = 0x10325476;   // D
  407.  
  408.         var addLength = (56 - ((input.Length + 1) % 64)) % 64; // calculate the new length with padding
  409.         var processedInput = new byte[input.Length + 1 + addLength + 8];
  410.         Array.Copy(input, processedInput, input.Length);
  411.         processedInput[input.Length] = 0x80; // add 1
  412.  
  413.         byte[] length = BitConverter.GetBytes(input.Length * 8); // bit converter returns little-endian
  414.         Array.Copy(length, 0, processedInput, processedInput.Length - 8, 4); // add length in bits
  415.  
  416.         for (int i = 0; i < processedInput.Length / 64; ++i)
  417.         {
  418.             // copy the input to M
  419.             uint[] M = new uint[16];
  420.             for (int j = 0; j < 16; ++j)
  421.                 M[j] = BitConverter.ToUInt32(processedInput, (i * 64) + (j * 4));
  422.  
  423.             // initialize round variables
  424.             uint A = a0, B = b0, C = c0, D = d0, F = 0, g = 0;
  425.  
  426.             // primary loop
  427.             for (uint k = 0; k < 64; ++k)
  428.             {
  429.                 if (k <= 15)
  430.                 {
  431.                     F = (B & C) | (~B & D);
  432.                     g = k;
  433.                 }
  434.                 else if (k >= 16 && k <= 31)
  435.                 {
  436.                     F = (D & B) | (~D & C);
  437.                     g = ((5 * k) + 1) % 16;
  438.                 }
  439.                 else if (k >= 32 && k <= 47)
  440.                 {
  441.                     F = B ^ C ^ D;
  442.                     g = ((3 * k) + 5) % 16;
  443.                 }
  444.                 else if (k >= 48)
  445.                 {
  446.                     F = C ^ (B | ~D);
  447.                     g = (7 * k) % 16;
  448.                 }
  449.  
  450.                 var dtemp = D;
  451.                 D = C;
  452.                 C = B;
  453.                 B = B + leftRotate((A + F + K[k] + M[g]), s[k]);
  454.                 A = dtemp;
  455.             }
  456.  
  457.             a0 += A;
  458.             b0 += B;
  459.             c0 += C;
  460.             d0 += D;
  461.         }
  462.  
  463.         return GetByteString(a0) + GetByteString(b0) + GetByteString(c0) + GetByteString(d0);
  464.     }
  465.  
  466.     private static string GetByteString(uint x)
  467.     {
  468.         return String.Join("", BitConverter.GetBytes(x).Select(y => y.ToString("x2")));
  469.     }
  470. }
  471.  
  472. class UtilitySpatial
  473. {
  474.  
  475. }
  476.  
  477.  
  478. public class WcPbApi
  479. {
  480.     private Action<IMyTerminalBlock, IDictionary<MyDetectedEntityInfo, float>> _getSortedThreats;
  481.     private Func<long, bool> _hasGridAi;
  482.     //private Func<Sandbox.ModAPI.Ingame.IMyTerminalBlock, long, int, Vector3D?> _getPredictedTargetPos;
  483.     //private Func<Sandbox.ModAPI.Ingame.IMyTerminalBlock, int, Sandbox.ModAPI.Ingame.MyDetectedEntityInfo> _getWeaponTarget;
  484.     //private Action<ICollection<MyDefinitionId>> _getCoreTurrets;
  485.     private Func<long, int, Sandbox.ModAPI.Ingame.MyDetectedEntityInfo> _getAiFocus;
  486.     private Func<Sandbox.ModAPI.Ingame.IMyTerminalBlock, long, int, bool> _setAiFocus;
  487.     private Action<Sandbox.ModAPI.Ingame.IMyTerminalBlock, bool, bool, int> _toggleWeaponFire;
  488.     private Func<Sandbox.ModAPI.Ingame.IMyTerminalBlock, bool> _hasCoreWeapon;
  489.     //private Action<Sandbox.ModAPI.Ingame.IMyTerminalBlock, ICollection<Sandbox.ModAPI.Ingame.MyDetectedEntityInfo>> _getObstructions;
  490.     private Func<Sandbox.ModAPI.Ingame.IMyTerminalBlock, ICollection<string>, int, bool> _getTurretTargetTypes;
  491.     private Action<Sandbox.ModAPI.Ingame.IMyTerminalBlock, ICollection<string>, int> _setTurretTargetTypes;
  492.     private Func<Sandbox.ModAPI.Ingame.IMyTerminalBlock, long, int, Vector3D?> _getPredictedTargetPos;
  493.  
  494.     private Func<Sandbox.ModAPI.Ingame.IMyTerminalBlock, int, Matrix> _getWeaponAzimuthMatrix;
  495.     private Func<Sandbox.ModAPI.Ingame.IMyTerminalBlock, int, Matrix> _getWeaponElevationMatrix;
  496.     private Func<Sandbox.ModAPI.Ingame.IMyTerminalBlock, long, int, MyTuple<bool, Vector3D?>> _isTargetAlignedExtended;
  497.     private Func<Sandbox.ModAPI.Ingame.IMyTerminalBlock, int, string> _getActiveAmmo;
  498.     private Action<Sandbox.ModAPI.Ingame.IMyTerminalBlock, int, string> _setActiveAmmo;
  499.     private Func<long, float> _getConstructEffectiveDps;
  500.     private Func<Sandbox.ModAPI.Ingame.IMyTerminalBlock, int, Sandbox.ModAPI.Ingame.MyDetectedEntityInfo> _getWeaponTarget;
  501.     private Action<Sandbox.ModAPI.Ingame.IMyTerminalBlock, long, int> _setWeaponTarget;
  502.  
  503.     private Action<Sandbox.ModAPI.Ingame.IMyTerminalBlock, int, Action<long, int, ulong, long, Vector3D, bool>> _monitorProjectile;
  504.     private Action<Sandbox.ModAPI.Ingame.IMyTerminalBlock, int, Action<long, int, ulong, long, Vector3D, bool>> _unMonitorProjectile;
  505.     private Func<ulong, MyTuple<Vector3D, Vector3D, float, float, long, string>> _getProjectileState;
  506.  
  507.     public bool Activate(IMyTerminalBlock pbBlock)
  508.     {
  509.         var dict = pbBlock.GetProperty("WcPbAPI")?.As<IReadOnlyDictionary<string, Delegate>>().GetValue(pbBlock);
  510.         if (dict == null) throw new Exception("WcPbAPI failed to activate");
  511.         return ApiAssign(dict);
  512.     }
  513.  
  514.     public bool ApiAssign(IReadOnlyDictionary<string, Delegate> delegates)
  515.     {
  516.         if (delegates == null)
  517.             return false;
  518.         AssignMethod(delegates, "GetSortedThreats", ref _getSortedThreats);
  519.         AssignMethod(delegates, "HasGridAi", ref _hasGridAi);
  520.         AssignMethod(delegates, "GetAiFocus", ref _getAiFocus);
  521.         AssignMethod(delegates, "SetAiFocus", ref _setAiFocus);
  522.         AssignMethod(delegates, "ToggleWeaponFire", ref _toggleWeaponFire);
  523.         AssignMethod(delegates, "HasCoreWeapon", ref _hasCoreWeapon);
  524.         AssignMethod(delegates, "GetPredictedTargetPosition", ref _getPredictedTargetPos);
  525.         AssignMethod(delegates, "GetTurretTargetTypes", ref _getTurretTargetTypes);
  526.         AssignMethod(delegates, "SetTurretTargetTypes", ref _setTurretTargetTypes);
  527.         AssignMethod(delegates, "GetWeaponAzimuthMatrix", ref _getWeaponAzimuthMatrix);
  528.         AssignMethod(delegates, "GetWeaponElevationMatrix", ref _getWeaponElevationMatrix);
  529.         AssignMethod(delegates, "IsTargetAlignedExtended", ref _isTargetAlignedExtended);
  530.         AssignMethod(delegates, "GetActiveAmmo", ref _getActiveAmmo);
  531.         AssignMethod(delegates, "SetActiveAmmo", ref _setActiveAmmo);
  532.         AssignMethod(delegates, "GetConstructEffectiveDps", ref _getConstructEffectiveDps);
  533.         AssignMethod(delegates, "GetWeaponTarget", ref _getWeaponTarget);
  534.         AssignMethod(delegates, "SetWeaponTarget", ref _setWeaponTarget);
  535.         AssignMethod(delegates, "MonitorProjectile", ref _monitorProjectile);
  536.         AssignMethod(delegates, "UnMonitorProjectile", ref _unMonitorProjectile);
  537.         AssignMethod(delegates, "GetProjectileState", ref _getProjectileState);
  538.  
  539.         return true;
  540.     }
  541.     private void AssignMethod<T>(IReadOnlyDictionary<string, Delegate> delegates, string name, ref T field) where T : class
  542.     {
  543.         if (delegates == null)
  544.         {
  545.             field = null;
  546.             return;
  547.         }
  548.         Delegate del;
  549.         if (!delegates.TryGetValue(name, out del))
  550.             throw new Exception($"{GetType().Name} :: Couldn't find {name} delegate of type {typeof(T)}");
  551.         field = del as T;
  552.         if (field == null)
  553.             throw new Exception(
  554.                 $"{GetType().Name} :: Delegate {name} is not type {typeof(T)}, instead it's: {del.GetType()}");
  555.     }
  556.     public void GetSortedThreats(IMyTerminalBlock pbBlock, IDictionary<MyDetectedEntityInfo, float> collection) =>
  557.         _getSortedThreats?.Invoke(pbBlock, collection);
  558.     public bool HasGridAi(long entity) => _hasGridAi?.Invoke(entity) ?? false;
  559.     //public Vector3D? GetPredictedTargetPosition(Sandbox.ModAPI.Ingame.IMyTerminalBlock weapon, long targetEnt, int weaponId) =>_getPredictedTargetPos?.Invoke(weapon, targetEnt, weaponId) ?? null;
  560.     // public MyDetectedEntityInfo? GetWeaponTarget(Sandbox.ModAPI.Ingame.IMyTerminalBlock weapon, int weaponId = 0) => _getWeaponTarget?.Invoke(weapon, weaponId);
  561.     //public void GetAllCoreTurrets(ICollection<MyDefinitionId> collection) => _getCoreTurrets?.Invoke(collection);
  562.     public MyDetectedEntityInfo? GetAiFocus(long shooter, int priority = 0) => _getAiFocus?.Invoke(shooter, priority);
  563.  
  564.     public bool SetAiFocus(Sandbox.ModAPI.Ingame.IMyTerminalBlock pBlock, long target, int priority = 0) =>
  565.         _setAiFocus?.Invoke(pBlock, target, priority) ?? false;
  566.  
  567.     public void ToggleWeaponFire(Sandbox.ModAPI.Ingame.IMyTerminalBlock weapon, bool on, bool allWeapons, int weaponId = 0) =>
  568.         _toggleWeaponFire?.Invoke(weapon, on, allWeapons, weaponId);
  569.     public bool HasCoreWeapon(Sandbox.ModAPI.Ingame.IMyTerminalBlock weapon) => _hasCoreWeapon?.Invoke(weapon) ?? false;
  570.  
  571.     //public void GetObstructions(Sandbox.ModAPI.Ingame.IMyTerminalBlock pBlock, ICollection<Sandbox.ModAPI.Ingame.MyDetectedEntityInfo> collection) =>
  572.     //   _getObstructions?.Invoke(pBlock, collection);
  573.  
  574.     public Vector3D? GetPredictedTargetPosition(Sandbox.ModAPI.Ingame.IMyTerminalBlock weapon, long targetEnt, int weaponId) =>
  575.         _getPredictedTargetPos?.Invoke(weapon, targetEnt, weaponId) ?? null;
  576.  
  577.     public Matrix GetWeaponAzimuthMatrix(Sandbox.ModAPI.Ingame.IMyTerminalBlock weapon, int weaponId) =>
  578.         _getWeaponAzimuthMatrix?.Invoke(weapon, weaponId) ?? Matrix.Zero;
  579.  
  580.     public Matrix GetWeaponElevationMatrix(Sandbox.ModAPI.Ingame.IMyTerminalBlock weapon, int weaponId) =>
  581.         _getWeaponElevationMatrix?.Invoke(weapon, weaponId) ?? Matrix.Zero;
  582.  
  583.     public MyTuple<bool, Vector3D?> IsTargetAlignedExtended(Sandbox.ModAPI.Ingame.IMyTerminalBlock weapon, long targetEnt, int weaponId) =>
  584.         _isTargetAlignedExtended?.Invoke(weapon, targetEnt, weaponId) ?? new MyTuple<bool, Vector3D?>();
  585.     public string GetActiveAmmo(Sandbox.ModAPI.Ingame.IMyTerminalBlock weapon, int weaponId) =>
  586.         _getActiveAmmo?.Invoke(weapon, weaponId) ?? null;
  587.  
  588.     public void SetActiveAmmo(Sandbox.ModAPI.Ingame.IMyTerminalBlock weapon, int weaponId, string ammoType) =>
  589.         _setActiveAmmo?.Invoke(weapon, weaponId, ammoType);
  590.  
  591.     public float GetConstructEffectiveDps(long entity) => _getConstructEffectiveDps?.Invoke(entity) ?? 0f;
  592.  
  593.     public MyDetectedEntityInfo? GetWeaponTarget(Sandbox.ModAPI.Ingame.IMyTerminalBlock weapon, int weaponId = 0) =>
  594.         _getWeaponTarget?.Invoke(weapon, weaponId);
  595.  
  596.     public void SetWeaponTarget(Sandbox.ModAPI.Ingame.IMyTerminalBlock weapon, long target, int weaponId = 0) =>
  597.         _setWeaponTarget?.Invoke(weapon, target, weaponId);
  598.  
  599.     public void MonitorProjectileCallback(Sandbox.ModAPI.Ingame.IMyTerminalBlock weapon, int weaponId, Action<long, int, ulong, long, Vector3D, bool> action) =>
  600.         _monitorProjectile?.Invoke(weapon, weaponId, action);
  601.  
  602.     public void UnMonitorProjectileCallback(Sandbox.ModAPI.Ingame.IMyTerminalBlock weapon, int weaponId, Action<long, int, ulong, long, Vector3D, bool> action) =>
  603.         _unMonitorProjectile?.Invoke(weapon, weaponId, action);
  604.  
  605.     //// POs, Dir, baseDamageLeft, HealthLeft, TargetEntityId, AmmoName
  606.     public MyTuple<Vector3D, Vector3D, float, float, long, string> GetProjectileState(ulong projectileId) =>
  607.         _getProjectileState?.Invoke(projectileId) ?? new MyTuple<Vector3D, Vector3D, float, float, long, string>();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement