Advertisement
klassekatze

KTZHunt3

Jul 17th, 2024
236
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 86.86 KB | None | 0 0
  1. static int getCtrlTick = -9000;
  2.  
  3. static IMyShipController getCtrlL = null;
  4.  
  5. static IMyShipController getCtrl()
  6. {
  7. var p = gProgram;
  8. if (tick - getCtrlTick > 3 * 60)
  9. {
  10. foreach (var c in p.controllers)
  11. {
  12. if (c.IsUnderControl)
  13. {
  14. getCtrlL = c;
  15. break;
  16. }
  17. }
  18. if(getCtrlL == null)
  19. {
  20. foreach (var c in p.controllers)
  21. {
  22. if (c.IsMainCockpit)
  23. {
  24. getCtrlL = c;
  25. break;
  26. }
  27. }
  28. }
  29. if (getCtrlL == null && p.controllers.Count > 0) getCtrlL = p.controllers[0];
  30. getCtrlTick = tick;
  31. }
  32. return getCtrlL;
  33. }
  34.  
  35.  
  36.  
  37. static int getMassT = -1;
  38.  
  39. static double getMassL = 0;
  40.  
  41. static double getMass()
  42. {
  43. if (tick != getMassT)
  44. {
  45. getMassT = tick;
  46. getMassL = getCtrl().CalculateShipMass().PhysicalMass;
  47. }
  48. return getMassL;
  49. }
  50.  
  51. static int getPositionT = -1;
  52.  
  53. static Vector3D getPositionL = Vector3D.Zero;
  54.  
  55. static Vector3D getPosition()
  56. {
  57. if (tick != getPositionT)
  58. {
  59. getPositionL = getCtrl().GetPosition();
  60. getPositionT = tick;
  61. }
  62. return getPositionL;
  63. }
  64.  
  65. static int getVelocityT = -1;
  66.  
  67. static Vector3D getVelocityL = Vector3D.Zero;
  68.  
  69. static Vector3D getVelocity()
  70. {
  71. if (tick != getVelocityT)
  72. {
  73. getVelocityL = getCtrl().GetShipVelocities().LinearVelocity;
  74. getVelocityT = tick;
  75. }
  76. return getVelocityL;
  77. }
  78.  
  79. static int getGravityT = -1;
  80.  
  81. static Vector3D getGravityL = Vector3D.Zero;
  82.  
  83. static Vector3D getGravity()
  84. {
  85. if (tick != getGravityT)
  86. {
  87. getGravityL = getCtrl().GetNaturalGravity();
  88. getGravityT = tick;
  89. }
  90. return getGravityL;
  91. }
  92.  
  93. static public Dictionary<string, RailData> RailDataSubType;
  94.  
  95. static public List<RailData> RailDatalist = new List<RailData>(){
  96. new RailData("UNN MA-15 Coilgun", 420, 900.0000f, 120, 6000.0f),
  97. new RailData("Mounted Zakosetara Heavy Railgun", 420, 3300.0000f, 120, 8000.0f),
  98. new RailData("OPA Behemoth Heavy Railgun", 300, 4202.6667f, 120, 12500.0f),
  99. new RailData("T-47 Roci Light Fixed Railgun", 324, 2400.0000f, 36, 9000.0f),
  100. new RailData("Zakosetara Heavy Railgun", 540, 3300.0000f, 0, 8000.0f),
  101. new RailData("Dawson-Pattern Medium Railgun", 300, 3000.0000f, 120, 10000.0f),
  102. new RailData("Farren-Pattern Heavy Railgun", 300, 4800.0000f, 120, 12500.0f),
  103. new RailData("V-14 Stiletto Light Railgun", 300, 2700.0000f, 120, 10000.0f),
  104. new RailData("VX-12 Foehammer Ultra-Heavy Railgun", 300, 4500.0000f, 120, 12500.0f)
  105. };
  106.  
  107.  
  108. //static public List<PDCData> PDCDatalist
  109. static public Dictionary<string, PDCData> PDCDataSubType = new Dictionary<string, PDCData>();
  110.  
  111. static public List<PDCData> PDCDatalist = new List<PDCData>()
  112. {
  113. new PDCData("OPA Point Defence Cannon", 1200, 100, 36000, 320, true),
  114. new PDCData("OPA Shotgun PDC", 240, 500, 36000, 320, true),
  115. new PDCData("OPA Shotgun PDC Angled", 240, 500, 36000, 320, true),
  116. new PDCData("Ostman-Jazinski Flak Cannon", 900, 100, 18000, 160, true),
  117. new PDCData("Voltaire Collective Anti Personnel PDC", 600, 100, 9000, 80, true),
  118. new PDCData("Nariman Dynamics PDC", 1800, 100, 45000, 400, true),
  119. new PDCData("Nariman Dynamics PDC Angled", 1800, 100, 45000, 400, true),
  120. new PDCData("Redfields Ballistics PDC", 1200, 90, 45000, 400, true),
  121. new PDCData("Redfields Ballistics PDC Angled", 1200, 90, 45000, 400, true)
  122. };
  123.  
  124.  
  125.  
  126.  
  127. public class PDCData
  128. {
  129. public string SubTypeId;
  130. public int MaxHeat = 1;
  131. public PDCData(string n, int rof = 0, int hps = 0, int mh = 0, int hsr = 0, bool drof = false)
  132. {
  133. SubTypeId = n;
  134. PDCDataSubType[SubTypeId] = this;
  135. MaxHeat = mh;
  136. }
  137. }
  138.  
  139.  
  140. public class RailData
  141. {
  142. public string SubTypeId;
  143. public int chargeTicks = 0;
  144. public int DUF = 0;
  145. public float maxDraw = 0;
  146. public float ammoVel = 0;
  147. public RailData(string subtype, int ticks, float maxcharge, int duf, float vel)
  148. {
  149. SubTypeId = subtype;
  150. if(RailDataSubType == null) RailDataSubType = new Dictionary<string, RailData>();
  151. RailDataSubType[SubTypeId] = this;
  152. chargeTicks = ticks;
  153. maxDraw = maxcharge;
  154. DUF = duf;
  155. ammoVel = vel;
  156. }
  157. }
  158.  
  159.  
  160.  
  161.  
  162. class WeaponState
  163. {
  164. public IMyTerminalBlock b = null;
  165. public RailData settings = null;
  166. //public PDCData psettings = null;
  167. public bool isCharging = false;
  168.  
  169. public float chargeProgress = 0;
  170. public void setCharging(bool b)
  171. {
  172. if (b != isCharging)
  173. {
  174. isCharging = b;
  175. if (b) chargeProgress = 0;
  176. else chargeProgress = 1;
  177. }
  178. }
  179. float lDraw = 0;
  180. float lProg = 0;
  181. public float lastDrawFactor = 0;
  182. public void update()
  183. {
  184. if (lDraw == 0 || tick % 3 == 0)
  185. {
  186. lDraw = gProgram.APIWC.GetCurrentPower(b);
  187. setCharging(lDraw > 5);
  188. }
  189. if (isCharging)
  190. {
  191. if (tick % 3 == 0)
  192. {
  193. lastDrawFactor = lDraw / settings.maxDraw;
  194. lProg = 1.0f / settings.chargeTicks * lastDrawFactor;
  195. }
  196. chargeProgress += lProg;
  197. if (chargeProgress > 1)
  198. {
  199. chargeProgress = 1;
  200. }
  201. }
  202. }
  203. }
  204.  
  205. Dictionary<IMyTerminalBlock, WeaponState> wsdict = new Dictionary<IMyTerminalBlock, WeaponState>();
  206.  
  207. WeaponState getWS(IMyTerminalBlock b)
  208. {
  209. WeaponState ws = null;
  210. wsdict.TryGetValue(b, out ws);
  211. if (ws == null)
  212. {
  213. if (RailDataSubType.ContainsKey(b.DefinitionDisplayNameText))
  214. {
  215. ws = wsdict[b] = new WeaponState();
  216. ws.settings = RailDataSubType[b.DefinitionDisplayNameText];
  217. ws.b = b;
  218. }/*else if(PDCDataSubType.ContainsKey(b.DefinitionDisplayNameText))
  219. {
  220. ws = wsdict[b] = new WeaponState();
  221. ws.psettings = PDCDataSubType[b.DefinitionDisplayNameText];
  222. ws.b = b;
  223. }*/
  224. }
  225. return ws;
  226. }
  227.  
  228. static Profiler railP = new Profiler("rail");
  229.  
  230. public void railchargeupdate()
  231. {
  232. railP.s();
  233. foreach (var w in subTargGroup)
  234. {
  235. WeaponState ws = null;
  236. wsdict.TryGetValue(w, out ws);
  237. if (ws == null)
  238. {
  239. if (RailDataSubType.ContainsKey(w.DefinitionDisplayNameText))
  240. {
  241. ws = wsdict[w] = new WeaponState();
  242. ws.settings = RailDataSubType[w.DefinitionDisplayNameText];
  243. ws.b = w;
  244. }
  245. }
  246. if (ws == null) continue;
  247. ws.update();
  248. }
  249. railP.e();
  250. }
  251.  
  252.  
  253. public class WcPbApi
  254. {
  255. public string[] WcBlockTypeLabels = new string[]
  256. {
  257. "Any",
  258. "Offense",
  259. "Utility",
  260. "Power",
  261. "Production",
  262. "Thrust",
  263. "Jumping",
  264. "Steering"
  265. };
  266.  
  267. private Action<ICollection<MyDefinitionId>> a;
  268. private Func<IMyTerminalBlock, IDictionary<string, int>, bool> b;
  269. private Action<IMyTerminalBlock, IDictionary<MyDetectedEntityInfo, float>> c;
  270. private Func<long, bool> d;
  271. private Func<long, int, MyDetectedEntityInfo> e;
  272. private Func<IMyTerminalBlock, long, int, bool> f;
  273. private Action<IMyTerminalBlock, bool, bool, int> g;
  274. private Func<IMyTerminalBlock, bool> h;
  275. private Action<IMyTerminalBlock, ICollection<MyDetectedEntityInfo>> i;
  276. private Func<IMyTerminalBlock, ICollection<string>, int, bool> j;
  277. private Action<IMyTerminalBlock, ICollection<string>, int> k;
  278. private Func<IMyTerminalBlock, long, int, Vector3D?> l;
  279.  
  280. private Func<IMyTerminalBlock, int, Matrix> m;
  281. private Func<IMyTerminalBlock, int, Matrix> n;
  282. private Func<IMyTerminalBlock, long, int, MyTuple<bool, Vector3D?>> o;
  283. private Func<IMyTerminalBlock, int, string> p;
  284. private Action<IMyTerminalBlock, int, string> q;
  285. private Func<long, float> r;
  286. private Func<IMyTerminalBlock, int, MyDetectedEntityInfo> s;
  287. private Action<IMyTerminalBlock, long, int> t;
  288. private Func<long, MyTuple<bool, int, int>> u;
  289.  
  290. private Action<IMyTerminalBlock, bool, int> v;
  291. private Func<IMyTerminalBlock, int, bool, bool, bool> w;
  292. private Func<IMyTerminalBlock, int, float> x;
  293. private Func<IMyTerminalBlock, int, MyTuple<Vector3D, Vector3D>> y;
  294. private Func<IMyTerminalBlock, float> _getCurrentPower;
  295. public Func<Sandbox.ModAPI.Ingame.IMyTerminalBlock, float> _getHeatLevel;
  296.  
  297. public bool isReady = false;
  298. IMyTerminalBlock pbBlock = null;
  299. public bool Activate(IMyTerminalBlock pbBlock)
  300. {
  301. this.pbBlock = pbBlock;
  302. var dict = pbBlock.GetProperty("WcPbAPI")?.As<IReadOnlyDictionary<string, Delegate>>().GetValue(pbBlock);
  303. if (dict == null) throw new Exception("WcPbAPI failed to activate");
  304. return ApiAssign(dict);
  305. }
  306.  
  307. public bool ApiAssign(IReadOnlyDictionary<string, Delegate> delegates)
  308. {
  309. if (delegates == null)
  310. return false;
  311. AssignMethod(delegates, "GetCoreWeapons", ref a);
  312. AssignMethod(delegates, "GetBlockWeaponMap", ref b);
  313. AssignMethod(delegates, "GetSortedThreats", ref c);
  314. AssignMethod(delegates, "GetObstructions", ref i);
  315. AssignMethod(delegates, "HasGridAi", ref d);
  316. AssignMethod(delegates, "GetAiFocus", ref e);
  317. AssignMethod(delegates, "SetAiFocus", ref f);
  318. AssignMethod(delegates, "HasCoreWeapon", ref h);
  319. AssignMethod(delegates, "GetPredictedTargetPosition", ref l);
  320. AssignMethod(delegates, "GetTurretTargetTypes", ref j);
  321. AssignMethod(delegates, "SetTurretTargetTypes", ref k);
  322. AssignMethod(delegates, "GetWeaponAzimuthMatrix", ref m);
  323. AssignMethod(delegates, "GetWeaponElevationMatrix", ref n);
  324. AssignMethod(delegates, "IsTargetAlignedExtended", ref o);
  325. AssignMethod(delegates, "GetActiveAmmo", ref p);
  326. AssignMethod(delegates, "SetActiveAmmo", ref q);
  327. AssignMethod(delegates, "GetConstructEffectiveDps", ref r);
  328. AssignMethod(delegates, "GetWeaponTarget", ref s);
  329. AssignMethod(delegates, "SetWeaponTarget", ref t);
  330. AssignMethod(delegates, "GetProjectilesLockedOn", ref u);
  331.  
  332. AssignMethod(delegates, "FireWeaponOnce", ref v);
  333. AssignMethod(delegates, "ToggleWeaponFire", ref g);
  334. AssignMethod(delegates, "IsWeaponReadyToFire", ref w);
  335. AssignMethod(delegates, "GetMaxWeaponRange", ref x);
  336. AssignMethod(delegates, "GetWeaponScope", ref y);
  337.  
  338. AssignMethod(delegates, "GetCurrentPower", ref _getCurrentPower);
  339. AssignMethod(delegates, "GetHeatLevel", ref _getHeatLevel);
  340.  
  341. //Delegate.CreateDelegate(null, null);
  342.  
  343. isReady = true;
  344. return true;
  345. }
  346. private void AssignMethod<T>(IReadOnlyDictionary<string, Delegate> delegates, string name, ref T field) where T : class
  347. {
  348. if (delegates == null)
  349. {
  350. field = null;
  351. return;
  352. }
  353. Delegate del;
  354. if (!delegates.TryGetValue(name, out del))
  355. throw new Exception($"{GetType().Name} :: Couldn't find {name} delegate of type {typeof(T)}");
  356. field = del as T;
  357. if (field == null)
  358. throw new Exception(
  359. $"{GetType().Name} :: Delegate {name} is not type {typeof(T)}, instead it's: {del.GetType()}");
  360. }
  361.  
  362. public void GetAllCoreWeapons(ICollection<MyDefinitionId> collection) => a?.Invoke(collection);
  363. public void GetSortedThreats(IDictionary<MyDetectedEntityInfo, float> collection) =>
  364. c?.Invoke(pbBlock, collection);
  365. public bool HasGridAi(long entity) => d?.Invoke(entity) ?? false;
  366. public MyDetectedEntityInfo? GetAiFocus(long shooter, int priority = 0) => e?.Invoke(shooter, priority);
  367.  
  368. public bool SetAiFocus(IMyTerminalBlock pBlock, long target, int priority = 0) =>
  369. f?.Invoke(pBlock, target, priority) ?? false;
  370.  
  371. public void ToggleWeaponFire(IMyTerminalBlock weapon, bool on, bool allWeapons, int weaponId = 0) =>
  372. g?.Invoke(weapon, on, allWeapons, weaponId);
  373. public bool HasCoreWeapon(IMyTerminalBlock weapon) => h?.Invoke(weapon) ?? false;
  374.  
  375. public void GetObstructions(IMyTerminalBlock pBlock, ICollection<MyDetectedEntityInfo> collection) =>
  376. i?.Invoke(pBlock, collection);
  377.  
  378. public Vector3D? GetPredictedTargetPosition(IMyTerminalBlock weapon, long targetEnt, int weaponId) =>
  379. l?.Invoke(weapon, targetEnt, weaponId) ?? null;
  380.  
  381. public Matrix GetWeaponAzimuthMatrix(IMyTerminalBlock weapon, int weaponId) =>
  382. m?.Invoke(weapon, weaponId) ?? Matrix.Zero;
  383.  
  384. public Matrix GetWeaponElevationMatrix(IMyTerminalBlock weapon, int weaponId) =>
  385. n?.Invoke(weapon, weaponId) ?? Matrix.Zero;
  386.  
  387. public MyTuple<bool, Vector3D?> IsTargetAlignedExtended(IMyTerminalBlock weapon, long targetEnt, int weaponId) =>
  388. o?.Invoke(weapon, targetEnt, weaponId) ?? new MyTuple<bool, Vector3D?>();
  389. public string GetActiveAmmo(IMyTerminalBlock weapon, int weaponId) =>
  390. p?.Invoke(weapon, weaponId) ?? null;
  391.  
  392. public void SetActiveAmmo(IMyTerminalBlock weapon, int weaponId, string ammoType) =>
  393. q?.Invoke(weapon, weaponId, ammoType);
  394.  
  395. public float GetConstructEffectiveDps(long entity) => r?.Invoke(entity) ?? 0f;
  396.  
  397. public MyDetectedEntityInfo? GetWeaponTarget(IMyTerminalBlock weapon, int weaponId = 0) =>
  398. s?.Invoke(weapon, weaponId);
  399.  
  400. public void SetWeaponTarget(IMyTerminalBlock weapon, long target, int weaponId = 0) =>
  401. t?.Invoke(weapon, target, weaponId);
  402.  
  403. public bool GetBlockWeaponMap(IMyTerminalBlock weaponBlock, IDictionary<string, int> collection) =>
  404. b?.Invoke(weaponBlock, collection) ?? false;
  405.  
  406. public MyTuple<bool, int, int> GetProjectilesLockedOn(long victim) =>
  407. u?.Invoke(victim) ?? new MyTuple<bool, int, int>();
  408.  
  409. public void FireWeaponOnce(IMyTerminalBlock weapon, bool allWeapons = true, int weaponId = 0) =>
  410. v?.Invoke(weapon, allWeapons, weaponId);
  411.  
  412.  
  413. public bool IsWeaponReadyToFire(IMyTerminalBlock weapon, int weaponId = 0, bool anyWeaponReady = true,
  414. bool shootReady = false) =>
  415. w?.Invoke(weapon, weaponId, anyWeaponReady, shootReady) ?? false;
  416.  
  417. public float GetMaxWeaponRange(IMyTerminalBlock weapon, int weaponId) =>
  418. x?.Invoke(weapon, weaponId) ?? 0f;
  419.  
  420. public MyTuple<Vector3D, Vector3D> GetWeaponScope(IMyTerminalBlock weapon, int weaponId) =>
  421. y?.Invoke(weapon, weaponId) ?? new MyTuple<Vector3D, Vector3D>();
  422. public float GetCurrentPower(IMyTerminalBlock weapon) => _getCurrentPower?.Invoke(weapon) ?? 0f;
  423.  
  424. public float GetHeatLevel(Sandbox.ModAPI.Ingame.IMyTerminalBlock weapon) => _getHeatLevel?.Invoke(weapon) ?? 0f;
  425. }
  426.  
  427. public static string v2ss(Vector3D v)
  428. {
  429. return "<" + v.X.ToString("0.0000") + "," + v.Y.ToString("0.0000") + "," + v.Z.ToString("0.0000") + ">";
  430. }
  431.  
  432. static int dd_tick;
  433.  
  434. static Vector3D dd_dfv, dd_duv;
  435.  
  436. static MatrixD dd_wm;
  437.  
  438. static double dd_y, dd_p, dd_r;
  439.  
  440. public static void GetRotationAnglesSimultaneousDedup(Vector3D fwd, Vector3D up, MatrixD wm, out double yaw, out double pitch, out double roll)
  441. {
  442. if(tick != dd_tick || fwd != dd_dfv || up != dd_duv || dd_wm != wm)
  443. {
  444. dd_tick = tick;
  445. dd_dfv = fwd;
  446. dd_duv = up;
  447. dd_wm = wm;
  448. GetRotationAnglesSimultaneous(dd_dfv, dd_duv, dd_wm, out dd_y, out dd_p, out dd_r);
  449. }
  450. yaw = dd_y;
  451. pitch = dd_p;
  452. roll = dd_r;
  453. }
  454.  
  455.  
  456. /// <summary>
  457. /// Whip's GetRotationAnglesSimultaneous - Last modified: 07/05/2020
  458. /// </summary>
  459. public static void GetRotationAnglesSimultaneous(Vector3D a, Vector3D b, MatrixD w, out double yaw, out double pitch, out double roll)
  460. {
  461. a = SafeNormalize(a);
  462. MatrixD twm;
  463. MatrixD.Transpose(ref w, out twm);
  464. Vector3D.Rotate(ref a, ref twm, out a);
  465. Vector3D.Rotate(ref b, ref twm, out b);
  466. Vector3D lv = Vector3D.Cross(b, a);
  467. Vector3D axis;
  468. double angle;
  469. if (Vector3D.IsZero(b) || Vector3D.IsZero(lv))
  470. {
  471. axis = new Vector3D(a.Y, -a.X, 0);
  472. angle = Math.Acos(MathHelper.Clamp(-a.Z, -1.0, 1.0));
  473. }
  474. else
  475. {
  476. lv = SafeNormalize(lv);
  477. Vector3D upVector = Vector3D.Cross(a, lv);
  478. MatrixD tm = MatrixD.Zero;
  479. tm.Forward = a;
  480. tm.Left = lv;
  481. tm.Up = upVector;
  482. axis = new Vector3D(tm.M23 - tm.M32,tm.M31 - tm.M13,tm.M12 - tm.M21);
  483. double trace = tm.M11 + tm.M22 + tm.M33;
  484. angle = Math.Acos(MathHelper.Clamp((trace - 1) * 0.5, -1, 1));
  485. }
  486. if (Vector3D.IsZero(axis))
  487. {
  488. angle = a.Z < 0 ? 0 : Math.PI;
  489. yaw = angle;
  490. pitch = 0;
  491. roll = 0;
  492. return;
  493. }
  494. axis = SafeNormalize(axis);
  495. yaw = -axis.Y * angle;
  496. pitch = axis.X * angle;
  497. roll = -axis.Z * angle;
  498. }
  499.  
  500.  
  501. public static Vector3D SafeNormalize(Vector3D a)
  502. {
  503. if (Vector3D.IsZero(a))
  504. return Vector3D.Zero;
  505.  
  506. if (Vector3D.IsUnit(ref a))
  507. return a;
  508.  
  509. return Vector3D.Normalize(a);
  510. }
  511.  
  512. public const double d180bypi = (180 / Math.PI);
  513.  
  514. public static double ConvertRadiansToDegrees(double radians)
  515. {
  516. double degrees = d180bypi * radians;
  517. return (degrees);
  518. }
  519.  
  520. static double dpiby180 = (Math.PI / 180);
  521.  
  522. public static double ConvertDegreesToRadians(double degrees)
  523. {
  524. double radians = dpiby180 * degrees;
  525. return (radians);
  526. }
  527.  
  528. public static double cpa_time(Vector3D Tr1_p, Vector3D Tr1_v, Vector3D Tr2_p, Vector3D Tr2_v)
  529. {
  530. Vector3D dv = Tr1_v - Tr2_v;
  531.  
  532. double dv2 = Vector3D.Dot(dv, dv);
  533. if (dv2 < 0.00000001) // the tracks are almost parallel
  534. return 0.0; // any time is ok. Use time 0.
  535.  
  536. Vector3D w0 = Tr1_p - Tr2_p;
  537. double cpatime = -Vector3D.Dot(w0, dv) / dv2;
  538.  
  539. return cpatime; // time of CPA
  540. }
  541.  
  542. public class SpriteHUDLCD
  543. {
  544. static Dictionary<string, Color> ColorList = new Dictionary<string, Color> { { "aliceblue", Color.AliceBlue }, { "antiquewhite", Color.AntiqueWhite }, { "aqua", Color.Aqua }, { "aquamarine", Color.Aquamarine }, { "azure", Color.Azure }, { "beige", Color.Beige }, { "bisque", Color.Bisque }, { "black", Color.Black }, { "blanchedalmond", Color.BlanchedAlmond }, { "blue", Color.Blue }, { "blueviolet", Color.BlueViolet }, { "brown", Color.Brown }, { "burlywood", Color.BurlyWood }, { "badetblue", Color.CadetBlue }, { "chartreuse", Color.Chartreuse }, { "chocolate", Color.Chocolate }, { "coral", Color.Coral }, { "cornflowerblue", Color.CornflowerBlue }, { "cornsilk", Color.Cornsilk }, { "crimson", Color.Crimson }, { "cyan", Color.Cyan }, { "darkblue", Color.DarkBlue }, { "darkcyan", Color.DarkCyan }, { "darkgoldenrod", Color.DarkGoldenrod }, { "darkgray", Color.DarkGray }, { "darkgreen", Color.DarkGreen }, { "darkkhaki", Color.DarkKhaki }, { "darkmagenta", Color.DarkMagenta }, { "darkoliveGreen", Color.DarkOliveGreen }, { "darkorange", Color.DarkOrange }, { "darkorchid", Color.DarkOrchid }, { "darkred", Color.DarkRed }, { "darksalmon", Color.DarkSalmon }, { "darkseagreen", Color.DarkSeaGreen }, { "darkslateblue", Color.DarkSlateBlue }, { "darkslategray", Color.DarkSlateGray }, { "darkturquoise", Color.DarkTurquoise }, { "darkviolet", Color.DarkViolet }, { "deeppink", Color.DeepPink }, { "deepskyblue", Color.DeepSkyBlue }, { "dimgray", Color.DimGray }, { "dodgerblue", Color.DodgerBlue }, { "firebrick", Color.Firebrick }, { "floralwhite", Color.FloralWhite }, { "forestgreen", Color.ForestGreen }, { "fuchsia", Color.Fuchsia }, { "gainsboro", Color.Gainsboro }, { "ghostwhite", Color.GhostWhite }, { "gold", Color.Gold }, { "goldenrod", Color.Goldenrod }, { "gray", Color.Gray }, { "green", Color.Green }, { "greenyellow", Color.GreenYellow }, { "doneydew", Color.Honeydew }, { "hotpink", Color.HotPink }, { "indianred", Color.IndianRed }, { "indigo", Color.Indigo }, { "ivory", Color.Ivory }, { "khaki", Color.Khaki }, { "lavender", Color.Lavender }, { "lavenderblush", Color.LavenderBlush }, { "lawngreen", Color.LawnGreen }, { "lemonchiffon", Color.LemonChiffon }, { "lightblue", Color.LightBlue }, { "lightcoral", Color.LightCoral }, { "lightcyan", Color.LightCyan }, { "lightgoldenrodyellow", Color.LightGoldenrodYellow }, { "lightgray", Color.LightGray }, { "lightgreen", Color.LightGreen }, { "lightpink", Color.LightPink }, { "lightsalmon", Color.LightSalmon }, { "lightseagreen", Color.LightSeaGreen }, { "lightskyblue", Color.LightSkyBlue }, { "lightslategray", Color.LightSlateGray }, { "lightsteelblue", Color.LightSteelBlue }, { "lightyellow", Color.LightYellow }, { "lime", Color.Lime }, { "limegreen", Color.LimeGreen }, { "linen", Color.Linen }, { "magenta", Color.Magenta }, { "maroon", Color.Maroon }, { "mediumaquamarine", Color.MediumAquamarine }, { "mediumblue", Color.MediumBlue }, { "mediumorchid", Color.MediumOrchid }, { "mediumpurple", Color.MediumPurple }, { "mediumseagreen", Color.MediumSeaGreen }, { "mediumslateblue", Color.MediumSlateBlue }, { "mediumspringgreen", Color.MediumSpringGreen }, { "mediumturquoise", Color.MediumTurquoise }, { "mediumvioletred", Color.MediumVioletRed }, { "midnightblue", Color.MidnightBlue }, { "mintcream", Color.MintCream }, { "mistyrose", Color.MistyRose }, { "moccasin", Color.Moccasin }, { "navajowhite", Color.NavajoWhite }, { "navy", Color.Navy }, { "oldlace", Color.OldLace }, { "olive", Color.Olive }, { "olivedrab", Color.OliveDrab }, { "orange", Color.Orange }, { "orangered", Color.OrangeRed }, { "orchid", Color.Orchid }, { "palegoldenrod", Color.PaleGoldenrod }, { "palegreen", Color.PaleGreen }, { "paleturquoise", Color.PaleTurquoise }, { "palevioletred", Color.PaleVioletRed }, { "papayawhip", Color.PapayaWhip }, { "peachpuff", Color.PeachPuff }, { "peru", Color.Peru }, { "pink", Color.Pink }, { "plum", Color.Plum }, { "powderblue", Color.PowderBlue }, { "purple", Color.Purple }, { "red", Color.Red }, { "rosybrown", Color.RosyBrown }, { "royalblue", Color.RoyalBlue }, { "saddlebrown", Color.SaddleBrown }, { "salmon", Color.Salmon }, { "sandybrown", Color.SandyBrown }, { "seagreen", Color.SeaGreen }, { "seashell", Color.SeaShell }, { "sienna", Color.Sienna }, { "silver", Color.Silver }, { "skyblue", Color.SkyBlue }, { "slateblue", Color.SlateBlue }, { "slategray", Color.SlateGray }, { "snow", Color.Snow }, { "springgreen", Color.SpringGreen }, { "steelblue", Color.SteelBlue }, { "tan", Color.Tan }, { "teal", Color.Teal }, { "thistle", Color.Thistle }, { "tomato", Color.Tomato }, { "turquoise", Color.Turquoise }, { "violet", Color.Violet }, { "wheat", Color.Wheat }, { "white", Color.White }, { "whitesmoke", Color.WhiteSmoke }, { "yellow", Color.Yellow }, { "yellowgreen", Color.YellowGreen } };
  545. public IMyTextSurface s = null;
  546.  
  547. public SpriteHUDLCD(IMyTextSurface s)
  548. {
  549. this.s = s;
  550. }
  551. int ltick = -1;
  552. string lasttext = "-1";
  553. public void setLCD(string text)
  554. {
  555. if (text != lasttext || tick - ltick > 120)
  556. {
  557. ltick = tick;
  558. lasttext = text;
  559. s.WriteText(text);
  560. List<object> tok = new List<object>();
  561. string[] tokens = text.Split(new string[] { "<color=" }, StringSplitOptions.None);
  562. for (int i = 0; i < tokens.Length; i++)
  563. {
  564. var t = tokens[i];
  565. foreach (var kvp in ColorList)
  566. {
  567. if (t.StartsWith(kvp.Key + ">"))
  568. {
  569. t = t.Substring(kvp.Key.Length + 1);
  570. tok.Add(kvp.Value);
  571. break;
  572. }
  573. }
  574. tok.Add(t);
  575. }
  576.  
  577. s.ContentType = ContentType.SCRIPT;
  578. s.Script = "";
  579. s.Font = "Monospace";
  580. RectangleF _viewport;
  581. _viewport = new RectangleF(
  582. (s.TextureSize - s.SurfaceSize) / 2f,
  583. s.SurfaceSize
  584. );
  585. using (var frame = s.DrawFrame())
  586. {
  587. var zpos = new Vector2(0, 0) + _viewport.Position + new Vector2(s.TextPadding / 100 * s.SurfaceSize.X, s.TextPadding / 100 * s.SurfaceSize.Y);
  588. var position = zpos;
  589. Color cColor = Color.White;
  590. foreach (var t in tok)
  591. {
  592. if (t is Color) cColor = (Color)t;
  593. else if (t is string) writeText((string)t, frame, ref position, zpos, s.FontSize, cColor);
  594. }
  595. }
  596. }
  597. }
  598.  
  599. public void writeText(string text, MySpriteDrawFrame frame, ref Vector2 pos, Vector2 zpos, float textSize, Color color)
  600. {
  601. string[] lines = text.Split('\n');
  602. for (int l = 0; l < lines.Length; l++)
  603. {
  604. var line = lines[l];
  605. if (line.Length > 0)
  606. {
  607. MySprite sprite = MySprite.CreateText(line, "Monospace", color, textSize, TextAlignment.LEFT);
  608. sprite.Position = pos;
  609. frame.Add(sprite);
  610. }
  611. if (l < lines.Length - 1)
  612. {
  613. pos.X = zpos.X;
  614. pos.Y += 28 * textSize;
  615. }
  616. else pos.X += 20 * textSize * line.Length;
  617. }
  618. }
  619. }
  620.  
  621.  
  622. bool matchSpeed = false;
  623.  
  624. DetectedEntity matchTarget = null;
  625.  
  626.  
  627. void toggleMatchSpeed()
  628. {
  629. matchSpeed = !matchSpeed;
  630. if (!matchSpeed)
  631. {
  632. matchTarget = null;
  633. foreach (var t in thrusters) t.ThrustOverridePercentage = 0;
  634. }
  635. }
  636.  
  637. void speedMatch(string arg)
  638. {
  639. toggleMatchSpeed();
  640. if (matchSpeed)
  641. {
  642. if (arg == "matchclosest")
  643. {
  644. if (detectedEntitiesL.Count > 0)
  645. {
  646. matchTarget = detectedEntitiesL[0];
  647. }
  648. else toggleMatchSpeed();
  649. }
  650. if (arg == "matchfocus")
  651. {
  652. MyDetectedEntityInfo? focus = APIWC.GetAiFocus(Me.CubeGrid.EntityId);
  653. if (focus.HasValue && !focus.Value.IsEmpty())
  654. {
  655.  
  656. matchTarget = null;
  657. detectedEntitiesD.TryGetValue(focus.Value.EntityId, out matchTarget);
  658. if (matchTarget == null) toggleMatchSpeed();
  659. }
  660. else toggleMatchSpeed();
  661. }
  662. }
  663. else matchTarget = null;
  664. processRadar(0, true);
  665. }
  666.  
  667. static Profiler spdmtchP = new Profiler("spdmtch");
  668.  
  669. bool lastDamp = true;
  670.  
  671. void speedmatch_upd()
  672. {
  673. spdmtchP.s();
  674. if (matchSpeed)
  675. {
  676. var over = getCtrl().DampenersOverride;
  677. if (lastDamp != over)
  678. {
  679. lastDamp = over;
  680. if(!over)
  681. {
  682. foreach (var t in thrusters) t.ThrustOverridePercentage = 0;
  683. }
  684. }
  685.  
  686.  
  687. bool canTrack = false;
  688. if (matchTarget != null)
  689. {
  690. DetectedEntity d = null;
  691. detectedEntitiesD.TryGetValue(matchTarget.EntityId, out d);
  692. if (d != null)
  693. {
  694. canTrack = true;
  695. matchTarget = d;
  696. }
  697.  
  698. if (!canTrack || matchTarget == null)
  699. {
  700. toggleMatchSpeed();
  701. }
  702. else
  703. {
  704. targetVelocityVec = matchTarget.Velocity;
  705. }
  706. }
  707. }
  708. if (matchSpeed && lastDamp) SpeedMatcher();
  709. spdmtchP.e();
  710. }
  711.  
  712.  
  713.  
  714.  
  715. //taken mostly wholesale from https://github.com/Whiplash141/SpaceEngineersScripts/blob/master/Released/speed_matcher.cs
  716. Vector3D targetVelocityVec = new Vector3D(0, 0, 0);
  717.  
  718.  
  719. Vector3D ldesire;
  720.  
  721. void SpeedMatcher()
  722. {
  723. var ctrl = getCtrl();
  724. var myVelocityVec = ctrl.GetShipVelocities().LinearVelocity;
  725. var inputVec = ctrl.MoveIndicator;
  726. var desiredDirectionVec = Vector3D.TransformNormal(inputVec, ctrl.WorldMatrix); //world relative input vector
  727. var relativeVelocity = myVelocityVec - targetVelocityVec;
  728. var rvsqr = relativeVelocity.LengthSquared();
  729. if (tick % 2 == 0 || ldesire != desiredDirectionVec || (rvsqr > 0.01*0.01 && rvsqr < 50*50))
  730. {//speedmatch is surprisingly unperformant even with all we can do. use heuristic to do half-ticks a lot of the time
  731. ldesire = desiredDirectionVec;
  732. ApplyThrust(thrusters, relativeVelocity, desiredDirectionVec, ctrl);
  733. }
  734. }
  735.  
  736.  
  737. void ApplyThrust(List<IMyThrust> thrusters, Vector3D targetVel, Vector3D dirvec, IMyShipController ctrl)
  738. {
  739. var mass = ctrl.CalculateShipMass().PhysicalMass;
  740. var gravity = ctrl.GetNaturalGravity();
  741.  
  742. var desiredThrust = mass * (2 * targetVel + gravity);
  743. var thrustToApply = desiredThrust;
  744. if (!Vector3D.IsZero(dirvec))
  745. {
  746. thrustToApply = VectorRejection(desiredThrust, dirvec);
  747. }
  748. applySpeedMatchThrust(thrustToApply, dirvec, ctrl.DampenersOverride);
  749. }
  750.  
  751. public Vector3D VectorRejection(Vector3D a, Vector3D b) //reject a on b
  752. {
  753. if (Vector3D.IsZero(b))
  754. return Vector3D.Zero;
  755.  
  756. return a - a.Dot(b) / b.LengthSquared() * b;
  757. }
  758.  
  759.  
  760. static Profiler aavtP = new Profiler("aavt");
  761.  
  762. static public void applySpeedMatchThrust(Vector3D thrustNewtons, Vector3D desiredDirectionVec, bool dampener)
  763. {
  764. aavtP.s();
  765. //curThrustVector = thrustNewtons;
  766.  
  767. foreach (var k in Base6Directions.EnumDirections)
  768. {
  769. var l = thrustersByDir[k];
  770. if (l.Count > 0)
  771. {
  772. var fwd = l[0].WorldMatrix.Forward;
  773. var bck = l[0].WorldMatrix.Backward;
  774. var fwddot = Vector3D.Dot(fwd, thrustNewtons);
  775. var bckdot = Vector3D.Dot(bck, desiredDirectionVec);
  776. foreach (IMyThrust t in l)
  777. {
  778. if (bckdot > .7071) //thrusting in desired direction
  779. {
  780. t.ThrustOverridePercentage = 1f;
  781. }
  782. else if(fwddot > 0.00001f && dampener)
  783. {
  784. var met = thrusterMaxEffectiveThrust[t];
  785. var outputProportion = MathHelper.Clamp(fwddot / met, 0, 1);
  786. var achievedot = outputProportion * met;
  787. fwddot -= achievedot;
  788. t.ThrustOverridePercentage = (float)outputProportion;
  789. }
  790. else t.ThrustOverridePercentage = 0.000001f;
  791. }
  792. }
  793. }
  794. aavtP.e();
  795. }
  796.  
  797. bool readConfig = false;
  798.  
  799. string lastCustomData = "";
  800.  
  801. void configChk()
  802. {
  803. if (!readConfig || tick % 60 == 0)
  804. {
  805. if (Config == null) Config = new Config_();
  806. readConfig = true;
  807. if (Me.CustomData != lastCustomData)
  808. {
  809. log("Loading CustomData.", LT.LOG_N);
  810. deserializeConfig(Me.CustomData);
  811. Me.CustomData = lastCustomData = serializeConfig();
  812. }
  813. }
  814. }
  815.  
  816.  
  817.  
  818. public static List<Setting_> settings = null;
  819.  
  820. public static string serializeConfig()
  821. {
  822. string s = "";
  823. foreach(var v in settings)
  824. {
  825. if (s.Length > 0) s += "\n";
  826. if (v.desc.Length > 0)
  827. {
  828. s += "//"+v.desc+"\n";
  829. }
  830. s += v.serialized();
  831. }
  832. return s;
  833. }
  834.  
  835. public static void deserializeConfig(string s)
  836. {
  837. if (settings == null) throw new Exception("setting list null?");
  838. string[] lines = s.Split('\n');
  839. foreach (var l in lines)
  840. {
  841. if (l.StartsWith("//") || l.StartsWith("#")) continue;//a=b
  842. int idx = l.IndexOf('=');
  843. if(idx != -1)
  844. {
  845. var a = l.Substring(0, idx);
  846. var b = l.Substring(idx+1);
  847. Setting_ set = null;
  848. foreach (var stn in settings)
  849. {
  850. if (stn != null && a == stn.name)
  851. {
  852. set = stn;
  853. break;
  854. }
  855. }
  856. if (set != null)
  857. {
  858. set.deserializeValue(b);
  859. }
  860. }
  861. }
  862. }
  863.  
  864. public static void resetConfig()
  865. {
  866. foreach (var v in settings)v.reset();
  867. }
  868.  
  869.  
  870.  
  871. public abstract class Setting_
  872. {
  873. public string name = "";
  874. public string desc = "";
  875. public Setting_(string n)
  876. {
  877. name = n;
  878. if(settings == null) settings = new List<Setting_>();
  879. settings.Add(this);
  880. }
  881. protected string setvalue = "";
  882. abstract public void serializeValue();
  883. public string serialized()
  884. {
  885. serializeValue();
  886. return name + "=" + setvalue;
  887. }
  888. public abstract void deserializeValue(string v);
  889.  
  890. public T typeString<T>(string v)
  891. {
  892. try
  893. {
  894. object V_ = null;
  895. if (typeof(T) == typeof(string)) V_ = v;
  896. else if (typeof(T) == typeof(int)) V_ = Int32.Parse(v);
  897. else if (typeof(T) == typeof(float)) V_ = Single.Parse(v);
  898. else if (typeof(T) == typeof(double)) V_ = Double.Parse(v);
  899. else if (typeof(T) == typeof(char)) V_ = Char.Parse(v);
  900. else if (typeof(T) == typeof(DateTime)) V_ = DateTime.Parse(v);
  901. else if (typeof(T) == typeof(decimal)) V_ = Decimal.Parse(v);
  902. else if (typeof(T) == typeof(bool)) V_ = Boolean.Parse(v);
  903. else if (typeof(T) == typeof(byte)) V_ = Byte.Parse(v);
  904. else if (typeof(T) == typeof(uint)) V_ = UInt32.Parse(v);
  905. else if (typeof(T) == typeof(short)) V_ = short.Parse(v);
  906. else if (typeof(T) == typeof(long)) V_ = long.Parse(v);
  907. else if (typeof(T) == typeof(List<string>))
  908. {
  909. V_ = new List<string>(v.Split(','));
  910. }
  911. else
  912. {
  913. log("Unsupported type in typeString for " + typeof(T).ToString(), LT.LOG_N);
  914. return default(T);
  915. }
  916. return (T)V_;
  917. }
  918. catch (Exception e)
  919. {
  920. log("Exception in typeString: " + e.Message, LT.LOG_N);
  921. return default(T);
  922. }
  923. }
  924. public abstract void reset();
  925. }
  926.  
  927. public class SettingDict<T> : Setting_
  928. {
  929. public Dictionary<string, T> DVal = new Dictionary<string, T>();
  930. public Dictionary<string, T> Val = new Dictionary<string, T>();
  931. public SettingDict(string n, Dictionary<string, T> def=null) : base(n)
  932. {
  933. if (def != null) Val = def;
  934. }
  935.  
  936. public override void deserializeValue(string v)
  937. {
  938. Val.Clear();
  939. string[] kvps = v.Split(',');
  940. foreach (var p in kvps)
  941. {
  942. string[] kvp = p.Split(':');
  943. if (kvp.Length > 1)
  944. {
  945. Val[kvp[0]] = typeString<T>(kvp[1]);
  946. }
  947. }
  948. }
  949.  
  950. public override void serializeValue()
  951. {
  952. string av = "";
  953. foreach (var kvp in Val)
  954. {
  955. if (av.Length > 0) av += ",";
  956. av += kvp.Key + ":" + kvp.Value.ToString();
  957. }
  958. setvalue = av;
  959. }
  960.  
  961. public SettingDict<T> Desc(string d)
  962. {
  963. desc = d;
  964. return this;
  965. }
  966. public SettingDict<T> Default(Dictionary<string, T> v)
  967. {
  968. DVal = Val = v;
  969. return this;
  970. }
  971. public override void reset()
  972. {
  973. Val = DVal;
  974. }
  975. }
  976.  
  977.  
  978. public class Setting<T> : Setting_
  979. {
  980. public T Val;
  981. T DVal;
  982.  
  983. T defaultV()
  984. {
  985. if (typeof(T) == typeof(String)) return (T)(object)String.Empty;
  986. return default(T);
  987. }
  988. public Setting(string n) : base(n)
  989. {
  990. try
  991. {
  992. typeString<T>(defaultV().ToString());//will trip the invalid type error if it is invalid
  993. }catch(Exception e)
  994. {
  995. gProgram.Echo(e.ToString());
  996. //throw e;
  997. }
  998. Val = defaultV();
  999. }
  1000.  
  1001. public Setting<T> Desc(string d)
  1002. {
  1003. desc = d;
  1004. return this;
  1005. }
  1006. public Setting<T> Default(T v)
  1007. {
  1008. DVal = Val = v;
  1009. return this;
  1010. }
  1011.  
  1012. override public void serializeValue()
  1013. {
  1014. try
  1015. {
  1016. if (typeof(T) == typeof(List<string>))
  1017. {
  1018. object V_ = Val;
  1019. List<string> Vl = (List<string>)V_;
  1020. setvalue = String.Join(",", Vl.ToArray());
  1021. }
  1022. else setvalue = "" + Val;
  1023. }
  1024. catch (Exception e) {
  1025. log("Exception in serializeValue: " + e.Message, LT.LOG_N);
  1026. }
  1027. }
  1028. override public void deserializeValue(string v)
  1029. {
  1030. Val = typeString<T>(v);
  1031. //return V;
  1032. }
  1033. public override void reset()
  1034. {
  1035. Val = DVal;
  1036. }
  1037. }
  1038.  
  1039. List<MyDetectedEntityInfo> WCobstructions = new List<MyDetectedEntityInfo>();
  1040.  
  1041. Dictionary<MyDetectedEntityInfo, float> WCthreats = new Dictionary<MyDetectedEntityInfo, float>();
  1042.  
  1043. MyDetectedEntityInfo focus = new MyDetectedEntityInfo();
  1044.  
  1045. long lfocus = -1;
  1046.  
  1047. int focusChangeTick = -1;
  1048.  
  1049. class DetectedEntity
  1050. {
  1051. public int updTick;
  1052.  
  1053. public long EntityId;
  1054. public string Name = "";
  1055. public MyDetectedEntityType Type;
  1056. public BoundingBoxD BBox;
  1057. public MatrixD Orientation;
  1058. public Vector3D Position;
  1059. public Vector3D Velocity;
  1060. public MyRelationsBetweenPlayerAndBlock Rel = MyRelationsBetweenPlayerAndBlock.Neutral;
  1061. public float threat;
  1062.  
  1063. public MyDetectedEntityInfo focus;
  1064. public double ldistSqr;
  1065. public double distSqr;
  1066.  
  1067. public bool isPMW = false;
  1068.  
  1069.  
  1070. public DetectedEntity upd(MyDetectedEntityInfo e)
  1071. {
  1072. if (e.IsEmpty()) return this;
  1073. updTick = tick;
  1074. EntityId = e.EntityId;
  1075. if (e.Name.Length > 0) Name = e.Name;
  1076. Type = e.Type;
  1077. Orientation = e.Orientation;
  1078. Position = e.Position;
  1079. Velocity = e.Velocity;
  1080. BBox = e.BoundingBox;
  1081. Rel = e.Relationship;
  1082. if ((e.Type == MyDetectedEntityType.CharacterHuman || e.Type == MyDetectedEntityType.CharacterOther) && Name.Length == 0)
  1083. {
  1084. Name = "Suit";// + e.EntityId;
  1085. }
  1086. if (e.Type == MyDetectedEntityType.Unknown)
  1087. {//unknown means obstruction list generally
  1088. if (e.Name.StartsWith("MyVoxelMap"))
  1089. {
  1090. Type = MyDetectedEntityType.Asteroid;
  1091. Name = "Asteroid";
  1092. Rel = MyRelationsBetweenPlayerAndBlock.Neutral;
  1093. }
  1094. else if (e.Name.Length == 0)
  1095. {
  1096. var he = BBox.Max - BBox.Min;
  1097. //grids this small don't actually show up in obstruction list, only suits.
  1098. if (he.X < 3 && he.Y < 3 && he.Z < 3)
  1099. {
  1100. Type = MyDetectedEntityType.CharacterHuman;
  1101. Rel = MyRelationsBetweenPlayerAndBlock.Friends;
  1102. Name = "Suit";
  1103. }
  1104. }
  1105. else Rel = MyRelationsBetweenPlayerAndBlock.Neutral;
  1106. }
  1107. else if (e.Type == MyDetectedEntityType.Asteroid) Name = "Asteroid";
  1108. else if (e.Type == MyDetectedEntityType.Planet) Name = "Planet";
  1109. if (e.Type == MyDetectedEntityType.LargeGrid)
  1110. {
  1111. try
  1112. {
  1113. focus = gProgram.APIWC.GetAiFocus(EntityId).GetValueOrDefault();
  1114. }
  1115. catch (Exception) { }
  1116. }
  1117. return this;
  1118. }
  1119. const double rdivisor = 1.0d / 60.0d;
  1120. public DetectedEntity upd(MyDetectedEntityInfo e, float t)
  1121. {
  1122. upd(e);
  1123. threat = t;
  1124. if (Type == MyDetectedEntityType.SmallGrid)
  1125. {
  1126. if (e.Name.StartsWith("Small Grid")) isPMW = true;
  1127. else
  1128. {
  1129. var he = BBox.Max - BBox.Min;
  1130. if (he.X < 10 && he.Y < 10 && he.Z < 10) isPMW = true;
  1131. }
  1132. }
  1133. return this;
  1134. }
  1135. public Vector3D getEstPos()
  1136. {
  1137. if (updTick == tick) return Position;
  1138. return Position + (Velocity * (tick - updTick) * rdivisor);
  1139. }
  1140. }
  1141.  
  1142. Dictionary<long, DetectedEntity> detectedEntitiesD = new Dictionary<long, DetectedEntity>();
  1143.  
  1144. List<DetectedEntity> detectedEntitiesL = new List<DetectedEntity>();
  1145.  
  1146. void addDE(DetectedEntity e)
  1147. {
  1148. detectedEntitiesD[e.EntityId] = e;
  1149. detectedEntitiesL.Add(e);
  1150. }
  1151.  
  1152. void remDE(DetectedEntity e)
  1153. {
  1154. detectedEntitiesD.Remove(e.EntityId);
  1155. detectedEntitiesL.Remove(e);
  1156. }
  1157.  
  1158. int stale_threshold = 20;
  1159.  
  1160.  
  1161. string getColFromRel(MyRelationsBetweenPlayerAndBlock rel)
  1162. {
  1163. if (rel == MyRelationsBetweenPlayerAndBlock.Enemies) return Config.REC.Val;
  1164. else if (rel == MyRelationsBetweenPlayerAndBlock.Owner) return "blue";//never happens?
  1165. else if (rel == MyRelationsBetweenPlayerAndBlock.Friends || rel == MyRelationsBetweenPlayerAndBlock.FactionShare) return Config.RFC.Val;
  1166. else if (rel == MyRelationsBetweenPlayerAndBlock.Neutral) return Config.RNC.Val;
  1167. else return Config.ROC.Val;
  1168. }
  1169.  
  1170.  
  1171. //bool matchSpeed = false;
  1172. //DetectedEntity matchTarget = null;
  1173. //DetectedEntity rotateTarget = null;
  1174. //bool autoRotate = false;
  1175.  
  1176. string lastRadarStr = "";
  1177.  
  1178.  
  1179. int lastRUpdTick = -9000;
  1180.  
  1181. static Profiler radarP = new Profiler("radar");
  1182.  
  1183. IEnumerator<bool> __processRadar = null;
  1184.  
  1185. int fr = 1;
  1186.  
  1187. int rsteps = 0;
  1188.  
  1189. int rtix = 0;
  1190.  
  1191. //bool radar_firstrun = true;
  1192. public void processRadar(double maxMS, bool force=false)
  1193. {
  1194. abort_start = DateTime.Now;
  1195. max_time = maxMS;
  1196. radarP.s();
  1197. if ((tick - lastRUpdTick > 60 || force) && __processRadar == null)
  1198. {
  1199. /*if (radar_firstrun)
  1200. {
  1201. radar_firstrun = false;
  1202. bt60.setwait(0.05);
  1203. }
  1204. else*/
  1205. {
  1206. __processRadar = _processRadar();
  1207. lastRUpdTick = tick;
  1208. //if (fr > 0) log("radar init", LT.LOG_N);
  1209. }
  1210. }
  1211. if(__processRadar != null)
  1212. {
  1213. //DateTime s = DateTime.Now;
  1214. double r = 0;
  1215. bool fin = false;
  1216. do
  1217. {
  1218. fin = !__processRadar.MoveNext();
  1219. rsteps++;
  1220. //r = (DateTime.Now - s).TotalMilliseconds;
  1221. } while (!fin && !abort());
  1222. rtix++;
  1223.  
  1224. if (fin)
  1225. {
  1226. if (fr > 0)
  1227. {
  1228. fr--;
  1229.  
  1230. log("radar processed in " + rsteps + " steps, " + rtix + "t", LT.LOG_N);
  1231. rsteps = 0;
  1232. rtix = 0;
  1233. }
  1234. __processRadar.Dispose();
  1235. __processRadar = null;
  1236. }
  1237. }
  1238. radarP.e();
  1239. }
  1240.  
  1241.  
  1242. public IEnumerator<bool> _processRadar()
  1243. {
  1244. yield return true;
  1245. var my_id = gProgram.Me.CubeGrid.EntityId;
  1246. #region DATA UPDATE
  1247. {
  1248. var tickstart = tick;
  1249. yield return true;
  1250. var my_pos = Me.GetPosition();
  1251. focus = APIWC.GetAiFocus(my_id, 0).GetValueOrDefault();
  1252. yield return true;
  1253. if (focus.EntityId != lfocus)
  1254. {
  1255. lfocus = focus.EntityId;
  1256. focusChangeTick = tick;
  1257. }
  1258. WCobstructions.Clear();
  1259. APIWC.GetObstructions(Me, WCobstructions);
  1260. yield return true;
  1261.  
  1262. WCthreats.Clear();
  1263. APIWC.GetSortedThreats(WCthreats);
  1264. yield return true;
  1265. foreach (var o in WCobstructions)
  1266. {
  1267. if (!o.IsEmpty())
  1268. {
  1269. DetectedEntity de = null;
  1270. detectedEntitiesD.TryGetValue(o.EntityId, out de);
  1271. if (de != null) de.upd(o);
  1272. else addDE(new DetectedEntity().upd(o));
  1273. yield return true;
  1274. }
  1275. }
  1276. foreach (var kvp in WCthreats)
  1277. {
  1278. if (!kvp.Key.IsEmpty())
  1279. {
  1280. DetectedEntity de = null;
  1281. detectedEntitiesD.TryGetValue(kvp.Key.EntityId, out de);
  1282. if (de != null) de.upd(kvp.Key).threat = kvp.Value;
  1283. else
  1284. {
  1285. var n = new DetectedEntity();
  1286. n.upd(kvp.Key).threat = kvp.Value;
  1287. addDE(n);
  1288. }
  1289. yield return true;
  1290. }
  1291. }
  1292. List<DetectedEntity> del = new List<DetectedEntity>();
  1293. foreach (var e in detectedEntitiesL)
  1294. {
  1295. if (tickstart - e.updTick > stale_threshold) del.Add(e);
  1296. else
  1297. {
  1298. e.ldistSqr = e.distSqr;
  1299. e.distSqr = (my_pos - e.Position).LengthSquared();
  1300. }
  1301. yield return true;
  1302. }
  1303. foreach (var e in del)
  1304. {
  1305. remDE(e);
  1306. yield return true;
  1307. }
  1308. }
  1309. #endregion
  1310.  
  1311. #region RENDER
  1312. StringBuilder b = new StringBuilder();
  1313. {//matcher
  1314.  
  1315. var trg = APIWC.GetAiFocus(my_id).GetValueOrDefault();
  1316. yield return true;
  1317. if (matchSpeed)
  1318. {
  1319. b.Append("<color=white>!<color=green>SPEEDMATCHING");
  1320. if (trg.IsEmpty() || trg.Name != matchTarget.Name)
  1321. {
  1322. bapp(b, ":<color=", getColFromRel(matchTarget.Rel), ">", matchTarget.Name);
  1323. }
  1324. else b.Append(" ON");
  1325. b.Append("\n");
  1326. }
  1327. else b.Append("\n");
  1328. yield return true;
  1329.  
  1330. if (autoRotate)
  1331. {
  1332. b.Append("<color=white>!<color=lightblue>AUTOROTATING");
  1333. if (trg.IsEmpty() || trg.Name != rotateTarget.Name)
  1334. {
  1335. bapp(b, ":<color=", getColFromRel(rotateTarget.Rel), ">", rotateTarget.Name);
  1336. }
  1337. else b.Append(" ON");
  1338. b.Append("\n");
  1339. }
  1340. else b.Append("\n");
  1341. yield return true;
  1342.  
  1343. if (matchSpeed || !trg.IsEmpty())
  1344. {
  1345. Vector3D tp = Vector3D.Zero;
  1346. Vector3D tv = Vector3D.Zero;
  1347. if (!matchSpeed || (matchSpeed && trg.Name == matchTarget.Name))
  1348. {
  1349. tp = trg.Position;
  1350. tv = trg.Velocity;
  1351. }
  1352. else if (matchSpeed && matchTarget != null)
  1353. {
  1354. tp = matchTarget.getEstPos();
  1355. tv = matchTarget.Velocity;
  1356. }
  1357. yield return true;
  1358. if (tp != Vector3D.Zero)
  1359. {
  1360. var cpat = cpa_time(getPosition(), getVelocity(), tp, tv);
  1361. b.Append("<color=lightgray>CPA:");//, rotateTarget.Name);
  1362. if (cpat < 0) b.Append("moving away");
  1363. else
  1364. {
  1365. var mf = getPosition() + (getVelocity() * cpat);
  1366. var tf = tp + (tv * cpat);
  1367. var d = Vector3D.Distance(mf, tf);
  1368. bapp(b, dist2str(d), " in ", cpat.ToString("0.0"), "s");
  1369. }
  1370. b.Append("\n");
  1371. yield return true;
  1372. }
  1373. }
  1374. b.Append("\n");
  1375. if (!trg.IsEmpty())
  1376. {
  1377. double d = (trg.Position - getPosition()).Length();
  1378. bapp(b, "<color=lightgray>Target: <color=red>", trg.Name, " (", dist2str(d), ")\n");
  1379. }
  1380. else b.Append("<color=lightgray>Target: none\n");
  1381. yield return true;
  1382. }
  1383. {//railguns
  1384. if (subTargGroup.Count > 0)
  1385. {
  1386. foreach (var blk in subTargGroup)
  1387. {
  1388. var rdy = APIWC.IsWeaponReadyToFire(blk);
  1389. if (rdy) bapp(b, " <color=lightgreen>", blk.CustomName);
  1390. else
  1391. {
  1392. var ws = getWS(blk);
  1393. if (ws != null && ws.settings != null)
  1394. {
  1395. var timeleft = (1.0 - ws.chargeProgress) * ws.settings.chargeTicks / 60;
  1396. if (ws.lastDrawFactor != 0) timeleft /= ws.lastDrawFactor;
  1397. var chrgt = timeleft.ToString("0.0");
  1398.  
  1399. if (chrgt.Length < 3) b.Append(" ");
  1400. bapp(b, "<color=orange>", chrgt, "s ", blk.CustomName);
  1401. }
  1402. }
  1403. var t = APIWC.GetWeaponTarget(blk).GetValueOrDefault();
  1404. if (t.Type == MyDetectedEntityType.LargeGrid || t.Type == MyDetectedEntityType.SmallGrid) bapp(b, " ► ", t.Name);
  1405. else b.Append(" ► <color=lightgray>No target");
  1406. b.Append("\n");
  1407. yield return true;
  1408. }
  1409. }
  1410. }
  1411. {//movers
  1412. int PMWs = 0;
  1413. foreach (var e in detectedEntitiesL)
  1414. {
  1415. if (e.isPMW) PMWs++;
  1416. }
  1417. var plo = APIWC.GetProjectilesLockedOn(my_id);
  1418. var plocked = plo.Item2;
  1419. if (plocked > 0)
  1420. {
  1421. bapp(b, "<color=white>!<color=red>INBOUND TORPS:<color=white>", plocked, "\n");
  1422. }
  1423. if (PMWs > 0)
  1424. {
  1425. bapp(b, "<color=white>!<color=red>Probable PMWs:<color=white>", PMWs, "\n");
  1426. }
  1427. b.Append("\n");
  1428. yield return true;
  1429. }
  1430. {//detected entities
  1431. for (int i = 0; i < detectedEntitiesL.Count; i++)
  1432. {
  1433. var e = detectedEntitiesL[i];
  1434.  
  1435. bapp(b, "<color=", getColFromRel(e.Rel), ">");
  1436.  
  1437. bapp(b, e.Name, " (", dist2str(Math.Sqrt(e.distSqr)), ")");
  1438. string thrt;
  1439. if (e.threat < 0.0001) thrt = "0";
  1440. else if (e.threat > 0.1) thrt = e.threat.ToString("0.0");
  1441. else if (e.threat > 0.01) thrt = e.threat.ToString("0.00");
  1442. else thrt = "<0.01";
  1443.  
  1444. if (e.Rel == MyRelationsBetweenPlayerAndBlock.Enemies) b.Append(" t:" + thrt);
  1445.  
  1446. bapp(b, " v:", dist2str(e.Velocity.Length()), "/s");
  1447. yield return true;
  1448. if (!e.focus.IsEmpty())
  1449. {
  1450. b.Append("\n └target:");
  1451. if (e.focus.Relationship == MyRelationsBetweenPlayerAndBlock.Friends) b.Append("<color=lightgreen>");
  1452. else b.Append("<color=lightgray>");
  1453. b.Append(e.focus.Name);
  1454. }
  1455. b.Append("\n");
  1456. yield return true;
  1457. }
  1458. }
  1459. var str = b.ToString();
  1460. if(str != lastRadarStr)
  1461. {
  1462. lastRadarStr = str;
  1463. if (statusLogSprite == null) statusLogSprite = new SpriteHUDLCD(statusLog);
  1464. statusLogSprite.s = statusLog;
  1465. statusLogSprite.setLCD(str);
  1466. }
  1467. #endregion
  1468.  
  1469. yield return false;
  1470. }
  1471.  
  1472. SpriteHUDLCD statusLogSprite = null;
  1473.  
  1474.  
  1475.  
  1476.  
  1477.  
  1478.  
  1479. public static string dist2str(double d)
  1480. {
  1481. if (d > 1000)
  1482. {
  1483. return (d / 1000).ToString("0.0") + "km";
  1484. }
  1485. else return d.ToString("0") + "m";
  1486. }
  1487.  
  1488. static public Program gProgram = null;
  1489.  
  1490. public WcPbApi APIWC = null;
  1491.  
  1492.  
  1493. bool constructor = true;
  1494.  
  1495. DateTime abort_start = DateTime.Now;
  1496.  
  1497. double max_time = 0;
  1498.  
  1499. bool abort()
  1500. {
  1501. if(constructor)return Runtime.CurrentInstructionCount > (Runtime.MaxInstructionCount - 1000);
  1502. else
  1503. {
  1504. return (DateTime.Now - abort_start).TotalMilliseconds > max_time;
  1505. }
  1506. }
  1507.  
  1508. public Program()
  1509. {
  1510. try
  1511. {
  1512. gProgram = this;
  1513. }catch(Exception e)
  1514. {
  1515. Echo(e.ToString());
  1516. return;
  1517. }
  1518. constructor = true;
  1519. mainP.start();
  1520. var mic = Runtime.MaxInstructionCount.ToString();
  1521. configChk();
  1522. gProgram = this;
  1523. Config = new Config_();
  1524. gyroECU = new GyroECU5();
  1525. log("BOOT", LT.LOG_N);
  1526. Runtime.UpdateFrequency = UpdateFrequency.Update1;
  1527. if (abort()) return;
  1528. log("-0:"+Runtime.CurrentInstructionCount.ToString() + "/" + mic, LT.LOG_N);
  1529. loadBlocks(0);
  1530. log("-1:" + Runtime.CurrentInstructionCount.ToString() + "/" + mic, LT.LOG_N);
  1531. if (abort()) return;
  1532. processRadar(0,true);
  1533. log("-2:" + Runtime.CurrentInstructionCount.ToString() + "/" + mic, LT.LOG_N);
  1534. processHeat(0, true);
  1535. log("-3:" + Runtime.CurrentInstructionCount.ToString() + "/" + mic, LT.LOG_N);
  1536. Echo("Program();");
  1537. constructor = false;
  1538. mainP.stop();
  1539. BurnoutTrack.NOP = true;
  1540. Main("", UpdateType.Update1);
  1541. BurnoutTrack.NOP = false;
  1542. log("-e:" + Runtime.CurrentInstructionCount.ToString() + "/" + mic, LT.LOG_N);
  1543. }
  1544.  
  1545. GyroECU5 gyroECU = null;
  1546.  
  1547. public void Save()
  1548. {
  1549. // This method is called whenever the script might cease for any reason, be it pblimiter burnout (depending on pblimiter settings), disabled block, save, power failure, etc.
  1550. //so let's release gyros and thrusters here. If the script is still going, it'll take them back if necessary next tick.
  1551. if (matchSpeed || autoRotate) foreach (var g in gyros) g.GyroOverride = false;
  1552. if (matchSpeed) foreach (var t in thrusters) t.ThrustOverride = 0;
  1553. if (matchSpeed && getCtrl().DampenersOverride)
  1554. {
  1555. getCtrl().DampenersOverride = false;
  1556. save_putdampon = true;
  1557. //we don't want a burnout while grinding some npc to send us rocketing into it
  1558. //this will flick it back on in a moment, if it turns out we're not being destroyed by pblimiter here
  1559. }
  1560. gProgram = null;
  1561. }
  1562.  
  1563. bool save_putdampon = false;
  1564.  
  1565.  
  1566. public static int tick = -1;
  1567.  
  1568. const double maxScriptTimeMSPerSec = 0.25;
  1569.  
  1570. BurnoutTrack bt60 = new BurnoutTrack(60, maxScriptTimeMSPerSec);
  1571.  
  1572.  
  1573. static Profiler initP = new Profiler("init");
  1574.  
  1575. static Profiler mainP = new Profiler("main");
  1576.  
  1577. #region premain
  1578. public void Main(string arg, UpdateType upd)
  1579. {
  1580. constructor = false;
  1581. gProgram = this;
  1582. tick += 1;
  1583. #region burnoutfailsafepre
  1584. if (bt60.burnoutpre()) return;
  1585. #endregion
  1586.  
  1587. if (tick % 20 == 0) if (Me.Closed)
  1588. {
  1589. Runtime.UpdateFrequency = UpdateFrequency.None;
  1590. return;
  1591. }
  1592. mainP.start();
  1593. main(arg, upd);
  1594. mainP.stop();
  1595. if (tick % 5 == 0)
  1596. {
  1597. Echo(tick.ToString());
  1598. if (profileLog != null) profileLog.WriteText("name:ms1t:ms60t\n" + Profiler.getAllReports());
  1599. }
  1600. if (consoleLog != null && tick % 5 == 0)
  1601. {
  1602. if (Logger.loggedMessagesDirty)
  1603. {
  1604. Logger.updateLoggedMessagesRender();
  1605. consoleLog.WriteText(Logger.loggedMessagesRender);
  1606. }
  1607. }
  1608. #region burnoutfailsafepost
  1609. if (bt60.burnoutpost()) return;
  1610. #endregion
  1611. }
  1612.  
  1613.  
  1614. #endregion
  1615. void main(string arg, UpdateType upd)
  1616. {
  1617. //if (tick == 1) return;
  1618. configChk();
  1619. initP.start();
  1620. var loaded = loadBlocks(0.05);
  1621. initP.stop();
  1622. if (!loaded) return;
  1623.  
  1624. processRadar(0.025);
  1625. processHeat(0.025);
  1626.  
  1627. //thrustScan();
  1628. //updRadar();
  1629. weaponDesync();
  1630. //updatePDCNets();
  1631. railchargeupdate();
  1632. //grinder_update();
  1633. speedmatch_upd();
  1634. autorot_update();
  1635. gyroECU.update();
  1636. //ammoPull();
  1637. //fuelPull();
  1638.  
  1639.  
  1640. if (arg == "resetConfig")
  1641. {
  1642. resetConfig();
  1643. Me.CustomData = lastCustomData = serializeConfig();
  1644. }
  1645. else if (arg.StartsWith("match")) speedMatch(arg);
  1646. else if (arg == "lookat") toggleAutorotate(false);
  1647. else if (arg == "rlookat") toggleAutorotate(true);
  1648. else if (arg == "turnonall")
  1649. {
  1650. List<IMyFunctionalBlock> tmp = new List<IMyFunctionalBlock>();
  1651. GridTerminalSystem.GetBlocksOfType<IMyFunctionalBlock>(tmp, b => b.IsSameConstructAs(Me) && !(b is IMyShipGrinder) && !(b is IMyShipWelder));
  1652. foreach (var b in tmp) b.Enabled = true;
  1653. }
  1654.  
  1655.  
  1656.  
  1657. if (save_putdampon)
  1658. {
  1659. save_putdampon = false;
  1660. getCtrl().DampenersOverride = true;
  1661. }
  1662. //MyIni x = new MyIni();
  1663. //x.Get("","").
  1664. }
  1665.  
  1666. static void bapp(StringBuilder b, params object[] args)
  1667. {
  1668. foreach (object a in args)
  1669. {
  1670. b.Append(a.ToString());
  1671. }
  1672. }
  1673.  
  1674. public class Stopwatch
  1675. {
  1676. DateTime start;
  1677. public Stopwatch()
  1678. {
  1679. start = DateTime.Now;
  1680. }
  1681. public double e()
  1682. {
  1683. return (DateTime.Now - start).TotalMilliseconds;
  1684. }
  1685. }
  1686.  
  1687.  
  1688.  
  1689. public class Profiler
  1690. {
  1691.  
  1692.  
  1693. static bool PROFILING_ENABLED = true;
  1694. static List<Profiler> profilers = new List<Profiler>();
  1695. const int mstracklen = 60;
  1696. double[] mstrack = new double[mstracklen];
  1697. double msdiv = 1.0d / mstracklen;
  1698. int mscursor = 0;
  1699. DateTime start_time = DateTime.MinValue;
  1700. string Name = "";
  1701. string pre = "";
  1702. string post = "";
  1703. int _ticks_between_calls = 1;
  1704. int ltick = int.MinValue;
  1705. //..int callspertick = 1;
  1706.  
  1707. static int base_sort_position_c = 0;
  1708. int base_sort_position = 0;
  1709.  
  1710. bool nevercalled = true;
  1711. //bool closed = true;
  1712. public int getSortPosition()
  1713. {
  1714. if (nevercalled) return int.MaxValue;
  1715. int mult = (int)Math.Pow(10, 8 - (depth * 2));
  1716. if (parent != null) return parent.getSortPosition() + (base_sort_position * mult);
  1717. return base_sort_position * mult;
  1718. }
  1719. static int basep = (int)Math.Pow(10, 5);
  1720. public Profiler(string name)
  1721. {
  1722. if (PROFILING_ENABLED)
  1723. {
  1724. Name = name;
  1725. profilers.Add(this);
  1726. for(var i =0; i < mstracklen; i++)mstrack[i] = 0;
  1727. base_sort_position = base_sort_position_c;
  1728. base_sort_position_c += 1;
  1729. }
  1730. }
  1731. public void s()
  1732. {
  1733. start();
  1734. }
  1735. public void e()
  1736. {
  1737. stop();
  1738. }
  1739. static List<Profiler> stack = new List<Profiler>();
  1740. Profiler parent = null;
  1741. int depth = 0;
  1742. bool adding = false;
  1743. public void start()
  1744. {
  1745. if (PROFILING_ENABLED)
  1746. {
  1747. //closed = false;
  1748. nevercalled = false;
  1749. if (tick != ltick)
  1750. {
  1751. if (_ticks_between_calls == 1 && ltick != int.MinValue)
  1752. {
  1753. _ticks_between_calls = tick - ltick;
  1754. }else
  1755. {
  1756. var tbc = tick - ltick;
  1757. if (tbc != _ticks_between_calls)
  1758. {
  1759. _ticks_between_calls = 1;
  1760. for (var i = 0; i < mstracklen; i++) mstrack[i] = 0;
  1761. }
  1762. }
  1763.  
  1764. ltick = tick;
  1765. //callspertick = 1;
  1766. adding = false;
  1767. }
  1768. else
  1769. {
  1770. adding = true;
  1771. }
  1772. if (depth == 0) depth = stack.Count;
  1773. if (depth > 11) depth = 11;
  1774. if (stack.Count > 0 && parent == null) parent = stack[stack.Count - 1];
  1775. stack.Add(this);
  1776. start_time = DateTime.Now;
  1777. }
  1778. }
  1779. double lastms = 0;
  1780. double average = 0;
  1781.  
  1782.  
  1783. /// <summary>
  1784. /// records a fake ms consumption for this timeframe - for tests or demo
  1785. /// </summary>
  1786. public double FAKE_stop(double fakems)
  1787. {
  1788. return stop(fakems);
  1789. }
  1790. /// <summary>
  1791. /// adds the elapsed time since start() to the records
  1792. /// </summary>
  1793. public double stop()
  1794. {
  1795. double time = 0;
  1796. if (PROFILING_ENABLED)
  1797. {
  1798. //closed = true;
  1799. time = (DateTime.Now - start_time).TotalMilliseconds;
  1800. }
  1801. return stop(time);
  1802. }
  1803.  
  1804. private double stop(double _ms)
  1805. {
  1806. double time = 0;
  1807. if (PROFILING_ENABLED)
  1808. {
  1809. time = _ms;
  1810.  
  1811. stack.Pop();
  1812. if (parent != null)
  1813. {
  1814. depth = parent.depth + 1;
  1815. }
  1816.  
  1817. //if(!adding)mscursor = (mscursor + 1) % mstracklen;
  1818.  
  1819.  
  1820. if (!adding) mstrack[mscursor] = 0;
  1821. mstrack[mscursor] += time;
  1822. if (!adding) mscursor = (mscursor + 1) % mstracklen;
  1823.  
  1824. average = 0d;
  1825. foreach (double ms in mstrack) average += ms;
  1826. average *= msdiv;
  1827. average /= _ticks_between_calls;
  1828. lastms = time;
  1829. }
  1830. return time;
  1831. }
  1832. /// <summary>
  1833. /// generates a monospaced report text. If called every tick, every 120 ticks it will recalculate treeview data.
  1834. /// </summary>
  1835. //the treeview can be initially inaccurate as some profilers might not be called every tick, depending on program architecture
  1836. public string getReport(StringBuilder bu)
  1837. {
  1838. if (PROFILING_ENABLED)
  1839. {
  1840. if (tick % 120 == 25)//recalculate hacky treeview data, delayed by 25 ticks from program start
  1841. {
  1842. try
  1843. {
  1844. profilers.Sort(delegate (Profiler x, Profiler y)
  1845. {
  1846. return x.getSortPosition().CompareTo(y.getSortPosition());
  1847. });
  1848. }
  1849. catch (Exception) { }
  1850.  
  1851. for (int i = 0; i < profilers.Count; i++)
  1852. {
  1853. Profiler p = profilers[i];
  1854.  
  1855. p.pre = "";
  1856. if (p.depth > 0 && p.parent != null)
  1857. {
  1858. bool parent_has_future_siblings = false;
  1859. bool has_future_siblings_under_parent = false;
  1860. for (int b = i + 1; b < profilers.Count; b++)
  1861. {
  1862. if (profilers[b].depth == p.parent.depth) parent_has_future_siblings = true;
  1863. if (profilers[b].depth == p.depth) has_future_siblings_under_parent = true;
  1864. if (profilers[b].depth < p.depth) break;
  1865.  
  1866. }
  1867. while (p.pre.Length < p.parent.depth)
  1868. {
  1869. if (parent_has_future_siblings) p.pre += "│";
  1870. else p.pre += " ";
  1871. }
  1872. bool last = false;
  1873.  
  1874. if (!has_future_siblings_under_parent)
  1875. {
  1876. if (i < profilers.Count - 1)
  1877. {
  1878. if (profilers[i + 1].depth != p.depth) last = true;
  1879. }
  1880. else last = true;
  1881. }
  1882. if (last) p.pre += "└";
  1883. else p.pre += "├";
  1884. while (p.pre.Length < p.depth) p.pre += "─";
  1885. }
  1886. }
  1887. int mlen = 0;
  1888. foreach (Profiler p in profilers) if (p.pre.Length + p.Name.Length > mlen) mlen = p.pre.Length + p.Name.Length;
  1889. foreach (Profiler p in profilers)
  1890. {
  1891. p.post = "";
  1892. int l = p.pre.Length + p.Name.Length + p.post.Length;
  1893. if (l < mlen) p.post = new string('_', mlen - l);
  1894. }
  1895. }
  1896. if (nevercalled) bapp(bu, "!!!!", Name , "!!!!: NEVER CALLED!");
  1897. else bapp(bu, pre, Name, post, ": " , lastms.ToString("0.00") , ";", average.ToString("0.00"));
  1898. }
  1899. return "";
  1900. }
  1901. static public string getAllReports()
  1902. {
  1903. StringBuilder b = new StringBuilder();
  1904. //string r = "";
  1905. if (PROFILING_ENABLED)
  1906. {
  1907. foreach (Profiler watch in profilers)
  1908. {
  1909. watch.getReport(b);
  1910. b.Append("\n");
  1911. }
  1912. }
  1913. if (stack.Count > 0)
  1914. {
  1915. bapp(b,"profile stack error:\n", stack.Count, "\n");
  1916. foreach (var s in stack)
  1917. {
  1918. bapp(b, s.Name, ",");
  1919. }
  1920. }
  1921. return b.ToString();
  1922. }
  1923. }
  1924.  
  1925. public enum LT
  1926. {
  1927. LOG_N = 0,
  1928. LOG_D,
  1929. LOG_DD
  1930. }
  1931.  
  1932. string[] logtype_labels = { "INFO","_DBG","DDBG"};
  1933.  
  1934.  
  1935. public static LT LOG_LEVEL = LT.LOG_N;
  1936.  
  1937. public static Logger logger = new Logger();
  1938.  
  1939. public static void log(string s, LT level)
  1940. {
  1941. Logger.log(s, level);
  1942. }
  1943.  
  1944. public static void log(string s)
  1945. {
  1946. Logger.log(s, LT.LOG_N);
  1947. }
  1948.  
  1949.  
  1950. public class Logger
  1951. {
  1952. public class logmsg
  1953. {
  1954. public logmsg(string m,string m2, LT l) { msg = m; msg_raw = m2; level = l; }
  1955. public string msg = "";
  1956. public string msg_raw = "";
  1957. public int c = 1;
  1958. public LT level = LT.LOG_N;
  1959. }
  1960.  
  1961. static List<logmsg> loggedMessages = new List<logmsg>();
  1962. static int MAX_LOG = 50;
  1963. static List<logmsg> superLoggedMessages = new List<logmsg>();
  1964. static int MAX_SUPER_LOG = 1000;
  1965.  
  1966. static public bool loggedMessagesDirty = true;
  1967.  
  1968. public static void log(string s, LT level)
  1969. {
  1970. if (level > LOG_LEVEL) return;
  1971. string s2 = s;
  1972. if (s.Length > 50)
  1973. {
  1974. List<string> tok = new List<string>();
  1975. while (s.Length > 50)
  1976. {
  1977. int c = 0;
  1978. if (tok.Count > 0) c = 2;
  1979. tok.Add(s.Substring(0, 50 - c));
  1980. s = s.Substring(50 - c);
  1981. }
  1982. tok.Add(s);
  1983. s = string.Join("\n ", tok);
  1984. }
  1985. var p = gProgram;
  1986. logmsg l = null;
  1987. if (loggedMessages.Count > 0)
  1988. {
  1989. l = loggedMessages[loggedMessages.Count - 1];
  1990. }
  1991. if (l != null)
  1992. {
  1993. if (l.msg == s) l.c += 1;
  1994. else loggedMessages.Add(new logmsg(s, s2, level));
  1995. }
  1996. else loggedMessages.Add(new logmsg(s, s2, level));
  1997. if (loggedMessages.Count > MAX_LOG) loggedMessages.RemoveAt(0);
  1998.  
  1999. l = null;
  2000. if (superLoggedMessages.Count > 0)
  2001. {
  2002. l = superLoggedMessages[superLoggedMessages.Count - 1];
  2003. }
  2004. if (l != null)
  2005. {
  2006. if (l.msg == s) l.c += 1;
  2007. else superLoggedMessages.Add(new logmsg(s, s2, level));
  2008. }
  2009. else superLoggedMessages.Add(new logmsg(s, s2, level));
  2010. if (superLoggedMessages.Count > MAX_SUPER_LOG) superLoggedMessages.RemoveAt(0);
  2011.  
  2012. loggedMessagesDirty = true;
  2013. }
  2014.  
  2015.  
  2016. static public string loggedMessagesRender = "";
  2017. static public void updateLoggedMessagesRender()
  2018. {
  2019. if (!loggedMessagesDirty) return;
  2020. StringBuilder b = new StringBuilder();
  2021. //if (!loggedMessagesDirty) return;// loggedMessagesRender;
  2022.  
  2023.  
  2024. foreach (var m in loggedMessages)
  2025. {
  2026. b.Append(m.msg);
  2027. if (m.c > 1) bapp(b," (" ,m.c ,")");
  2028. b.Append("\n");
  2029. }
  2030. string o = b.ToString();
  2031. loggedMessagesDirty = false;
  2032. loggedMessagesRender = o;
  2033. }
  2034. /*static public void writeSuperlog()
  2035. {
  2036. StringBuilder b = new StringBuilder();
  2037. //if (!loggedMessagesDirty) return;// loggedMessagesRender;
  2038.  
  2039.  
  2040. foreach (var m in superLoggedMessages)
  2041. {
  2042. b.Append(m.msg);
  2043. if (m.c > 1) bapp(b, " (", m.c, ")");
  2044. b.Append("\n");
  2045. }
  2046. string o = b.ToString();
  2047. controllers[0].CustomData = o;
  2048. log(controllers[0].CustomName, LT.LOG_N);
  2049. }*/
  2050. }
  2051.  
  2052. IMyTextSurface consoleLog = null;
  2053.  
  2054. IMyTextSurface statusLog = null;
  2055.  
  2056. IMyTextSurface profileLog = null;
  2057.  
  2058. IMyTextSurface PDCLog = null;
  2059.  
  2060.  
  2061. List<IMyTerminalBlock> weaponCoreWeapons = new List<IMyTerminalBlock>();
  2062.  
  2063.  
  2064. List<IMyPowerProducer> powergens = new List<IMyPowerProducer>();
  2065.  
  2066.  
  2067. List<IMyShipController> controllers = new List<IMyShipController>();
  2068.  
  2069.  
  2070. List<IMyGyro> gyros = new List<IMyGyro>();
  2071.  
  2072.  
  2073. List<IMyTerminalBlock> grinders = new List<IMyTerminalBlock>();
  2074.  
  2075.  
  2076. List<IMyGasGenerator> extractors = new List<IMyGasGenerator>();
  2077.  
  2078. List<IMyGasTank> tanks_hydrogen = new List<IMyGasTank>();
  2079.  
  2080.  
  2081.  
  2082. List<IMyAssembler> assemblers = new List<IMyAssembler>();
  2083.  
  2084.  
  2085. List<IMyTerminalBlock> inventoryBlocks = new List<IMyTerminalBlock>();
  2086.  
  2087.  
  2088. List<IMyCargoContainer> loot_cargos = new List<IMyCargoContainer>();
  2089.  
  2090. List<IMyShipConnector> connectors = new List<IMyShipConnector>();
  2091.  
  2092.  
  2093. //List<IMyFunctionalBlock> torpedoGroup = new List<IMyFunctionalBlock>();
  2094. List<IMyFunctionalBlock> desyncGroup = new List<IMyFunctionalBlock>();
  2095.  
  2096. List<IMyFunctionalBlock> subTargGroup = new List<IMyFunctionalBlock>();
  2097.  
  2098.  
  2099.  
  2100. List<IMyFunctionalBlock> PDCGroup = new List<IMyFunctionalBlock>();
  2101.  
  2102.  
  2103. Dictionary<string, List<IMyFunctionalBlock>> PDCBlockGroups = new Dictionary<string, List<IMyFunctionalBlock>>();
  2104.  
  2105. List<string> PDCBlockGroupK = new List<string>();
  2106.  
  2107.  
  2108.  
  2109. List<IMyThrust> _thrusters = new List<IMyThrust>();
  2110.  
  2111. List<IMyThrust> thrusters = new List<IMyThrust>();
  2112.  
  2113.  
  2114. static Dictionary<Base6Directions.Direction, double> thrustByDir = new Dictionary<Base6Directions.Direction, double>();
  2115.  
  2116. static Dictionary<Base6Directions.Direction, List<IMyThrust>> thrustersByDir = new Dictionary<Base6Directions.Direction, List<IMyThrust>>();
  2117.  
  2118. static Dictionary<IMyThrust, double> thrusterMaxEffectiveThrust = new Dictionary<IMyThrust, double>();
  2119.  
  2120. void updateMET()
  2121. {
  2122. thrusterMaxEffectiveThrust.Clear();
  2123. foreach (var t in thrusters)
  2124. {
  2125. var met = t.MaxEffectiveThrust;
  2126. thrusterMaxEffectiveThrust[t] = met;
  2127. }
  2128. }
  2129.  
  2130. readonly Array directions = Enum.GetValues(typeof(Base6Directions.Direction));
  2131.  
  2132. void updateThrustByDir()
  2133. {
  2134. foreach (var d in directions)
  2135. {
  2136. var k = (Base6Directions.Direction)d;
  2137. thrustByDir[k] = 0;
  2138. if (!thrustersByDir.ContainsKey(k)) thrustersByDir[k] = new List<IMyThrust>();
  2139. else thrustersByDir[k].Clear();
  2140. }
  2141. foreach (var t in thrusters)
  2142. {
  2143.  
  2144. var met = thrusterMaxEffectiveThrust[t];
  2145. var f = t.Orientation.Forward;
  2146. thrustByDir[f] += met;
  2147. thrustersByDir[f].Add(t);
  2148. }
  2149. var th = 0d;
  2150.  
  2151. foreach (var kvp in thrustByDir)
  2152. {
  2153. if (kvp.Value > th)
  2154. {
  2155. th = kvp.Value;
  2156. }
  2157. }
  2158. }
  2159.  
  2160.  
  2161. static bool addIfT<T>(IMyTerminalBlock b, List<T> l) where T : class
  2162. {
  2163. T t = b as T;
  2164. if (t != null)
  2165. {
  2166. l.Add(t);
  2167. return true;
  2168. }
  2169. return false;
  2170. }
  2171.  
  2172. bool isThis(IMyTerminalBlock b)
  2173. {
  2174. return b.OwnerId == Me.OwnerId && b.CubeGrid == Me.CubeGrid;
  2175. }
  2176.  
  2177. int loadstep = 0;
  2178.  
  2179. IEnumerator<bool> blockLoad = null;
  2180.  
  2181. public bool loaded = false;
  2182.  
  2183. public double lastMS = 0;
  2184.  
  2185. public bool loadBlocks(double maxMS)
  2186. {
  2187. abort_start = DateTime.Now;
  2188. max_time = maxMS;
  2189. //bool abort = false;
  2190. //DateTime s = DateTime.Now;
  2191. if (!loaded)
  2192. {
  2193. if (blockLoad == null) blockLoad = blockLoader();
  2194. double r = 0;
  2195. do
  2196. {
  2197. loaded = !blockLoad.MoveNext();
  2198. loadstep++;
  2199. //abort = abort();
  2200. //r = (DateTime.Now - s).TotalMilliseconds;
  2201. } while (!loaded && !abort());
  2202. lastMS = r;
  2203. if (loaded)
  2204. {
  2205. blockLoad.Dispose();
  2206. blockLoad = null;
  2207. log("Blockload completed in " + loadstep + " steps, " + tick + "t", LT.LOG_N);
  2208. }
  2209. }
  2210. return loaded;
  2211. }
  2212.  
  2213.  
  2214.  
  2215.  
  2216. public IEnumerator<bool> blockLoader()
  2217. {
  2218. yield return true;
  2219. if (APIWC == null)
  2220. {
  2221. APIWC = new WcPbApi();
  2222. try
  2223. {
  2224. APIWC.Activate(Me);
  2225. }
  2226. catch (Exception) { }
  2227. if (!APIWC.isReady) log("Unable to load WeaponCore PBAPI?", LT.LOG_N);
  2228. }
  2229. yield return true;
  2230. var gts = GridTerminalSystem;
  2231. List<IMyTerminalBlock> allBlocks = new List<IMyTerminalBlock>();
  2232. yield return true;
  2233. gts.GetBlocks(allBlocks);
  2234. int allBlocksLength = allBlocks.Count;
  2235. for (int i = 0; i < allBlocksLength; i++)
  2236. {
  2237. yield return true;
  2238. var b = allBlocks[i];
  2239. //bool m = false;
  2240. if (isThis(b))
  2241. {
  2242. if (APIWC.HasCoreWeapon(b)) weaponCoreWeapons.Add(b);
  2243. var lcd = b as IMyTextSurface;
  2244. if (lcd != null)
  2245. {
  2246. if (statusLog == null && b.CustomData.Contains("radarLog"))
  2247. {
  2248. statusLog = lcd;
  2249. continue;
  2250. }
  2251. else if (consoleLog == null && b.CustomData.Contains("consoleLog"))
  2252. {
  2253. consoleLog = lcd;
  2254. continue;
  2255. }
  2256. else if (profileLog == null && b.CustomData.Contains("profileLog"))
  2257. {
  2258. profileLog = lcd;
  2259. continue;
  2260. }
  2261. else if (PDCLog == null && b.CustomData.Contains("PDCLog"))
  2262. {
  2263. PDCLog = lcd;
  2264. continue;
  2265. }
  2266. }
  2267.  
  2268. yield return true;
  2269. if (b.InventoryCount > 0)
  2270. {
  2271. inventoryBlocks.Add(b);
  2272. yield return true;
  2273. }
  2274. if (addIfT(b, controllers)) continue;
  2275. yield return true;
  2276. if (addIfT(b, gyros)) continue;
  2277. yield return true;
  2278. if (addIfT(b, connectors)) continue;
  2279. yield return true;
  2280. if (addIfT(b, powergens)) continue;
  2281. yield return true;
  2282. var deftxt = b.DefinitionDisplayNameText;
  2283.  
  2284. if (deftxt.Contains("Grinder"))
  2285. {
  2286. grinders.Add(b);
  2287. continue;
  2288. }
  2289. yield return true;
  2290. if (b is IMyGasGenerator && (deftxt == "Extractor" || deftxt == "Small Fuel Extractor"))
  2291. {
  2292. extractors.Add((IMyGasGenerator)b);
  2293. continue;
  2294. }
  2295. yield return true;
  2296. if (b is IMyGasTank && deftxt.Contains("Hydrogen"))
  2297. {
  2298. tanks_hydrogen.Add((IMyGasTank)b);
  2299. continue;
  2300. }
  2301. }
  2302. else if (b is IMyThrust && b.CubeGrid == Me.CubeGrid)
  2303. {
  2304. _thrusters.Add((IMyThrust)b);
  2305. thrusters.Add((IMyThrust)b);
  2306. }
  2307. }
  2308.  
  2309. List<IMyBlockGroup> bgs = new List<IMyBlockGroup>();
  2310. gts.GetBlockGroups(bgs);
  2311. int l = bgs.Count;
  2312. for (int gi = 0; gi < bgs.Count; gi++)
  2313. {
  2314. yield return true;
  2315. var bg = bgs[gi];
  2316. var n = bg.Name;
  2317. if (n == Config.PDCGroup.Val) bg.GetBlocksOfType(PDCGroup);
  2318. if (n == Config.WeaponDesync.Val) bg.GetBlocksOfType(desyncGroup);
  2319. if (n == Config.RSubtarget.Val) bg.GetBlocksOfType(subTargGroup);
  2320.  
  2321.  
  2322. if (n.StartsWith("PDCGroup"))
  2323. {
  2324. yield return true;
  2325.  
  2326. List<IMyFunctionalBlock> blox = new List<IMyFunctionalBlock>();
  2327. bg.GetBlocksOfType(blox);
  2328. List<IMyFunctionalBlock> k = new List<IMyFunctionalBlock>();
  2329. foreach (var b in blox)
  2330. {
  2331. if (weaponCoreWeapons.Contains(b))
  2332. {
  2333. if (PDCDataSubType.ContainsKey(b.DefinitionDisplayNameText)) k.Add(b);
  2334. else log("unknown pdc type \"" + b.DefinitionDisplayNameText + "\"");
  2335. }
  2336. yield return true;
  2337. }
  2338. PDCBlockGroups[bg.Name] = k;
  2339. PDCBlockGroupK.Add(bg.Name);
  2340. yield return true;
  2341. }
  2342. //
  2343. //else if (n == "Torps") bg.GetBlocksOfType(torpedoGroup);
  2344. }
  2345. if (PDCBlockGroupK.Count == 0 && PDCGroup.Count != 0)
  2346. {
  2347. PDCBlockGroups[Config.PDCGroup.Val] = PDCGroup;
  2348. PDCBlockGroupK.Add(Config.PDCGroup.Val);
  2349. }
  2350. updPDCNetGroups();
  2351. yield return false;
  2352. }
  2353.  
  2354.  
  2355. List<PDCNetGroup> PDCNetGroups = new List<PDCNetGroup>();
  2356.  
  2357. void updPDCNetGroups()
  2358. {
  2359. foreach (var kvp in PDCBlockGroups)
  2360. {
  2361. var t = kvp.Key.Split(' ');
  2362. PDCNetGroup group = new PDCNetGroup();
  2363. group.bgroup = kvp.Key;
  2364. if (t.Length > 1) group.name = t[1];
  2365. if (t.Length > 2 && t[2].ToLower() == "sided") group.sided = true;
  2366. bool exist = false;
  2367. foreach (var g in PDCNetGroups)
  2368. {
  2369. if (g.name == group.name && g.sided == group.sided && g.bgroup == group.bgroup)
  2370. {
  2371. exist = true;
  2372. break;
  2373. }
  2374. }
  2375. if (!exist)
  2376. {
  2377. PDCNetGroups.Add(group);
  2378. }
  2379. }
  2380. }
  2381.  
  2382. public class GyroECU5
  2383. {
  2384. public static double gyroMaxRPM = Math.PI;
  2385.  
  2386. public double angleMultiplier = 1;
  2387.  
  2388. bool firstrun = true;
  2389.  
  2390. public GyroECU5() : base()
  2391. {
  2392. }
  2393. void init()
  2394. {
  2395. angleMultiplier = gProgram.Me.CubeGrid.GridSizeEnum == VRage.Game.MyCubeSize.Small ? 2 : 1;
  2396. gyroMaxRPM *= angleMultiplier;
  2397. firstrun = false;
  2398. }
  2399.  
  2400.  
  2401. double lastAngleRoll, lastAnglePitch, lastAngleYaw;
  2402. double lMPTRoll, lMPTPitch, lMPTYaw;
  2403.  
  2404. public bool active = false;
  2405. Vector3D targetPosition;
  2406. Vector3D targetVelocity;//currently unused
  2407.  
  2408. Vector3D targetHeading;
  2409. Vector3D targetUp;
  2410.  
  2411. public int startTick;
  2412. public int ticksOnTarget = 0;
  2413. private void flush()
  2414. {
  2415. var p = gProgram;
  2416. if (firstrun) init();
  2417. if (!active)
  2418. {
  2419. active = true;
  2420. foreach (var g in p.gyros) g.GyroOverride = false;
  2421. lG = null;
  2422. startTick = tick;
  2423. lastAngleRoll = lastAnglePitch = lastAngleYaw = 0;
  2424. lMPTRoll = lMPTPitch = lMPTYaw = 0;
  2425. ticksOnTarget = 0;
  2426. }
  2427. }
  2428.  
  2429. public void rotateToPosition(Vector3D tp, Vector3D tv = new Vector3D())
  2430. {
  2431. if (!active) log("GECU test init rtp", LT.LOG_N);
  2432. flush();
  2433. targetPosition = tp;
  2434. targetVelocity = tv;
  2435. targetUp = getCtrl().WorldMatrix.Up;
  2436. }
  2437. public void rotateToHeading(Vector3D forward, Vector3D up = new Vector3D())
  2438. {
  2439. if (up == Vector3D.Zero) up = getCtrl().WorldMatrix.Up;
  2440. if (!active)
  2441. {
  2442. log("GECU test init rth", LT.LOG_N);
  2443. log("forward:" + v2ss(forward), LT.LOG_N);
  2444. log("up:" + v2ss(up), LT.LOG_N);
  2445. }
  2446. flush();
  2447. targetPosition = targetVelocity = Vector3D.Zero;
  2448. targetHeading = forward;
  2449. targetUp = up;
  2450. }
  2451.  
  2452. double error_thresholdLocked = ConvertDegreesToRadians(1);//we must be within this much on each axis
  2453. double minVelThresholdLocked = ConvertDegreesToRadians(1d);
  2454. //these only set qualifiers for ticksOnTarget.
  2455.  
  2456. private void calculateAxisSpecificData(double now, ref double prior, ref double lastMPT, out bool braking, out double lastMPTActual, string p = "")//, out double ticksToStop, out double ticksToTarget)
  2457. {
  2458.  
  2459. var radMovedPerTick = Math.Abs(prior - now);
  2460. var ticksToTarget = Math.Abs(now) / radMovedPerTick;
  2461. var initVel = radMovedPerTick;
  2462. var rateOfDecel = Math.Abs(lastMPT - radMovedPerTick);
  2463. //if (rateOfDecel > mod) mod = rateOfDecel;
  2464.  
  2465. //if (Math.Abs(now) > nobrake_threshold) rateOfDecel *= 1.5;//overestimating here did not improve timings
  2466. var ticksToStop = initVel / rateOfDecel;
  2467. //mod - maximum observed decel - saved 0.1s on large sluggish ship but lost .3s on sg snappy ship.
  2468. //sticking to the conservative metric
  2469.  
  2470. bool closing = Math.Abs(now) < Math.Abs(prior);
  2471. lastMPTActual = radMovedPerTick;
  2472. if (!closing)
  2473. {
  2474. lastMPT = 0.0001;
  2475. }
  2476. else lastMPT = radMovedPerTick;
  2477.  
  2478. if (closing)
  2479. {
  2480. if (ticksToStop > ticksToTarget + 1) braking = true;
  2481. else braking = false;
  2482. }
  2483. else braking = false;
  2484.  
  2485. prior = now;
  2486. }
  2487.  
  2488. //for distances under 90 degrees, it returns a value between 0 and gyromaxRPM, sharpened with sine so it levels off a bit in a nice way at the end.
  2489. //slightly black magic, but if it works, it works
  2490. static double amp_threshold = ConvertDegreesToRadians(100);//125.0d);
  2491. static double deAmp(double i)//, double spd)
  2492. {
  2493. if (i == 0) return i;
  2494. var abs = Math.Abs(i);
  2495. var ig = i / abs * gyroMaxRPM;
  2496. //spd = 0;
  2497. if (abs > amp_threshold) return ig;
  2498.  
  2499. i = i / (amp_threshold);
  2500. i = Math.Abs(i);
  2501. i = Math.Sin(i);
  2502. return i * ig;
  2503. }
  2504.  
  2505. public static void setUpdateRate(int ups)
  2506. {
  2507. updateRate = ups;
  2508. updr_mult = 60 / updateRate;
  2509. updr_mult_div = updr_mult / 60.0d;
  2510. }
  2511.  
  2512. static int updateRate = 30;
  2513. static int updr_mult = 60 / updateRate;
  2514. static double updr_mult_div = 60.0d / updateRate / 60.0d;
  2515. int ltick = -1;
  2516. public void update()
  2517. {
  2518.  
  2519. if (active && tick - ltick > updr_mult)// && tick % 2 == 0)
  2520. {
  2521. ltick = tick;
  2522.  
  2523. if (!targetPosition.IsZero()) targetHeading = Vector3D.Normalize(targetPosition - getPosition());
  2524.  
  2525. double pitch, yaw, roll;
  2526. GetRotationAnglesSimultaneousDedup(targetHeading, targetUp, getCtrl().WorldMatrix, out yaw, out pitch, out roll);
  2527.  
  2528. double rA, pA, yA;
  2529.  
  2530. bool yB, pB, rB;
  2531. calculateAxisSpecificData(roll, ref lastAngleRoll, ref lMPTRoll, out rB, out rA);
  2532. calculateAxisSpecificData(pitch, ref lastAnglePitch, ref lMPTPitch, out pB, out pA);
  2533. calculateAxisSpecificData(yaw, ref lastAngleYaw, ref lMPTYaw, out yB, out yA);
  2534.  
  2535. //Vector3D a_act = new Vector3D(pA, yA,rA);
  2536. //var amax = a_act.AbsMax();
  2537.  
  2538. Vector3D a_impulse = new Vector3D(pB ? 0 : pitch, yB ? 0 : yaw, rB ? 0 : roll);
  2539.  
  2540. //black magic everywhere
  2541. a_impulse.X = deAmp(a_impulse.X);//, amax * updr_mult);
  2542. a_impulse.Y = deAmp(a_impulse.Y);//, amax * updr_mult);
  2543. a_impulse.Z = deAmp(a_impulse.Z);//, amax * updr_mult);
  2544. if (Math.Abs(pA) / 60 * updateRate > Math.Abs(a_impulse.X)) a_impulse.X = 0;
  2545. if (Math.Abs(yA) / 60 * updateRate > Math.Abs(a_impulse.Y)) a_impulse.Y = 0;
  2546. if (Math.Abs(rA) / 60 * updateRate > Math.Abs(a_impulse.Z)) a_impulse.Z = 0;
  2547.  
  2548.  
  2549. GyroOverride(getCtrl().WorldMatrix, a_impulse.X, a_impulse.Y, a_impulse.Z);
  2550.  
  2551. if (Math.Abs(roll) < error_thresholdLocked && Math.Abs(pitch) < error_thresholdLocked && Math.Abs(yaw) < error_thresholdLocked)
  2552. {
  2553. if (rA < minVelThresholdLocked * updr_mult_div && pA < minVelThresholdLocked * updr_mult_div && yA < minVelThresholdLocked * updr_mult_div)
  2554. {
  2555. ticksOnTarget += 1;
  2556. }
  2557. else ticksOnTarget = 0;
  2558. }
  2559. else ticksOnTarget = 0;
  2560. }
  2561. }
  2562.  
  2563. IMyGyro lG = null;
  2564. static Vector3D state = new Vector3D(9, 9, 9);
  2565. const double E = MathHelper.EPSILON;
  2566. void GyroOverride(MatrixD shipRef, double pitch_speed, double yaw_speed, double roll_speed)
  2567. {
  2568. IMyGyro g = null;
  2569. var p = gProgram;
  2570. foreach (var c in p.gyros)
  2571. {
  2572. if (c.Enabled && c.IsFunctional && !c.Closed)
  2573. {
  2574. g = c;
  2575. break;
  2576. }
  2577. }
  2578. if (g == null) return;
  2579.  
  2580. if (g != lG)
  2581. {
  2582. if(lG != null) lG.GyroOverride = false;
  2583. lG = g;
  2584. state = new Vector3D(9, 9, 9);
  2585. g.GyroOverride = true;
  2586. }
  2587.  
  2588. var rotationVec = new Vector3D(-pitch_speed, yaw_speed, roll_speed); //because keen does some weird stuff with signs
  2589. var relativeRotationVec = Vector3D.TransformNormal(rotationVec, shipRef);
  2590. var trv = Vector3D.TransformNormal(relativeRotationVec, Matrix.Transpose(g.WorldMatrix));
  2591.  
  2592. if (trv.X != state.X)// && Math.Abs(trv.X - state.X) > E)
  2593. {
  2594. state.X = trv.X;
  2595. g.Pitch = (float)(state.X);
  2596. }
  2597. if (trv.Y != state.Y)// && Math.Abs(trv.Y - state.Y) > E)
  2598. {
  2599. state.Y = trv.Y;
  2600. g.Yaw = (float)(state.Y);
  2601. }
  2602. if (trv.Z != state.Z)// && Math.Abs(trv.Z - state.Z) > E)
  2603. {
  2604. state.Z = trv.Z;
  2605. g.Roll = (float)(state.Z);
  2606. }
  2607. }
  2608.  
  2609. public void shutdown()
  2610. {
  2611. if (active)
  2612. {
  2613. active = false;
  2614. if (lG != null) lG.GyroOverride = false;
  2615. log("GECU shutdown", LT.LOG_N);
  2616. log("time: " + (tick - startTick) + "t (" + ((double)(tick - startTick) / 60).ToString("0.0") + "s)", LT.LOG_N);
  2617. }
  2618. }
  2619. }
  2620.  
  2621. public class Config_
  2622. {
  2623. //public Setting<bool> autoExtractor = new Setting<bool>("autoExtractor").Default(true)
  2624. //;//.Desc("Misc - Automatically feed fuel items to extractors to maintain a minimum fuel % in tanks");
  2625. //public Setting<int> feMinHydrogen = new Setting<int>("feMinHydrogen").Default(10)
  2626. //;//.Desc("Misc - Percentage, 0-100, that determines when to feed fuel items if feedExtractors is enabled.");
  2627. //public Setting<int> feMinHydrogenDock = new Setting<int>("feMinHydrogenDock").Default(50)
  2628. //;//.Desc("Misc - Percentage, 0-100, that it will try to pull from another grid if docked to it.");
  2629.  
  2630. public Setting<bool> Eject = new Setting<bool>("Eject").Default(true);
  2631. public Setting<string> EjectDiscard = new Setting<string>("EjectDiscardFilter").Default("BulletproofGlass,Canvas,Computer,Construction,Detector,Display,Explosives,Girder,GravityGenerator,InteriorPlate,LargeTube,Medical,MetalGrid,Motor,PowerCell,RadioCommunication,Reactor,SmallTube,SolarCell,SteelPlate,Superconductor,Thrust,AmmoCache,Fuel_Tank,HeavyArms,SmallArms,ToolPack,SemiAutoPistolMagazine");
  2632. public Setting<string> EjectKeep = new Setting<string>("EjectKeepFilter").Default("MCRN,UNN,Belter,Adv,Upg,Experi,Lidar,Black,Data");
  2633.  
  2634. public Setting<string> WeaponDesync = new Setting<string>("WeaponDesyncBlockGroup").Default("Railguns");
  2635.  
  2636. public Setting<string> PDCGroup = new Setting<string>("PDCHeatBlockGroup").Default("PDCs");
  2637. //public Setting<bool> PDCAntiOverheat = new Setting<bool>("PDCAntiOverheat").Default(true);
  2638.  
  2639.  
  2640. public Setting<string> RSubtarget = new Setting<string>("RSubtargBlockGroup").Default("Railguns");
  2641. public Setting<string> RFC = new Setting<string>("RFriendColor").Default("lightgreen");
  2642. public Setting<string> REC = new Setting<string>("REnemyColor").Default("red");
  2643. public Setting<string> RNC = new Setting<string>("RNeutColor").Default("lightgreen");
  2644. public Setting<string> ROC = new Setting<string>("ROtherColor").Default("gray");
  2645.  
  2646. //public Setting<bool> PDCSeparateRange = new Setting<bool>("PDCSeparateRange").Default(true);
  2647. }
  2648.  
  2649. Config_ Config = null;
  2650.  
  2651. const double MAX_MS_PER_SEC_BOOT = 0.1;
  2652.  
  2653. const double MAX_MS_PER_SEC = 0.1;
  2654.  
  2655. const int PBLIMIT_STARTUPTICKS = 0;//20 by default
  2656.  
  2657. class BurnoutTrack
  2658. {
  2659. public static bool NOP = false;
  2660. public double maxmspersec = 0.25;
  2661. public static double[] defertrack;
  2662. public int len = 60;
  2663. public BurnoutTrack(int l, double ms)
  2664. {
  2665. len = l;
  2666. maxmspersec = ms;
  2667. defertrack = new double[len];
  2668. }
  2669. int defercalls = 0;
  2670. int deferpos = 0;
  2671. static public bool hangflag = false;
  2672. int hangticks = 0;
  2673. int hangtick = 0;
  2674. DateTime bf = DateTime.Now;
  2675. public bool burnoutpre()
  2676. {
  2677. bf = DateTime.Now;
  2678. if (hangflag)
  2679. {
  2680. if (tick > hangtick)
  2681. {
  2682. double avg = 0;
  2683. foreach (var d in defertrack) avg += d;
  2684. avg = avg / (defercalls > defertrack.Length ? defertrack.Length : defercalls);
  2685. if (avg > maxmspersec * len / 60)
  2686. {
  2687. defertrack[deferpos] = 0;
  2688. if (!NOP)
  2689. {
  2690. defercalls += 1;
  2691. deferpos = (deferpos + 1) % defertrack.Length;
  2692. return true;
  2693. }
  2694. else return false;
  2695. }
  2696. else
  2697. {
  2698. hangflag = false;
  2699. //log("Resuming after " + (hangticks / 60.0d).ToString("0.0") + "s", LT.LOG_N);
  2700. }
  2701. }
  2702. }
  2703. return hangflag;
  2704. }
  2705. public double avg()
  2706. {
  2707. double avg = 0;
  2708. foreach (var d in defertrack) avg += d;
  2709. avg = avg / (defercalls > defertrack.Length ? defertrack.Length : defercalls);
  2710. return avg;
  2711. }
  2712. public void setwait(int ticks)
  2713. {
  2714. hangticks = ticks;
  2715. hangtick = tick + ticks;
  2716. hangflag = true;
  2717. }
  2718. public void setwait(double targetmsavg, bool emerg = false, double cap=int.MaxValue)
  2719. {
  2720. double p_avg = 0;
  2721. foreach (var d in defertrack) p_avg += d;
  2722. int divisor = defercalls > defertrack.Length ? defertrack.Length : defercalls;
  2723. var avg = p_avg / divisor;
  2724. var mtch = targetmsavg * len / 60;
  2725. if (avg > mtch && !NOP)
  2726. {
  2727. int waitticks = 0;
  2728. while (p_avg / (divisor + waitticks) > mtch) waitticks++;
  2729. if (waitticks > cap * 60) waitticks = (int)(cap / 60);
  2730. hangticks = waitticks;
  2731. hangtick = tick + waitticks;
  2732. hangflag = true;
  2733. var lstr = "";// Waiting " + (hangticks / 60.0d).ToString("0.0") + "s to reach "+ targetmsavg.ToString("0.00")+"ms/s util";
  2734. if(emerg) lstr = tick + ": " + avg.ToString("0.00") + ">" + (mtch).ToString("0.00") + "ms/s exec. Sleeping " + (hangticks / 60.0d).ToString("0.0") + "s";
  2735. else lstr = "Waiting " + (hangticks / 60.0d).ToString("0.0") + "s to reach " + targetmsavg.ToString("0.00") + "ms/s util";
  2736. //tick + ": " + avg.ToString("0.00") + ">" + (mtch).ToString("0.00") + "ms/s exec. Sleeping " + (hangticks / 60.0d).ToString("0.0") + "s";
  2737. log(lstr, LT.LOG_N);
  2738. }
  2739. }
  2740. public bool burnoutpost()
  2741. {
  2742. if (NOP) return false;
  2743. double ms = (DateTime.Now - bf).TotalMilliseconds;
  2744. defertrack[deferpos] = ms;
  2745. defercalls += 1;
  2746. deferpos = (deferpos + 1) % defertrack.Length;
  2747. if (!hangflag)
  2748. {
  2749. setwait(maxmspersec, true);
  2750. }
  2751. else return true;
  2752. return false;
  2753. }
  2754. }
  2755.  
  2756. DetectedEntity rotateTarget = null;
  2757.  
  2758. bool autoRotate = false;
  2759.  
  2760. bool AR_reverse = false;
  2761.  
  2762. void toggleAutorotate(bool reverse=false)
  2763. {
  2764. AR_reverse = reverse;
  2765. autoRotate = !autoRotate;
  2766. if (autoRotate)
  2767. {
  2768. rotateTarget = null;
  2769. MyDetectedEntityInfo? focus = APIWC.GetAiFocus(Me.CubeGrid.EntityId);
  2770. if (focus.HasValue)detectedEntitiesD.TryGetValue(focus.Value.EntityId, out rotateTarget);
  2771. if (rotateTarget == null && matchTarget != null) rotateTarget = matchTarget;
  2772.  
  2773. if (rotateTarget == null) autoRotate = false;
  2774. }
  2775. else
  2776. {
  2777. rotateTarget = null;
  2778. gyroECU.shutdown();
  2779. }
  2780. processRadar(0, true);
  2781. }
  2782.  
  2783. void autorot_update()
  2784. {
  2785. if (autoRotate)
  2786. {
  2787. bool canTrack = false;
  2788. if (rotateTarget != null)
  2789. {
  2790. DetectedEntity d = null;
  2791. detectedEntitiesD.TryGetValue(rotateTarget.EntityId, out d);
  2792. if (d != null)
  2793. {
  2794. canTrack = true;
  2795. rotateTarget = d;
  2796. }
  2797. MyDetectedEntityInfo? focus = APIWC.GetAiFocus(Me.CubeGrid.EntityId);
  2798. if (focus.HasValue)
  2799. {
  2800. if (focus.Value.EntityId == rotateTarget.EntityId) rotateTarget.upd(focus.Value);
  2801. }
  2802.  
  2803. if (rotateTarget != null) rotateTarget.upd(focus.Value);
  2804.  
  2805. if (!canTrack || rotateTarget == null)
  2806. {
  2807. toggleAutorotate();
  2808. }
  2809. }
  2810. if (rotateTarget != null)
  2811. {
  2812. var pos = getPosition();
  2813. var tpos = rotateTarget.getEstPos();
  2814. var offset = (tpos - pos);
  2815. var dist = offset.Length();
  2816. Vector3D aim = offset/ dist;
  2817. if (AR_reverse) aim = -aim;
  2818. gyroECU.rotateToHeading(aim);
  2819. }
  2820. }
  2821. }
  2822.  
  2823. static public double VectorAngleBetween(Vector3D a, Vector3D b) //returns radians
  2824. {
  2825. if (a.LengthSquared() == 0 || b.LengthSquared() == 0)
  2826. return 0;
  2827. else
  2828. return Math.Acos(MathHelper.Clamp(a.Dot(b) / a.Length() / b.Length(), -1, 1));
  2829. }
  2830.  
  2831. class targetReserve
  2832. {
  2833. public targetReserve(IMyFunctionalBlock we, long e, int ex)
  2834. {
  2835. w = we; eid = e; expire = ex;
  2836. }
  2837. public IMyFunctionalBlock w;
  2838. public long eid;
  2839. public int expire;
  2840. }
  2841.  
  2842. List<IMyFunctionalBlock> desynced = new List<IMyFunctionalBlock>();
  2843.  
  2844. List<targetReserve> reservations = new List<targetReserve>();
  2845.  
  2846. targetReserve targetReserved(long e)
  2847. {
  2848. foreach (var r in reservations) if (r.eid == e) return r;
  2849. return null;
  2850. }
  2851.  
  2852. static Profiler wpndsyncP = new Profiler("wpndsync");
  2853.  
  2854. void weaponDesync()
  2855. {
  2856. wpndsyncP.s();
  2857. for (int i = 0; i < reservations.Count;)
  2858. {
  2859. if (tick > reservations[i].expire) reservations.RemoveAt(i);
  2860. else i++;
  2861. }
  2862. foreach (var w in desynced)
  2863. {
  2864. w.Enabled = true;
  2865. APIWC.SetWeaponTarget(w, Me.EntityId, 0);
  2866. }
  2867. desynced.Clear();
  2868.  
  2869. if (tick % 60 == 0)
  2870. {
  2871. foreach (var w in desyncGroup)
  2872. {
  2873. APIWC.SetWeaponTarget(w, Me.EntityId, 0);
  2874. if (!desynced.Contains(w) && APIWC.IsWeaponReadyToFire(w))
  2875. {
  2876. var t = APIWC.GetWeaponTarget(w).GetValueOrDefault();
  2877. if (t.Type == MyDetectedEntityType.LargeGrid || t.Type == MyDetectedEntityType.SmallGrid)
  2878. {
  2879. var reservetime = tick + (60 * 2) - 1;
  2880. WeaponState ws = null;
  2881. wsdict.TryGetValue(w, out ws);
  2882. if (ws != null)
  2883. {
  2884. var apx_ttt = (w.GetPosition() - t.Position).Length() / ws.settings.ammoVel;
  2885. reservetime = (int)(apx_ttt * 60) + 30;
  2886. }
  2887.  
  2888. var reserved = targetReserved(t.EntityId);
  2889. if (reserved != null)
  2890. {
  2891. if (reserved.w != w)
  2892. {
  2893. w.Enabled = false;
  2894. desynced.Add(w);
  2895. }
  2896. else reserved.expire = reservetime;
  2897. //effectively, it won't count down until we actually fire
  2898. }
  2899. else
  2900. {
  2901. reservations.Add(new targetReserve(w, t.EntityId, reservetime));
  2902. }
  2903. }
  2904. }
  2905. }
  2906. }
  2907. wpndsyncP.e();
  2908. }
  2909.  
  2910. static List<PDCFirmware> PDCFirmwareList = new List<PDCFirmware>();
  2911.  
  2912. public class PDCFirmware
  2913. {
  2914. public IMyFunctionalBlock b = null;
  2915. public PDCData settings = null;
  2916. public float range = 0;
  2917.  
  2918. public PDCFirmware(IMyFunctionalBlock block)
  2919. {
  2920. b = block;
  2921. PDCDataSubType.TryGetValue(b.DefinitionDisplayNameText, out settings);
  2922. if (settings == null) settings = new PDCData(b.DefinitionDisplayNameText);
  2923. }
  2924. //public int lUpdTick = -1;
  2925.  
  2926. public double lastHeat = 0;
  2927. public void update()
  2928. {
  2929. lastHeat = gProgram.APIWC.GetHeatLevel(b);
  2930. }
  2931. }
  2932.  
  2933. class PDCNet
  2934. {
  2935. public string label;
  2936. public Base6Directions.Direction dir;
  2937. public double range;
  2938.  
  2939. int interval = 3;
  2940. int[] heatavg5s = new int[60];//entry every 5 ticks?
  2941. int heatc = 0;
  2942. public PDCNet(string lbl)
  2943. {
  2944. label = lbl;
  2945. for (int i = 0; i < 60; i++) heatavg5s[i] = 0;
  2946. }
  2947. public List<PDCFirmware> PDCs = new List<PDCFirmware>();
  2948. public void addPDC(PDCFirmware b)
  2949. {
  2950. PDCs.Add(b);
  2951. PDCFirmwareList.Add(b);
  2952. }
  2953. public bool remPDC(IMyFunctionalBlock b)
  2954. {
  2955. PDCFirmware del = null;
  2956. foreach (var w in PDCs)
  2957. {
  2958. if (w.b == b)
  2959. {
  2960. del = w;
  2961. break;
  2962. }
  2963. }
  2964. if (del != null)
  2965. {
  2966. PDCs.Remove(del);
  2967. PDCFirmwareList.Remove(del);
  2968. return true;
  2969. }
  2970. return false;
  2971. }
  2972.  
  2973. int lupdt = -1;
  2974. public void update()
  2975. {
  2976. if (tick % interval == 0)
  2977. {
  2978. lupdt = tick;
  2979. int topheat = 0;
  2980. int totalheat = 0;
  2981. bool chng = false;
  2982. foreach (PDCFirmware frm in PDCs)
  2983. {
  2984. //if (frm.lUpdTick == tick)
  2985. {
  2986. //frm.update();
  2987. int heat = (int)(frm.lastHeat * 100 / frm.settings.MaxHeat);
  2988. totalheat += heat;
  2989. if (heat > topheat) topheat = heat;
  2990. chng = true;
  2991. }
  2992. }
  2993. if (chng)
  2994. {
  2995. if (PDCs.Count > 0) totalheat /= PDCs.Count;
  2996. topHeat = topheat;
  2997. avgHeat = totalheat;
  2998. }
  2999.  
  3000. heatavg5s[heatc] = totalheat;
  3001. heatc = (heatc + 1) % 60;
  3002. }
  3003. }
  3004. public int topHeat = 0;
  3005. public int avgHeat = 0;
  3006. public int topheat3sago()
  3007. {
  3008. //as a rolling 5s loop the next entry is about 5 s ago
  3009. return heatavg5s[(heatc + 1) % 60];
  3010. }
  3011. }
  3012.  
  3013.  
  3014. static string[] dirl = new string[]
  3015. {
  3016. " FWD",
  3017. " BACK",
  3018. " LEFT",
  3019. "RIGHT",
  3020. " TOP",
  3021. " DOWN"
  3022. };
  3023.  
  3024. class PDCNetGroup
  3025. {
  3026. public string name = "";
  3027. public bool sided = false;
  3028. public List<PDCNet> PDCNets = new List<PDCNet>();
  3029. public string bgroup = "";
  3030.  
  3031. List<IMyFunctionalBlock> trackedPDC = new List<IMyFunctionalBlock>();
  3032. public void addPDC(IMyFunctionalBlock b)
  3033. {
  3034. if (trackedPDC.Contains(b)) return;
  3035. trackedPDC.Add(b);
  3036. string label = new string(' ', dirl[0].Length);
  3037. var d = Base6Directions.Direction.Forward;
  3038. if (sided)
  3039. {
  3040. var ctrl = getCtrl();
  3041. var w = ctrl.WorldMatrix;
  3042. Vector3D dir = b.WorldMatrix.Up;
  3043. if (dir == w.Forward || dir == w.Backward) dir = b.WorldMatrix.Forward;
  3044. string cat = dirl[0];
  3045. if (dir == w.Left) d = Base6Directions.Direction.Left;
  3046. else if (dir == w.Right) d = Base6Directions.Direction.Right;
  3047. else if (dir == w.Up) d = Base6Directions.Direction.Up;
  3048. else if (dir == w.Down) d = Base6Directions.Direction.Down;
  3049. label = dirl[(int)d];
  3050. }
  3051. PDCNet net = null;
  3052. foreach (var n in PDCNets)
  3053. {
  3054. if (n.dir == d)
  3055. {
  3056. net = n;
  3057. break;
  3058. }
  3059. }
  3060. if (net == null)
  3061. {
  3062. net = new PDCNet(label);
  3063. net.dir = d;
  3064. PDCNets.Add(net);
  3065. }
  3066. net.addPDC(new PDCFirmware(b));
  3067. }
  3068. public void remPDC(IMyFunctionalBlock b)
  3069. {
  3070. if (!trackedPDC.Contains(b)) return;
  3071. trackedPDC.Remove(b);
  3072. foreach (var n in PDCNets) if (n.remPDC(b)) break;
  3073. }
  3074.  
  3075. public void update()
  3076. {
  3077. foreach (var n in PDCNets) n.update();
  3078. }
  3079. }
  3080.  
  3081. int lastHUpdTick = -9000;
  3082.  
  3083. static Profiler heatP = new Profiler("heat");
  3084.  
  3085. IEnumerator<bool> __processHeat = null;
  3086.  
  3087. int fh = 1;
  3088.  
  3089. int hsteps = 0;
  3090.  
  3091. int htix = 0;
  3092.  
  3093. //bool radar_firstrun = true;
  3094. public void processHeat(double maxMS, bool force = false)
  3095. {
  3096. abort_start = DateTime.Now;
  3097. max_time = maxMS;
  3098. heatP.s();
  3099. pdcscanP.s();
  3100. PDCScan2(force);
  3101. pdcscanP.e();
  3102. foreach (var net in PDCNetGroups)
  3103. {
  3104. net.update();
  3105. }
  3106.  
  3107. if ((tick - lastHUpdTick > 60 || force) && __processHeat == null)
  3108. {
  3109. __processHeat = _processHeat();
  3110. lastHUpdTick = tick;
  3111. }
  3112. if (__processHeat != null)
  3113. {
  3114. double r = 0;
  3115. bool fin = false;
  3116. do
  3117. {
  3118. if (maxMS == 0 && force && (curBG != 0 || curPDC != 0))
  3119. {
  3120. PDCScan2(force);
  3121. fin = curBG == 0 && curPDC == 0;
  3122. }else fin = !__processHeat.MoveNext();
  3123. hsteps++;
  3124. } while (!fin && !abort());
  3125. htix++;
  3126.  
  3127. if (fin)
  3128. {
  3129. if (fh > 0)
  3130. {
  3131. fh--;
  3132.  
  3133. log("hrsy processed in " + hsteps + " steps, " + htix + "t", LT.LOG_N);
  3134. hsteps = 0;
  3135. htix = 0;
  3136. }
  3137. __processHeat.Dispose();
  3138. __processHeat = null;
  3139. }
  3140. }
  3141. heatP.e();
  3142. }
  3143.  
  3144. SpriteHUDLCD PDCLogSprite = null;
  3145.  
  3146. public IEnumerator<bool> _processHeat()
  3147. {
  3148. yield return true;
  3149.  
  3150. if (PDCLog == null) yield return false;
  3151.  
  3152. if (PDCLog != null)
  3153. {
  3154. if (PDCLogSprite == null) PDCLogSprite = new SpriteHUDLCD(PDCLog);
  3155. PDCLogSprite.s = PDCLog;
  3156. }
  3157. StringBuilder b = new StringBuilder();
  3158. if (PDCBlockGroupK.Count != 0)
  3159. {
  3160. foreach (var frm in PDCFirmwareList)
  3161. {
  3162. frm.update();
  3163. yield return true;
  3164. }
  3165. b.Append("<color=white>SIDE PD# AVG/TOP\n");
  3166. foreach (var netg in PDCNetGroups)
  3167. {
  3168. yield return true;
  3169. if (!netg.sided && netg.name.Length < 5) bapp(b, new string(' ', 5 - netg.name.Length));
  3170. bapp(b, "<color=lightsteelblue>", netg.name);//, "\n");
  3171. if (netg.sided || netg.name.Length > 5) bapp(b, "\n");
  3172.  
  3173. foreach (var netk in netg.PDCNets)
  3174. {
  3175. yield return true;
  3176. var n = netk;
  3177. var d = netk.dir;
  3178. var labl = "";
  3179. if (netg.sided) labl = dirl[(int)d];
  3180. var dif = n.avgHeat - n.topheat3sago();
  3181. var odif = dif;
  3182. var sym = '↑';
  3183. if (dif == 0)
  3184. {
  3185. sym = ' ';
  3186. }
  3187. else if (dif < 0)
  3188. {
  3189. sym = '↓';
  3190. }
  3191. if (dif < 0) dif = -dif;
  3192. //⚠
  3193. if (n.avgHeat > 80) b.Append("<color=indianred>");
  3194. else if (n.avgHeat > 60) b.Append("<color=orangered>");
  3195. else if (n.avgHeat > 35) b.Append("<color=goldenrod>");
  3196. else if (n.avgHeat > 20) b.Append("<color=palegoldenrod>");
  3197. else b.Append("<color=lightgray>");
  3198. bapp(b, labl);
  3199. if (n.PDCs.Count < 10) b.Append(" ");
  3200. else b.Append(" ");
  3201. bapp(b, n.PDCs.Count, " ");
  3202. if (n.avgHeat < 10) b.Append(" ");
  3203. else if (n.avgHeat < 100) b.Append(" ");
  3204. bapp(b, n.avgHeat, "%/");
  3205. if (n.topHeat < 10) b.Append(" ");
  3206. else if (n.topHeat < 100) b.Append(" ");
  3207. bapp(b, n.topHeat, "%");
  3208. if (odif > 0) b.Append("<color=red>");
  3209. else if (odif == 0) b.Append("<color=lightgray>");
  3210. else if (odif < 0) b.Append("<color=lightgreen>");
  3211. bapp(b, ' ', sym);
  3212. bapp(b, dif, "%/3s\n");
  3213. }
  3214. }
  3215. }
  3216. PDCLogSprite.setLCD(b.ToString());
  3217.  
  3218. yield return false;
  3219. }
  3220.  
  3221.  
  3222.  
  3223. int curBG = 0;
  3224.  
  3225. int curPDC = 0;
  3226.  
  3227.  
  3228. static Profiler pdcscanP = new Profiler("scn");
  3229.  
  3230.  
  3231. public void PDCScan2(bool force=false)
  3232. {
  3233. //pdcscanP.s();
  3234. if (tick % 10 == 0 || force)
  3235. {
  3236.  
  3237. if (PDCBlockGroupK.Count > 0)
  3238. {
  3239. var g = PDCBlockGroupK[curBG];
  3240. var y = PDCBlockGroups[g];
  3241. if (y.Count > 0)
  3242. {
  3243. var b = y[curPDC];
  3244. if (b.IsFunctional && !b.Closed) addPDC(g, b);
  3245. else remPDC(g, b);
  3246. }
  3247. curPDC = curPDC + 1;
  3248. if (curPDC >= y.Count)
  3249. {
  3250. curPDC = 0;
  3251. curBG = (curBG + 1) % PDCBlockGroupK.Count;
  3252. }
  3253. }
  3254. if (curBG >= PDCBlockGroupK.Count) curBG = curPDC = 0;
  3255. }
  3256. //pdcscanP.e();
  3257. }
  3258.  
  3259. void addPDC(string bg, IMyFunctionalBlock b)
  3260. {
  3261. foreach (var g in PDCNetGroups)
  3262. {
  3263. if (g.bgroup == bg)
  3264. {
  3265. g.addPDC(b);
  3266. break;
  3267. }
  3268. }
  3269. }
  3270.  
  3271. void remPDC(string bg, IMyFunctionalBlock b)
  3272. {
  3273. foreach (var g in PDCNetGroups)
  3274. {
  3275. if (g.bgroup == bg)
  3276. {
  3277. g.remPDC(b);
  3278. break;
  3279. }
  3280. }
  3281. }
  3282.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement