diff --git a/MissileController/Program.cs b/MissileController/Program.cs index 9a2ce30..5f3623e 100644 --- a/MissileController/Program.cs +++ b/MissileController/Program.cs @@ -33,26 +33,38 @@ 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. + const double DISTANCE_BEFORE_ROTATING = 15; // [m]. + const float ROTATION_SPEED = 0.5f; // [rad/s]. enum State { NORMAL, LAUNCHING, + TURNING, + ACCELERATING, TRAVELLING, + AI, } - + State currentState = State.NORMAL; + int tickFromStart; + int begginningOfaccelerationTick; + bool launchPositionSet = false; + Vector3D launchPosition; + Vector3D directionBeforeTurning; + + Vector3D lastPosition; + double speed; + double acceleration; + readonly Output output; readonly IMyCubeGrid grid; - int tickFromStart; IMyThrust forwardThruster; + IMyThrust backwardThruster; + IMyGyro gyroscope; IEnumerable thrusters; IMyFlightMovementBlock aiMove; IMyOffensiveCombatBlock aiCombat; @@ -83,6 +95,22 @@ namespace IngameScript return false; } + if (this.backwardThruster == null) + this.backwardThruster = this.GridTerminalSystem.GetBlock("[PM] Hydrogen Thruster 06", this.grid); + if (this.backwardThruster == null) + { + this.output.Print("Error: Cannot find backward thruster"); + return false; + } + + if (this.gyroscope == null) + this.gyroscope = this.GridTerminalSystem.GetBlock("[PM] Gyroscope", this.grid); + if (this.gyroscope == null) + { + this.output.Print("Error: Cannot find gyroscope"); + return false; + } + if (this.thrusters == null) { this.thrusters = this.GridTerminalSystem.GetBlocksFromGroup("[PM] Thrusters", this.grid); @@ -141,15 +169,15 @@ namespace IngameScript return true; } - bool BlinkBeforeBeingAutodestructed() - { - return this.MsSinceLaunch > AUTO_DESTRUCTION_AFTER - 3000; - } + //bool BlinkBeforeBeingAutodestructed() + //{ + // return this.MsSinceLaunch > AUTO_DESTRUCTION_AFTER - 3000; + //} - bool MustBeAutodestructed() - { - return this.MsSinceLaunch > AUTO_DESTRUCTION_AFTER; - } + //bool MustBeAutodestructed() + //{ + // return this.MsSinceLaunch > AUTO_DESTRUCTION_AFTER; + //} bool EnemyAtRange() { @@ -160,6 +188,20 @@ namespace IngameScript { this.tickFromStart += 10; + if (this.forwardThruster != null) + { + var currentPosition = this.forwardThruster.GetPosition(); + if (this.lastPosition != new Vector3D()) + { + var d = (currentPosition - this.lastPosition).Length(); + var speed = d * 10; + this.acceleration = (speed - this.speed) * 10; + this.speed = speed; + //this.output.Print($"Spd: {this.speed:0.0}, Acc: {this.acceleration:0.0}"); + } + this.lastPosition = currentPosition; + } + switch (this.currentState) { case State.LAUNCHING: @@ -170,35 +212,69 @@ namespace IngameScript 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())) + if (!this.launchPositionSet) { - foreach (var thruster in this.thrusters) - { - if (thruster != this.forwardThruster) - thruster.Enabled = true; - } + this.launchPosition = this.forwardThruster.GetPosition(); + this.launchPositionSet = true; + } + //this.forwardThruster.Enabled = true; // Only one thruster is enabled when launching. Replaced by the loop below to avoid issues when gravity is present. + foreach (var thruster in this.thrusters) + { + if (thruster != this.backwardThruster) + thruster.Enabled = true; + } + + this.forwardThruster.ThrustOverridePercentage = 1f; // Can be lowered for low gravity but set to 1f for 1G planet gravity. + + //this.output.Print($"Distance from launch: {this.DistanceFromLaunch:0.0} m"); + + if (this.DistanceFromLaunch > DISTANCE_BEFORE_ROTATING) + { + this.directionBeforeTurning = this.forwardThruster.WorldMatrix.Forward.Normalized(); + this.gyroscope.GyroOverride = true; + this.gyroscope.Roll = ROTATION_SPEED; + + this.output.Print($"Turning mode"); + this.currentState = State.TURNING; + } + break; + + case State.TURNING: + var dotProduct = this.forwardThruster.WorldMatrix.Forward.Normalized().Dot(this.directionBeforeTurning); + //this.output.Print($"Dot product: {dotProduct:0.000}"); + if (dotProduct <= EPSILON) + { + this.gyroscope.GyroOverride = false; + this.gyroscope.Roll = 0; + this.forwardThruster.ThrustOverridePercentage = 1f; + + this.output.Print($"Accelerating mode"); + this.begginningOfaccelerationTick = this.tickFromStart; + this.currentState = State.ACCELERATING; + } + break; + + case State.ACCELERATING: + //this.CheckTank(); + this.CheckEnemies(); + + if (this.acceleration <= EPSILON) + { 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; + //this.CheckTank(); + this.CheckEnemies(); + + break; - if (this.gasTank.FilledRatio <= EPSILON || this.MustBeAutodestructed()) - { - Detonate(); - } + case State.AI: + //this.CheckTank(); break; case State.NORMAL: @@ -206,6 +282,33 @@ namespace IngameScript } } + //void CheckTank() + //{ + // if (this.gasTank.FilledRatio <= EPSILON) + // { + // this.output.Print("Tank empty, detonating"); + // Detonate(); + // } + //} + + void CheckEnemies() + { + if (this.EnemyAtRange()) + { + this.forwardThruster.ThrustOverridePercentage = 0; + + foreach (var warhead in this.warheads) + warhead.IsArmed = true; + + this.backwardThruster.Enabled = true; + this.aiMove.Enabled = true; + + this.output.Print("Enemy in range, switching to AI mode"); + this.currentState = State.AI; + } + } + + void Detonate() { foreach (var warhead in this.warheads) @@ -216,9 +319,14 @@ namespace IngameScript { } - double MsSinceLaunch + //double MsSinceLaunch + //{ + // get { return (double)this.tickFromStart / 60 * 1000; } + //} + + double DistanceFromLaunch { - get { return (double)this.tickFromStart / 60 * 1000; } + get { return (this.forwardThruster.GetPosition() - this.launchPosition).Length(); } } public void Main(string argument, UpdateType updateSource)