Add missile launcher and missile controller projects
[SEScripts.git] / MissileController / Program.cs
diff --git a/MissileController/Program.cs b/MissileController/Program.cs
new file mode 100644 (file)
index 0000000..3fcc33c
--- /dev/null
@@ -0,0 +1,206 @@
+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 = 3000; // [ms].
+        const double AUTO_DESTRUCTION_AFTER = 60000; // [ms] (1 min).
+
+
+        enum State
+        {
+            NORMAL,
+            LAUNCHING,
+            TRAVELLING,
+        }
+
+        State currentState = State.NORMAL;
+
+        readonly Output output;
+
+        int tickFromStart;
+        IMyThrust forwardThruster;        
+        IMyFlightMovementBlock aiMove;
+        IMyOffensiveCombatBlock aiCombat;
+        IMySensorBlock sensor;
+        List<IMyWarhead> warheads = new List<IMyWarhead>();
+        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.Runtime.UpdateFrequency = UpdateFrequency.Update10;
+
+            this.output.Print("Missile controller system started");
+        }
+
+        void UpdateState10()
+        {
+            if (this.forwardThruster == null)
+                this.forwardThruster = this.GridTerminalSystem.GetBlockWithName("[PM] Hydrogen Thruster 01") as IMyThrust;
+            if (this.forwardThruster == null)
+            {
+                this.output.Print("Error: Cannot find forward thruster");
+                return;
+            }
+
+            if (this.aiMove == null)
+                this.aiMove = this.GridTerminalSystem.GetBlockWithName("[PM] AI Flight (Move)") as IMyFlightMovementBlock;
+            if (this.aiMove == null)
+            {
+                this.output.Print("Error: Cannot find AI move");
+                return;
+            }
+
+            if (this.aiCombat == null)
+                this.aiCombat = this.GridTerminalSystem.GetBlockWithName("[PM] AI Offensive (Combat)") as IMyOffensiveCombatBlock;
+            if (this.aiCombat == null)
+            {
+                this.output.Print("Error: Cannot find AI combat");
+                return;
+            }
+
+            if (this.sensor == null)
+                this.sensor = this.GridTerminalSystem.GetBlockWithName("[PM] Sensor") as IMySensorBlock;
+            if (this.sensor == null)
+            {
+                this.output.Print("Error: Cannot find sensor");
+                return;
+            }
+
+            if (this.warheads.Count == 0)
+                this.GridTerminalSystem.GetBlockGroupWithName("[PM] Warheads").GetBlocksOfType(this.warheads);
+            if (this.warheads.Count == 0)
+            {
+                this.output.Print("Error: Cannot find any warhead");
+                return;
+            }
+
+            if (this.gasTank == null)
+                this.gasTank = this.GridTerminalSystem.GetBlockWithName("[PM] Hydrogen Tank") as IMyGasTank;
+            if (this.gasTank == null)
+            {
+                this.output.Print("Error: Cannot find gas tank");
+                return;
+            }
+
+            if (this.light == null)
+                this.light = this.GridTerminalSystem.GetBlockWithName("[PM] Light") as IMyLightingBlock;
+            if (this.light == null)
+            {
+                this.output.Print("Error: Cannot find light");
+                return;
+            }
+
+            switch (this.currentState)
+            {
+                case State.LAUNCHING:
+                    // this.output.Print($"Tick: {this.tickFromStart}");
+                    //this.forwardThruster.ove
+                    this.forwardThruster.ThrustOverridePercentage = 1;
+                    if (this.MsSinceLaunch > DELAY_BEFORE_TRAVELLING_MODE)
+                    {
+                        this.forwardThruster.ThrustOverridePercentage = 0;
+                        this.aiMove.Enabled = true;
+                        this.aiCombat.Enabled = true;
+
+                        foreach (var warhead in this.warheads)
+                            warhead.IsArmed = true;
+
+                        this.output.Print($"Travelling mode");
+                        this.currentState = State.TRAVELLING;
+                    }
+                    break;
+
+                case State.TRAVELLING:
+                    var detectedEntity = this.sensor.LastDetectedEntity;
+
+                    if (this.MsSinceLaunch > AUTO_DESTRUCTION_AFTER - 3000)
+                        this.light.BlinkIntervalSeconds = 0.5f;
+
+                    if (this.gasTank.FilledRatio <= EPSILON || detectedEntity.Type != MyDetectedEntityType.None || this.MsSinceLaunch > AUTO_DESTRUCTION_AFTER)
+                    { 
+                        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.tickFromStart += 10;
+                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;
+
+                    default:
+                        this.output.Print($"Uknown command: {argument}");
+                        break;
+                }
+            }
+        }
+    }
+}