using EmptyKeys.UserInterface.Generated.DataTemplatesContracts_Bindings; using Sandbox.Game.Entities; using Sandbox.Game.Entities.Cube; using Sandbox.Game.EntityComponents; //using Sandbox.ModAPI; using Sandbox.ModAPI.Ingame; using Sandbox.ModAPI.Interfaces; using SpaceEngineers.Game.ModAPI.Ingame; using System; using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using VRage; using VRage.Collections; using VRage.Game; using VRage.Game.Components; using VRage.Game.GUI.TextPanel; using VRage.Game.ModAPI.Ingame; using VRage.Game.ModAPI.Ingame.Utilities; using VRage.Game.ObjectBuilders.Definitions; using VRageMath; namespace IngameScript { partial class Program : MyGridProgram { //const string MISSILE_GRID_PREFIX = "[PM]"; const float EPSILON = 0.05f; const double DELAY_BEFORE_TRAVELLING_MODE = 5000; // [ms] (5 s). const double AUTO_DESTRUCTION_AFTER = 120000; // [ms] (2 min). Or if the hydrogen tank is empty. enum State { NORMAL, LAUNCHING, TRAVELLING, } State currentState = State.NORMAL; readonly Output output; readonly IMyCubeGrid grid; int tickFromStart; IMyThrust forwardThruster; IEnumerable thrusters; IMyFlightMovementBlock aiMove; IMyOffensiveCombatBlock aiCombat; IEnumerable warheads; IMyGasTank gasTank; IMyLightingBlock light; public Program() { var output = this.Me.GetSurface(0); this.output = new Output(output); this.output.Print("Missile controller system starting..."); this.grid = this.Me.CubeGrid; this.Runtime.UpdateFrequency = UpdateFrequency.Update10; this.output.Print("Missile controller system started"); } bool FindElements() { if (this.forwardThruster == null) this.forwardThruster = this.GridTerminalSystem.GetBlock("[PM] Hydrogen Thruster 01", this.grid); if (this.forwardThruster == null) { this.output.Print("Error: Cannot find forward thruster"); return false; } if (this.thrusters == null) { this.thrusters = this.GridTerminalSystem.GetBlocksFromGroup("[PM] Thrusters", this.grid); if (this.thrusters.Count() == 0) { this.output.Print("Error: Cannot find thrusters"); return false; } } if (this.aiMove == null) this.aiMove = this.GridTerminalSystem.GetBlock("[PM] AI Flight (Move)", this.grid); if (this.aiMove == null) { this.output.Print("Error: Cannot find AI move"); return false; } if (this.aiCombat == null) this.aiCombat = this.GridTerminalSystem.GetBlock("[PM] AI Offensive (Combat)", this.grid); if (this.aiCombat == null) { this.output.Print("Error: Cannot find AI combat"); return false; } if (this.warheads == null) this.warheads = this.GridTerminalSystem.GetBlocksFromGroup("[PM] Warheads", this.grid); if (this.warheads.Count() == 0) { this.output.Print("Error: Cannot find any warhead"); return false; } // Debug. //else //{ // this.output.Print(String.Format("Number of warhead: {0}", this.warheads.Count())); //} if (this.gasTank == null) this.gasTank = this.GridTerminalSystem.GetBlock("[PM] Hydrogen Tank", this.grid); if (this.gasTank == null) { this.output.Print("Error: Cannot find gas tank"); return false; } if (this.light == null) this.light = this.GridTerminalSystem.GetBlock("[PM] Light", this.grid); if (this.light == null) { this.output.Print("Error: Cannot find light"); return false; } return true; } bool BlinkBeforeBeingAutodestructed() { return this.MsSinceLaunch > AUTO_DESTRUCTION_AFTER - 3000; } bool MustBeAutodestructed() { return this.MsSinceLaunch > AUTO_DESTRUCTION_AFTER; } bool EnemyAtRange() { return this.aiCombat.SearchEnemyComponent.FoundEnemyId.HasValue; } void UpdateState10() { this.tickFromStart += 10; switch (this.currentState) { case State.LAUNCHING: if (!this.FindElements()) { this.output.Print("Cannot find all missile elements, launching aborted"); this.currentState = State.NORMAL; break; } this.forwardThruster.Enabled = true; // Only one thruster is enabled when launching. this.forwardThruster.ThrustOverridePercentage = 1; if (this.MsSinceLaunch > DELAY_BEFORE_TRAVELLING_MODE && (this.EnemyAtRange() || this.BlinkBeforeBeingAutodestructed())) { foreach (var thruster in this.thrusters) { if (thruster != this.forwardThruster) thruster.Enabled = true; } this.forwardThruster.ThrustOverridePercentage = 0; this.aiMove.Enabled = true; foreach (var warhead in this.warheads) warhead.IsArmed = true; this.output.Print($"Travelling mode"); this.currentState = State.TRAVELLING; } break; case State.TRAVELLING: if (this.BlinkBeforeBeingAutodestructed()) this.light.BlinkIntervalSeconds = 0.5f; if (this.gasTank.FilledRatio <= EPSILON || this.MustBeAutodestructed()) { Detonate(); } break; case State.NORMAL: break; // Nothing; } } void Detonate() { foreach (var warhead in this.warheads) warhead.Detonate(); } public void Save() { } double MsSinceLaunch { get { return (double)this.tickFromStart / 60 * 1000; } } public void Main(string argument, UpdateType updateSource) { if ((updateSource & UpdateType.Update10) != 0) { this.UpdateState10(); } else if ((updateSource & (UpdateType.Script | UpdateType.Terminal | UpdateType.Trigger)) != 0) { switch (argument) { case "START": this.output.Print("Launching mode"); this.tickFromStart = 0; this.currentState = State.LAUNCHING; break; case "STOP": this.output.Print("Stop mode"); this.currentState = State.NORMAL; break; default: this.output.Print($"Uknown command: {argument}"); break; } } } } }