public bool AtWaypoint(Waypoint w) { if (w.Position != Vector3.One && w.Position != Vector3.Zero) { var speed = (float)(Controller.GetShipVelocities().LinearVelocity - w.Velocity).Length(); Vector3D posError = Destination - Reference.WorldMatrix.Translation; var distance = (float)posError.Length(); if (distance > 0.25f || speed > 0.25f) { return(false); } } if (w.Direction != Vector3.One && w.Direction != Vector3.Zero) { if (VectorHelpers.VectorAngleBetween(Reference.WorldMatrix.Forward, ForwardDir) > 0.03f) { return(false); } } if (w.DirectionUp != Vector3.One && w.DirectionUp != Vector3.Zero) { if (VectorHelpers.VectorAngleBetween(Reference.WorldMatrix.Up, UpDir) > 0.03f) { return(false); } } return(true); }
void GetRotationAngles(Vector3D v_target, Vector3D v_front, Vector3D v_left, Vector3D v_up, out double yaw, out double pitch) { //Dependencies: VectorProjection() | VectorAngleBetween() var projectTargetUp = VectorHelpers.VectorProjection(v_target, v_up); var projTargetFrontLeft = v_target - projectTargetUp; yaw = VectorHelpers.VectorAngleBetween(v_front, projTargetFrontLeft); if (Vector3D.IsZero(projTargetFrontLeft) && !Vector3D.IsZero(projectTargetUp)) //check for straight up case { pitch = MathHelper.PiOver2; } else { pitch = VectorHelpers.VectorAngleBetween(v_target, projTargetFrontLeft); //pitch should not exceed 90 degrees by nature of this definition } //---Check if yaw angle is left or right //multiplied by -1 to convert from right hand rule to left hand rule yaw = -1 * Math.Sign(v_left.Dot(v_target)) * yaw; //---Check if pitch angle is up or down pitch = Math.Sign(v_up.Dot(v_target)) * pitch; //---Check if target vector is pointing opposite the front vector if (Math.Abs(yaw) <= 1E-6 && v_target.Dot(v_front) < 0) { yaw = Math.PI; } }
private void NeutralControl(Vector3D gravDir) { Drive.Move(Vector3D.Zero); Vector3D turnTarget = Drive.Controller.WorldMatrix.Forward + Drive.Controller.RotationIndicator.Y * Drive.Controller.WorldMatrix.Right * 0.2; turnTarget = turnTarget - VectorHelpers.VectorProjection(turnTarget, gravDir); Drive.Turn(turnTarget); Drive.Drift(Vector3D.Zero); Drive.Spin(-gravDir); }
void SetGyroPowers(bool fake = false) { if (fake) { return; } if (reference == null) { return; } double yawAngle = 0, pitchAngle = 0, spinAngle = 0; if (targetDirection != Vector3.Zero || targetUp != Vector3.Zero) { if (targetDirection != Vector3.Zero) { GetRotationAngles(targetDirection, reference.WorldMatrix.Forward, reference.WorldMatrix.Left, reference.WorldMatrix.Up, out yawAngle, out pitchAngle); } if (targetUp != Vector3.Zero) { var projectedTargetUp = targetUp - reference.WorldMatrix.Forward.Dot(targetUp) * reference.WorldMatrix.Forward; spinAngle = -1 * VectorHelpers.VectorAngleBetween(reference.WorldMatrix.Up, projectedTargetUp) * Math.Sign(reference.WorldMatrix.Left.Dot(targetUp)); } if (DYaw == 0) { DYaw = yawAngle; } if (DPitch == 0) { DPitch = pitchAngle; } IYaw += yawAngle * kRunEveryXUpdates; IPitch += pitchAngle * kRunEveryXUpdates; // no point in trying to spin over 180 deg in a direction. IYaw = MathHelper.Clamp(IYaw, -1.0, 1.0); IPitch = MathHelper.Clamp(IPitch, -1.0, 1.0); ApplyGyroOverride(pitchAngle * RP + (pitchAngle - DPitch) * RD * kInverseTimeStep + IPitch * RI, yawAngle * RP + (yawAngle - DYaw) * RD * kInverseTimeStep + IYaw * RI, spinAngle * RP, gyros, reference); } if (!Persist && Math.Abs(yawAngle) < 0.01f && Math.Abs(pitchAngle) < 0.01f && Math.Abs(spinAngle) < 0.01f) { targetDirection = Vector3.Zero; targetUp = Vector3.Zero; } if (targetDirection == Vector3.Zero && targetUp == Vector3.Zero) { ClearGyros(); } }
void Attack(TimeSpan localTime) { FriendlyShipScratchpad.Clear(); var intelItems = IntelProvider.GetFleetIntelligences(localTime); foreach (var kvp in intelItems) { if (kvp.Key.Item1 == IntelItemType.Friendly) { var friendly = (FriendlyShipIntel)kvp.Value; if (friendly.AgentClass == AgentClass.Fighter && (friendly.AgentStatus & AgentStatus.Docked) != 0 && (friendly.GetPositionFromCanonicalTime(localTime + IntelProvider.CanonicalTimeDiff) - Controller.GetPosition()).Length() < 100) { FriendlyShipScratchpad.Add(friendly); } } } if (FriendlyShipScratchpad.Count == 0) { return; } for (int i = 0; i < FriendlyShipScratchpad.Count; i++) { var targetWaypoint = new Waypoint(); var gravDir = Controller.GetNaturalGravity(); targetWaypoint.Position = Controller.GetPosition(); var angle = 2 * i * Math.PI / FriendlyShipScratchpad.Count; if (gravDir != Vector3D.Zero) { gravDir.Normalize(); var flatForward = Controller.WorldMatrix.Forward - VectorHelpers.VectorProjection(Controller.WorldMatrix.Forward, gravDir); flatForward.Normalize(); var flatLeftDir = Vector3D.Cross(flatForward, gravDir); targetWaypoint.Position += (flatForward * TrigHelpers.FastCos(angle) + flatLeftDir * TrigHelpers.FastSin(angle)) * 500; targetWaypoint.Position -= gravDir * 200; } else { targetWaypoint.Position += (Controller.WorldMatrix.Forward * TrigHelpers.FastCos(angle) + Controller.WorldMatrix.Left * TrigHelpers.FastSin(angle)) * 500; } targetWaypoint.Position += Controller.GetShipVelocities().LinearVelocity * 3; IntelProvider.ReportFleetIntelligence(targetWaypoint, localTime); IntelProvider.ReportCommand(FriendlyShipScratchpad[i], TaskType.Attack, MyTuple.Create(IntelItemType.Waypoint, targetWaypoint.ID), localTime); } }
public void Turn(MatrixD Reference, Vector3D target) { if (Reference == MatrixD.Zero) { return; } MatrixD orientationMatrix = MatrixD.Identity; orientationMatrix.Translation = Reference.Translation; Vector3D orientationForward = Controller.WorldMatrix.Forward + Controller.WorldMatrix.Down + Controller.WorldMatrix.Left; orientationForward.Normalize(); orientationMatrix.Forward = orientationForward; Vector3D orientationUp = Reference.Forward; orientationUp -= VectorHelpers.VectorProjection(orientationUp, orientationForward); orientationUp.Normalize(); orientationMatrix.Up = orientationUp; Vector3D OrientationRight = orientationForward.Cross(orientationUp); orientationMatrix.Right = OrientationRight; var gravDir = Controller.GetNaturalGravity(); gravDir.Normalize(); double yawAngle, pitchAngle, spinAngle; GravAngle = VectorHelpers.VectorAngleBetween(gravDir, orientationMatrix.Forward); if (target != Vector3D.Zero && GravAngle < Math.PI * 0.1) { Vector3D TargetDir = target - orientationMatrix.Translation; TargetDir.Normalize(); var projectedTargetUp = TargetDir - VectorHelpers.VectorProjection(TargetDir, orientationForward); spinAngle = -1 * VectorHelpers.VectorAngleBetween(orientationMatrix.Up, projectedTargetUp) * Math.Sign(orientationMatrix.Left.Dot(TargetDir)); } else { spinAngle = 0; SpinPID.Reset(); } TrigHelpers.GetRotationAngles(gravDir, orientationMatrix.Forward, orientationMatrix.Left, orientationMatrix.Up, out yawAngle, out pitchAngle); TrigHelpers.ApplyGyroOverride(PitchPID.Control(pitchAngle), YawPID.Control(yawAngle), SpinPID.Control(spinAngle), Gyros, orientationMatrix); }
public bool AtWaypoint(Waypoint w) { if (Persist) { return(false); } if (w.Position != Vector3.One && w.Position != Vector3.Zero) { var speed = (float)(controller.GetShipVelocities().LinearVelocity - w.Velocity).Length(); Vector3D posError = (targetPosition - reference.WorldMatrix.Translation); var distance = (float)posError.Length(); if (distance > 0.25f || speed > 0.25f) { return(false); } } if (w.Direction != Vector3.One && w.Direction != Vector3.Zero) { double yawAngle, pitchAngle; GetRotationAngles(w.Direction, reference.WorldMatrix.Forward, reference.WorldMatrix.Left, reference.WorldMatrix.Up, out yawAngle, out pitchAngle); if (Math.Abs(yawAngle) > 0.03f || Math.Abs(pitchAngle) > 0.03f) { return(false); } } if (w.DirectionUp != Vector3.One && w.DirectionUp != Vector3.Zero) { var projectedTargetUp = targetUp - reference.WorldMatrix.Forward.Dot(targetUp) * reference.WorldMatrix.Forward; var spinAngle = -1 * VectorHelpers.VectorAngleBetween(reference.WorldMatrix.Up, projectedTargetUp) * Math.Sign(reference.WorldMatrix.Left.Dot(targetUp)); if (Math.Abs(spinAngle) > 0.03f) { return(false); } } return(true); }
public void Update(TimeSpan timestamp, UpdateFrequency updateFlags) { runs++; if (runs % 5 == 0) { statusBuilder.Clear(); indicatorBuilder.Clear(); bool firing = false; var index = Indicator.CustomName.IndexOf('|') + 1; if (index <= 0) { return; } string originalName = Indicator.CustomName.Substring(0, index); if (Context.WCAPI == null) { return; } var gravDir = IntelProvider.Controller.GetNaturalGravity(); var gravStr = gravDir.Normalize(); if (!active) { indicatorBuilder.Append("OFF"); NeutralControl(gravDir); } else { var target = Context.WCAPI.GetAiFocus(Context.Reference.CubeGrid.EntityId); if (!target.HasValue || target.Value.IsEmpty()) { indicatorBuilder.Append("NO TGT"); NeutralControl(gravDir); } else { var velocity = IntelProvider.Controller.GetShipVelocities().LinearVelocity; var relativeVector = target.Value.Position - IntelProvider.Controller.WorldMatrix.Translation; var relativeVelocity = target.Value.Velocity - velocity; var planarVector = relativeVector - VectorHelpers.VectorProjection(relativeVector, gravDir); planarVector.Normalize(); var targetPos = target.Value.Position - gravDir * range + planarVector * 50; statusBuilder.AppendLine((gravDir * range).ToString()); Drive.Move(targetPos); if ((targetPos - IntelProvider.Controller.WorldMatrix.Translation).Length() < 100) { Drive.Move(Vector3D.Zero); } Drive.Drift(target.Value.Velocity); var VerticalAngleToTarget = VectorHelpers.VectorAngleBetween(gravDir, relativeVector); planarVector -= gravDir * Math.Tan(VerticalAngleToTarget > 20 * Math.PI / 180 ? 0 : VerticalAngleToTarget); Drive.Turn(planarVector); Drive.Spin(-gravDir); indicatorBuilder.Append("TGT:"); indicatorBuilder.Append(target.Value.Name.Length > 4 ? target.Value.Name.Substring(0, 4) : target.Value.Name); indicatorBuilder.Append(" - DIST:"); indicatorBuilder.Append(relativeVector.Length().ToString("F")); indicatorBuilder.Append(" - STUS:"); // Fire control if (VerticalAngleToTarget > 20 * Math.PI / 180) { indicatorBuilder.Append(" APPROACH"); } else { indicatorBuilder.Append(" AIM "); var angleToTargetDegrees = VectorHelpers.VectorAngleBetween(Gun.WorldMatrix.Forward, relativeVector) * 180 / Math.PI; indicatorBuilder.Append(angleToTargetDegrees.ToString("F")); if (angleToTargetDegrees < 0.5 && Context.WCAPI.IsWeaponReadyToFire(Gun)) { indicatorBuilder.Clear(); indicatorBuilder.Append("FIRING!"); firing = true; } } } } Indicator.CustomName = originalName + " " + indicatorBuilder.ToString(); Context.WCAPI.ToggleWeaponFire(Gun, firing, true); } }
public void Main(string argument, UpdateType updateSource) { subsystemManager.UpdateTime(); if (argument == "descend") { Mode = 1; lockMatrix = Drive.Controller.WorldMatrix; } else if (argument == "ascend") { Mode = 2; lockMatrix = Drive.Controller.WorldMatrix; } else if (argument == "stop") { Mode = 0; lockMatrix = MatrixD.Zero; Drive.Clear(); } else if (commandLine.TryParse(argument)) { subsystemManager.Command(commandLine.Argument(0), commandLine.Argument(1), commandLine.ArgumentCount > 2 ? commandLine.Argument(2) : null); } else { try { subsystemManager.Update(updateSource); runs++; if (runs % 5 == 0) { OutputBuilder.Clear(); OutputBuilder.Append($"STATUS: ").AppendLine(Mode == 0 ? "STOP" : (Mode == 1 ? "DESC" : "ASCE")); foreach (var screen in Displays) { screen.ContentType = ContentType.TEXT_AND_IMAGE; screen.WriteText(OutputBuilder.ToString()); } var destination = new Waypoint(); if (Mode == 0) { Drive.Clear(); } else if (Mode == 1) { destination.MaxSpeed = DescendSpeed; var gravdir = Cockpit.GetNaturalGravity(); if (gravdir == Vector3D.Zero) { gravdir.Normalize(); destination.Position = gravdir * 10 + Cockpit.GetPosition(); var flatForward = Cockpit.WorldMatrix.Forward - VectorHelpers.VectorProjection(Cockpit.WorldMatrix.Forward, gravdir); flatForward.Normalize(); var flatLeft = Cockpit.WorldMatrix.Left - VectorHelpers.VectorProjection(Cockpit.WorldMatrix.Forward, gravdir); flatLeft.Normalize(); destination.Direction = flatForward * TrigHelpers.FastCos(0.02 * RotateSpeed) + flatLeft * TrigHelpers.FastSin(0.02 * RotateSpeed); } else { destination.Position = lockMatrix.Down * 10 + Cockpit.GetPosition(); destination.DirectionUp = lockMatrix.Up; var flatForward = Cockpit.WorldMatrix.Forward - VectorHelpers.VectorProjection(Cockpit.WorldMatrix.Forward, lockMatrix.Down); flatForward.Normalize(); var flatLeft = Cockpit.WorldMatrix.Left - VectorHelpers.VectorProjection(Cockpit.WorldMatrix.Forward, lockMatrix.Down); flatLeft.Normalize(); destination.Direction = flatForward * TrigHelpers.FastCos(0.02 * RotateSpeed) + flatLeft * TrigHelpers.FastSin(0.02 * RotateSpeed); } } else if (Mode == 2) { destination.MaxSpeed = AscendSpeed; if (Drive.Controller == Cockpit) { var gravdir = Cockpit.GetNaturalGravity(); gravdir.Normalize(); destination.Position = -gravdir * 10 + Cockpit.GetPosition(); } else { destination.Position = lockMatrix.Down * 10 + Cockpit.GetPosition(); destination.Direction = lockMatrix.Forward; } } Drive.Move(destination.Position); Drive.Turn(destination.Direction); Drive.Spin(destination.DirectionUp); Drive.SetMaxSpeed(destination.MaxSpeed); } } catch (Exception e) { Me.GetSurface(0).WriteText(e.Message); Me.GetSurface(0).WriteText("\n", true); Me.GetSurface(0).WriteText(e.StackTrace); Me.GetSurface(0).WriteText("\n", true); Me.GetSurface(0).WriteText(e.ToString()); } var s = subsystemManager.GetStatus(); if (!string.IsNullOrEmpty(s)) { Echo(s); } else { Echo(((int)subsystemManager.OutputMode).ToString()); } } }
public void Update(TimeSpan timestamp, UpdateFrequency updateFlags) { runs++; if (runs % 10 == 0) { indicatorBuilder.Clear(); var index = Indicator.CustomName.IndexOf('|') + 1; if (index <= 0) { return; } string originalName = Indicator.CustomName.Substring(0, index); if (Context.WCAPI == null) { return; } var rotationIndicator = Vector3.NegativeInfinity; var movementIndicator = Vector3.NegativeInfinity; if (!active) { indicatorBuilder.Append("OFF"); } else { var target = Context.WCAPI.GetAiFocus(Context.Reference.CubeGrid.EntityId); if (target == null) { indicatorBuilder.Append("NO TGT"); } else { var gravDir = IntelProvider.Controller.GetNaturalGravity(); var gravStr = gravDir.Normalize(); var velocity = IntelProvider.Controller.GetShipVelocities().LinearVelocity; var relativeVector = target.Value.Position - IntelProvider.Controller.WorldMatrix.Translation; var relativeVelocity = target.Value.Velocity - velocity; var heightSquared = VectorHelpers.VectorProjection(relativeVector, gravDir).LengthSquared(); var relativeplanarDir = relativeVector - VectorHelpers.VectorProjection(relativeVector, gravDir); var relativeplanarDist = relativeplanarDir.Normalize(); var relativePlanarVelocity = relativeVelocity - VectorHelpers.VectorProjection(relativeVelocity, gravDir); // Attack dir var relativeAttackPoint = AttackHelpers.GetAttackPoint(relativeVelocity, relativeVector, projectileSpeed); var attackPlanarVector = relativeAttackPoint - VectorHelpers.VectorProjection(relativeAttackPoint, gravDir); var attackPlanarLeft = IntelProvider.Controller.WorldMatrix.Left - VectorHelpers.VectorProjection(IntelProvider.Controller.WorldMatrix.Left, gravDir); attackPlanarLeft.Normalize(); var attackPlanarForward = IntelProvider.Controller.WorldMatrix.Forward - VectorHelpers.VectorProjection(IntelProvider.Controller.WorldMatrix.Forward, gravDir); attackPlanarForward.Normalize(); var spinAngle = VectorHelpers.VectorAngleBetween(attackPlanarForward, attackPlanarVector) * Math.Sign(-attackPlanarLeft.Dot(attackPlanarVector)); rotationIndicator.Y = (float)spinAngle; // Movement var myPlanarVelocity = velocity - VectorHelpers.VectorProjection(relativeAttackPoint, gravDir); var targetPlanarDist = Math.Sqrt(range * range - heightSquared); var targetPlanarPoint = relativeplanarDir * (relativeplanarDist - targetPlanarDist); var desiredRelativeVelocity = targetPlanarPoint * 0.5 + relativePlanarVelocity - myPlanarVelocity; desiredRelativeVelocity.Normalize(); movementIndicator.X = (float)desiredRelativeVelocity.Dot(IntelProvider.Controller.WorldMatrix.Right); movementIndicator.Z = (float)desiredRelativeVelocity.Dot(IntelProvider.Controller.WorldMatrix.Backward); indicatorBuilder.Append("TGT:"); indicatorBuilder.Append(target.Value.Name.Substring(0, 4)); indicatorBuilder.Append(" - DIST:"); indicatorBuilder.Append(relativeVector.Length().ToString("F")); indicatorBuilder.Append(" - "); indicatorBuilder.Append(movementIndicator.X.ToString("F")); indicatorBuilder.Append(","); indicatorBuilder.Append(movementIndicator.Z.ToString("F")); indicatorBuilder.Append(" -- "); indicatorBuilder.Append(spinAngle.ToString("F")); } } Indicator.CustomName = originalName + " " + indicatorBuilder.ToString(); Drive.RotationIndicatorOverride = rotationIndicator; Drive.MoveIndicatorOverride = movementIndicator; } }
public void Drive(Vector3D Destination) { if (Destination == Vector3D.Zero) { return; } if (GravAngle > Math.PI * 0.1) { foreach (var engine in HoverEngines) { engine.Block.Enabled = true; engine.OverridePercentage = 0; engine.AltitudeMin = DesiredAltitude / VertiHoriForceRatio; } return; } var gravDir = Controller.GetNaturalGravity(); var gravStr = gravDir.Length(); gravDir.Normalize(); var destDir = Destination - Controller.WorldMatrix.Translation; destDir -= VectorHelpers.VectorProjection(destDir, gravDir); var dist = destDir.Length(); Arrived = dist < 20; destDir.Normalize(); var maxSpeed = SpeedLimit == 0 ? Math.Min(100, GetMaxSpeedFromBrakingDistance((float)dist)) : SpeedLimit; var currentVel = Controller.GetShipVelocities().LinearVelocity; var horiVel = currentVel - VectorHelpers.VectorProjection(Controller.GetShipVelocities().LinearVelocity, gravDir); var vertiVel = currentVel.Dot(-gravDir); var accelDir = maxSpeed * destDir - horiVel; accelDir.Normalize(); var mass = Controller.CalculateShipMass().PhysicalMass; var gravForce = gravStr * mass; DirForces.Clear(); Dirs.Clear(); Dirs.Add(Controller.WorldMatrix.Forward); Dirs.Add(Controller.WorldMatrix.Down); Dirs.Add(Controller.WorldMatrix.Left); float alpha = 0; double altitude; Controller.TryGetPlanetElevation(MyPlanetElevation.Surface, out altitude); DesiredVerticalVel = DesiredAltitude - altitude; var altAdjust = DesiredVerticalVel - vertiVel; Vector3D PrimaryDriveDir = Vector3D.Zero; Vector3D SecondaryDriveDir = Vector3D.Zero; Vector3D OpposDriveDir = Vector3D.Zero; foreach (var dir in Dirs) { var engineDir = dir; engineDir -= VectorHelpers.VectorProjection(engineDir, gravDir); engineDir.Normalize(); var engineAngleDiff = VectorHelpers.VectorAngleBetween(engineDir, accelDir); if (engineAngleDiff < 0.3333333333333 * Math.PI) { DirForces[dir] = 0; OpposDriveDir = dir; } else if (engineAngleDiff > 2 * 0.3333333333333 * Math.PI) { DirForces[dir] = 1f; PrimaryDriveDir = dir; } else { var aPrime = 1 / (TrigHelpers.fastTan(engineAngleDiff - Math.PI * 0.333333333) * sqrt3inv + 1); DirForces[dir] = (float)(1 - aPrime) * 2; SecondaryDriveDir = dir; alpha = DirForces[dir]; } } var primaryDriveForce = MaxForce * VerticalForceRatio; var secondaryDriveForce = primaryDriveForce * alpha; var totalUpForce = primaryDriveForce + secondaryDriveForce; var multiplier = (gravForce + altAdjust * mass) / totalUpForce; Status = $"{altAdjust}, {dist}"; if (PrimaryDriveDir != Vector3D.Zero) { DirForces[PrimaryDriveDir] = Math.Max(0.01f, (float)multiplier); } if (SecondaryDriveDir != Vector3D.Zero) { DirForces[SecondaryDriveDir] = (float)Math.Max(0.01f, alpha * (float)multiplier); } var altMin = 1; if (altitude > 7) { altMin = 6; } if (altitude > 40) { altMin = 10; } foreach (var engine in HoverEngines) { engine.AltitudeMin = altMin; engine.Block.Enabled = OpposDriveDir != engine.Block.WorldMatrix.Forward; engine.OverridePercentage = DirForces[engine.Block.WorldMatrix.Forward]; } }
void GetMovementVectors(Vector3D target, IMyShipController controller, IMyTerminalBlock reference, float maxThrust, float maxSpeed, out Vector3D AutopilotMoveIndicator, ref Vector3D D, ref Vector3D I) { if (controller == null) { AutopilotMoveIndicator = Vector3D.Zero; return; } var speed = (float)(controller.GetShipVelocities().LinearVelocity - targetDrift).Length(); Vector3D currentVelocity = controller.GetShipVelocities().LinearVelocity; float aMax = 0.8f * maxThrust / controller.CalculateShipMass().PhysicalMass; Vector3D desiredVelocity = targetDrift; Vector3D posError = target - reference.WorldMatrix.Translation; var distance = (float)posError.Length(); posError.Normalize(); if (target != Vector3D.Zero) { float desiredSpeed = Math.Min((float)Math.Sqrt(2f * aMax * distance) * 0.01f * (100 - (float)targetDrift.Length()), maxSpeed); desiredSpeed = Math.Min(distance * distance * 2f, desiredSpeed); desiredVelocity += posError * desiredSpeed; } Vector3D adjustVector = currentVelocity - targetDrift - VectorHelpers.VectorProjection(currentVelocity - targetDrift, desiredVelocity - targetDrift); if (adjustVector.Length() < (currentVelocity - targetDrift).Length() * 0.1) { adjustVector = Vector3.Zero; } Vector3D Error = (desiredVelocity - currentVelocity - adjustVector * 1) * 60 / (aMax * kRunEveryXUpdates); float kP = TP; float kI = TI; float kD = TD; if (Error.LengthSquared() > 1) { Error.Normalize(); } else { kP = TP2; kI = TI2; kD = TD2; } if (D == Vector3.Zero) { D = Error; } AutopilotMoveIndicator = kP * Error + kD * (Error - D) * kInverseTimeStep + kI * I; // decrease speed when close and slow if (distance < 10 && speed < 10) { AutopilotMoveIndicator *= 0.5f; } if (AutopilotMoveIndicator.Length() > 1) { AutopilotMoveIndicator /= AutopilotMoveIndicator.Length(); } I += Error * kRunEveryXUpdates; if (I.Length() > 5) { I *= 5 / I.Length(); } D = Error; // if close enough, stop. if (targetDrift == Vector3D.Zero && distance < 0.25f && speed < 0.25f) { targetPosition = Vector3.Zero; AutopilotMoveIndicator = Vector3.Zero; I = Vector3.Zero; D = Vector3.Zero; } }
// Gets the maximum angle deviation from vertical the drone is allowed to operate in double GetMaxAngleConstraint() { var gravAngle = VectorHelpers.VectorAngleBetween(gravDir, Controller.WorldMatrix.Down); return(Math.Max(gravAngle, MaxAngleDegrees * Math.PI / 180)); }
public void Update(TimeSpan timestamp, UpdateFrequency updateFlags) { runs++; if (runs % 30 == 0) { MaxLiftThrust = 0; MaxLateralThrust = 0; MaxDownThrust = 0; foreach (var kvp in Thrusters) { if (kvp.Key == Base6Directions.Direction.Down) { foreach (var thruster in kvp.Value) { MaxLiftThrust += thruster.MaxEffectiveThrust; } } else if (kvp.Key == Base6Directions.Direction.Forward) { foreach (var thruster in kvp.Value) { MaxLateralThrust += thruster.MaxEffectiveThrust; } } else if (kvp.Key == Base6Directions.Direction.Up) { foreach (var thruster in kvp.Value) { MaxDownThrust += thruster.MaxEffectiveThrust; } } ThrusterManagers[kvp.Key].RecalculateThrust(); } } if (runs % 5 == 0) { StatusBuilder.Clear(); shipMass = Controller.CalculateShipMass().PhysicalMass; gravDir = Controller.GetNaturalGravity(); double yawAngle, pitchAngle, spinAngle; yawAngle = pitchAngle = spinAngle = 0; MatrixD orientationMatrix = new MatrixD(); var flatCurrentDir = Controller.WorldMatrix.Forward - VectorHelpers.VectorProjection(Controller.WorldMatrix.Forward, gravDir); flatCurrentDir.Normalize(); var flatLeftDir = Vector3D.Cross(flatCurrentDir, gravDir); if (gravDir != Vector3D.Zero) { gravStr = gravDir.Length(); gravDir.Normalize(); // Rotational Control var targetDir = Vector3D.Zero; if (ForwardDir != Vector3D.Zero) { targetDir = ForwardDir; } else if (FullAuto) { targetDir = Controller.WorldMatrix.Forward - VectorHelpers.VectorProjection(Controller.WorldMatrix.Forward, gravDir); } if (targetDir != Vector3D.Zero) { if (UpDir == Vector3D.Zero) { var angleFromVertical = VectorHelpers.VectorAngleBetween(targetDir, gravDir) - Math.PI * 0.5; var maxAngleFromVertical = GetMaxAngleConstraint(); angleFromVertical = Math.Max(Math.Min(angleFromVertical, maxAngleFromVertical), -maxAngleFromVertical); var flatAimDir = targetDir - VectorHelpers.VectorProjection(targetDir, gravDir); flatAimDir.Normalize(); var downDir = TrigHelpers.FastCos(angleFromVertical) * gravDir + TrigHelpers.FastSin(angleFromVertical) * flatAimDir; orientationMatrix.Forward = Controller.WorldMatrix.Down; orientationMatrix.Left = Controller.WorldMatrix.Left; orientationMatrix.Up = Controller.WorldMatrix.Forward; spinAngle = -VectorHelpers.VectorAngleBetween(flatAimDir, flatCurrentDir) * Math.Sign(Controller.WorldMatrix.Left.Dot(flatAimDir)); TrigHelpers.GetRotationAngles(downDir, orientationMatrix.Forward, orientationMatrix.Left, orientationMatrix.Up, out yawAngle, out pitchAngle); } else { orientationMatrix = reference.WorldMatrix; TrigHelpers.GetRotationAngles(ForwardDir, reference.WorldMatrix.Forward, reference.WorldMatrix.Left, reference.WorldMatrix.Up, out yawAngle, out pitchAngle); var projectedTargetUp = UpDir - reference.WorldMatrix.Forward.Dot(UpDir) * reference.WorldMatrix.Forward; spinAngle = -1 * VectorHelpers.VectorAngleBetween(reference.WorldMatrix.Up, projectedTargetUp) * Math.Sign(reference.WorldMatrix.Left.Dot(UpDir)); } } } else if (ForwardDir != Vector3D.Zero) { orientationMatrix = reference.WorldMatrix; TrigHelpers.GetRotationAngles(ForwardDir, reference.WorldMatrix.Forward, reference.WorldMatrix.Left, reference.WorldMatrix.Up, out yawAngle, out pitchAngle); if (UpDir != Vector3D.Zero) { var projectedTargetUp = UpDir - reference.WorldMatrix.Forward.Dot(UpDir) * reference.WorldMatrix.Forward; spinAngle = -1 * VectorHelpers.VectorAngleBetween(reference.WorldMatrix.Up, projectedTargetUp) * Math.Sign(reference.WorldMatrix.Left.Dot(UpDir)); } } if (yawAngle != 0 || pitchAngle != 0 || spinAngle != 0) { TrigHelpers.ApplyGyroOverride(PitchPID.Control(pitchAngle), YawPID.Control(yawAngle), gravDir == Vector3D.Zero ? spinAngle : SpinPID.Control(spinAngle), Gyros, orientationMatrix); } else { foreach (var gyro in Gyros) { if (gyro.GyroOverride) { gyro.GyroOverride = false; } } } // Translational Control if (Destination == Vector3D.Zero && TargetDrift == Vector3D.Zero) { foreach (var kvp in ThrusterManagers) { kvp.Value.SetThrust(0); } if (FullAuto) { Controller.DampenersOverride = true; } } else { Controller.DampenersOverride = false; // Compute direction of motion var destinationDir = Destination - Reference.GetPosition(); var destinationDist = destinationDir.Length(); destinationDir.Normalize(); // Compute current motion to find desired acceleration var currentVel = Controller.GetShipVelocities().LinearVelocity; if (destinationDist < 0.25 && currentVel.Length() < 0.25 && TargetDrift == Vector3D.Zero) { foreach (var kvp in ThrusterManagers) { kvp.Value.SetThrust(0); } Controller.DampenersOverride = true; Destination = Vector3D.Zero; } else { Vector3D desiredVel = Vector3D.Zero; if (Destination != Vector3D.Zero) { var maxSpeed = Math.Min(MaxSpeed, GetMaxSpeedFromBrakingDistance(destinationDist, GetMaxAccelFromAngleDeviation((float)GetMaxAngleConstraint() * MaxAngleTolerance)) * 0.9); maxSpeed = Math.Min(maxSpeed, destinationDist * destinationDist + 0.5); desiredVel = destinationDir * maxSpeed; } desiredVel += TargetDrift; var adjustVector = currentVel - VectorHelpers.VectorProjection(currentVel, desiredVel); var desiredAccel = desiredVel - currentVel - adjustVector * 2; // Transform desired acceleration into remote control frame var gridDesiredAccel = Vector3D.TransformNormal(desiredAccel, MatrixD.Transpose(Controller.WorldMatrix)); double accelMagnitude = gridDesiredAccel.Length(); if (accelMagnitude < PrecisionThreshold) { gridDesiredAccel *= Math.Max(accelMagnitude / PrecisionThreshold, .1); } gridDesiredAccel.X = XPID.Control(gridDesiredAccel.X); gridDesiredAccel.Y = YPID.Control(gridDesiredAccel.Y); gridDesiredAccel.Z = ZPID.Control(gridDesiredAccel.Z); double MinScale = 10; var gridGravDir = Vector3D.TransformNormal(gravDir, MatrixD.Transpose(Controller.WorldMatrix)); foreach (var kvp in ThrusterManagers) { var desiredDirectionalThrust = -1 * Base6Directions.GetVector(kvp.Key).Dot(gridDesiredAccel) * shipMass; var gravAssist = Base6Directions.GetVector(kvp.Key).Dot(gridGravDir) * shipMass; if (desiredDirectionalThrust > 0) { MinScale = Math.Min((kvp.Value.MaxThrust - gravAssist) / desiredDirectionalThrust, MinScale); } } gridDesiredAccel *= MinScale; gridDesiredAccel -= gridGravDir * gravStr; foreach (var kvp in ThrusterManagers) { kvp.Value.SetThrust(-1 * Base6Directions.GetVector(kvp.Key).Dot(gridDesiredAccel + gridGravDir) * shipMass); } } } } }
public void Update(TimeSpan timestamp, UpdateFrequency updateFlags) { runs++; OnRelease = OnRelease || LastFrameMouseDown & !Turret.IsShooting; var a = Turret.Azimuth; var b = Turret.Elevation; var TurretAimRay = Math.Sin(a) * Math.Cos(b) * Turret.WorldMatrix.Left + Math.Cos(a) * Math.Cos(b) * Turret.WorldMatrix.Forward + Math.Sin(b) * Turret.WorldMatrix.Up; var WallPlane = new Plane(Panels[Vector2I.Zero].GetPosition() - Panels[Vector2I.Zero].WorldMatrix.Backward, Panels[Vector2I.Zero].WorldMatrix.Backward); Vector3 Intersection; TrigHelpers.PlaneIntersection(WallPlane, Turret.GetPosition() + Turret.WorldMatrix.Up * 0.579 + Turret.WorldMatrix.Backward * 0.068, TurretAimRay, out Intersection); var CursorDirection = Intersection - Panels[Vector2I.Zero].GetPosition() + Panels[Vector2I.Zero].WorldMatrix.Backward * 1.25 + Panels[Vector2I.Zero].WorldMatrix.Right * 1.25; var CursorDist = CursorDirection.Length(); CursorDirection.Normalize(); // LCD wall configuration: // | | | // | | | // | | | // Cursor position, originating in the middle of the LCD wall, with unit in meters CursorPos = Vector3D.TransformNormal(CursorDirection, MatrixD.Transpose(Panels[Vector2I.Zero].WorldMatrix)) * CursorDist; CursorPos2D = new Vector2((float)CursorPos.X, (float)CursorPos.Y); if (runs % 10 == 0) { DebugBuilder.Clear(); SinViewDegree = Math.Sin(ViewAngleDegrees * Math.PI / 180); CosViewDegree = Math.Cos(ViewAngleDegrees * Math.PI / 180); SpriteScratchpad.Clear(); int i; AddSprite("CircleHollow", new Vector2(0, 0), new Vector2(5, 5 * (float)CosViewDegree)); for (i = 10000; i <= MapSize; i += 10000) { var CircleSize = MapOnScreenSizeMeters * PixelsPerMeter * i / MapSize; AddSprite("CircleHollow", new Vector2(0, 0), new Vector2(CircleSize, CircleSize * (float)CosViewDegree), new Color(1f, 0.4f, 0f, 0.005f)); } var gravDir = Controller.GetNaturalGravity(); // Create map matrix if (gravDir != Vector3D.Zero) { // Within gravity, align with gravity = down // Either use controller's forward direction or north as forward gravDir.Normalize(); var flatNorthDir = new Vector3D(0, 1, 0) - VectorHelpers.VectorProjection(new Vector3D(0, 1, 0), gravDir); flatNorthDir.Normalize(); var flatForwardDir = AlignWithNorth ? flatNorthDir : (Controller.WorldMatrix.Forward - VectorHelpers.VectorProjection(AlignWithNorth ? new Vector3D(0, 1, 0) : Controller.WorldMatrix.Forward, gravDir)); flatForwardDir.Normalize(); var flatLeftDir = Vector3D.Cross(flatForwardDir, gravDir); MapMatrix.Up = -gravDir; MapMatrix.Forward = flatForwardDir; MapMatrix.Left = flatLeftDir; var localNorthDir = Vector3D.TransformNormal(flatNorthDir, MatrixD.Transpose(MapMatrix)); var localWestDir = Vector3D.Cross(localNorthDir, new Vector3D(0, -1, 0)); AddTextSprite("N", LocalCoordsToMapPosition(localNorthDir * MapSize * 0.5, true), 4); AddTextSprite("S", LocalCoordsToMapPosition(-localNorthDir * MapSize * 0.5, true), 4); AddTextSprite("W", LocalCoordsToMapPosition(localWestDir * MapSize * 0.5, true), 4); AddTextSprite("E", LocalCoordsToMapPosition(-localWestDir * MapSize * 0.5, true), 4); } else { // Else... idk just align with world axis? MapMatrix = MatrixD.Identity; } var intelItems = IntelProvider.GetFleetIntelligences(timestamp); DebugBuilder.AppendLine(intelItems.Count.ToString()); SelectionCandidates.Clear(); ClosestItemKey = MyTuple.Create(IntelItemType.NONE, (long)0); ClosestItemDist = 0.3f; LocalCoordsScratchpad.Clear(); ScreenCoordsScratchpad.Clear(); if (ActionMode == ActionSelectPosition) { AddTextSprite("><", CursorPos2D, 1, "Debug"); if (OnRelease) { if (SelectFlatPos == Vector2.PositiveInfinity) { SelectFlatPos = CursorPos2D; } else { SelectedPosition = FlatPosToGlobalPos(SelectFlatPos, CursorPos2D); SelectPositionCallback(timestamp); SelectFlatPos = Vector2.PositiveInfinity; ActionMode = ActionNone; } OnRelease = false; } if (SelectFlatPos != Vector2.PositiveInfinity) { var selectAltitudePos = SelectFlatPos; selectAltitudePos.Y = CursorPos2D.Y; var midPosition = (selectAltitudePos + SelectFlatPos) * 0.5f; var lineLength = Math.Abs(selectAltitudePos.Y - SelectFlatPos.Y); AddSprite("CircleHollow", selectAltitudePos, new Vector2(20, 20)); AddSprite("CircleHollow", SelectFlatPos, new Vector2(30, 30 * (float)CosViewDegree)); AddSprite("SquareSimple", midPosition, new Vector2(2, lineLength * PixelsPerMeter)); } } foreach (var kvp in intelItems) { Vector3D localCoords; Vector2 flatPosition, altitudePosition; GetMapCoordsFromIntel(kvp.Value, timestamp, out localCoords, out flatPosition, out altitudePosition); ScreenCoordsScratchpad.Add(flatPosition); ScreenCoordsScratchpad.Add(altitudePosition); LocalCoordsScratchpad.Add(localCoords); DebugBuilder.AppendLine(localCoords.ToString()); var distToItem = (altitudePosition - CursorPos2D).Length(); if (distToItem < ClosestItemDist) { ClosestItemDist = distToItem; ClosestItemKey = kvp.Key; } } DrawContextMenu(); if (ActionMode == ActionNone) { SelectionCandidates.Add(ClosestItemKey); if (OnRelease) { if (ClosestItemKey.Item1 == IntelItemType.NONE) { SelectedItems.Clear(); } else if (ClosestItemKey.Item1 != IntelItemType.Waypoint) { if (SelectedItems.Count > 0 && SelectedItems[0].Item2 != ClosestItemKey.Item2) { SelectedItems.Clear(); } SelectedItems.Add(ClosestItemKey); } } } i = 0; foreach (var kvp in intelItems) { AddFleetIntelToMap(kvp.Value, timestamp, LocalCoordsScratchpad[i], ScreenCoordsScratchpad[2 * i], ScreenCoordsScratchpad[2 * i + 1]); i++; } // var text = Turret.IsShooting ? "[><]" : "><"; // AddTextSprite(text, CursorPos2D, 2, "Debug"); foreach (var kvp in Panels) { DrawSpritesForPanel(kvp.Key); } OnRelease = false; } LastFrameMouseDown = Turret.IsShooting; }
public void Do(Dictionary <MyTuple <IntelItemType, long>, IFleetIntelligence> IntelItems, TimeSpan canonicalTime, Profiler profiler) { if (canonicalTime == TimeSpan.Zero) { return; } runs++; if (MonitorSubsystem != null && (MonitorSubsystem.GetPercentage(MonitorOptions.Hydrogen) < 0.2 || MonitorSubsystem.GetPercentage(MonitorOptions.Cargo) < 0.02 || MonitorSubsystem.GetPercentage(MonitorOptions.Power) < 0.1)) { GoHome(canonicalTime); return; } IMyShipController controller = Autopilot.Controller; Vector3D linearVelocity = controller.GetShipVelocities().LinearVelocity; var currentPosition = controller.WorldMatrix.Translation; LeadTask.Destination.MaxSpeed = Autopilot.CruiseSpeed; if (!TargetPositionSet) { if (IntelKey.Item1 == IntelItemType.Waypoint && IntelItems.ContainsKey(IntelKey)) { TargetPosition = IntelItems[IntelKey].GetPositionFromCanonicalTime(canonicalTime); PatrolMaxSpeed = ((Waypoint)IntelItems[IntelKey]).MaxSpeed; } TargetPositionSet = true; } EnemyShipIntel orbitIntel = null; EnemyShipIntel shootIntel = null; double closestIntelDist = CombatSystem.AlertDist; foreach (var intel in IntelItems) { if (intel.Key.Item1 != IntelItemType.Enemy) { continue; } var enemyIntel = (EnemyShipIntel)intel.Value; if (!EnemyShipIntel.PrioritizeTarget(enemyIntel)) { continue; } if (IntelProvider.GetPriority(enemyIntel.ID) < 2) { continue; } double dist = (enemyIntel.GetPositionFromCanonicalTime(canonicalTime) - controller.WorldMatrix.Translation).Length(); if (IntelKey.Item1 == IntelItemType.Enemy && enemyIntel.ID != IntelKey.Item2 && FocusedTarget) { continue; } if (enemyIntel.CubeSize == MyCubeSize.Small) { dist -= 300; } if (IntelProvider.GetPriority(enemyIntel.ID) == 3) { dist -= 600; } if (IntelProvider.GetPriority(enemyIntel.ID) == 4) { dist -= 1200; } if (dist < closestIntelDist) { closestIntelDist = dist; shootIntel = enemyIntel; if (enemyIntel.Radius > 30) { orbitIntel = enemyIntel; } } } if (shootIntel == null && CombatSystem.TargetIntel != null && IntelProvider.GetPriority(CombatSystem.TargetIntel.ID) >= 2) { shootIntel = CombatSystem.TargetIntel; } if (orbitIntel == null) { orbitIntel = shootIntel; } var gravdir = Autopilot.Controller.GetNaturalGravity(); if (gravdir != Vector3D.Zero) { gravdir.Normalize(); } // No Target if (orbitIntel == null) { // Plot Intercept if (IntelKey.Item1 == IntelItemType.Enemy && IntelItems.ContainsKey(IntelKey) && EnemyShipIntel.PrioritizeTarget((EnemyShipIntel)IntelItems[IntelKey]) && IntelProvider.GetPriority(IntelKey.Item2) >= 2) { var target = IntelItems[IntelKey]; LeadTask.Destination.Position = currentPosition + AttackHelpers.GetAttackPoint(target.GetVelocity(), target.GetPositionFromCanonicalTime(canonicalTime) + target.GetVelocity() * 0.08 - currentPosition, Autopilot.CruiseSpeed); } // Go to Position ( Scramble ) else if (TargetPosition != Vector3.Zero) { LeadTask.Destination.MaxSpeed = PatrolMaxSpeed; LeadTask.Destination.Position = TargetPosition; } else { GoHome(canonicalTime); return; } Vector3D toTarget = LeadTask.Destination.Position - Program.Me.WorldMatrix.Translation; if (toTarget.LengthSquared() > 400) { if (gravdir == Vector3D.Zero) { LeadTask.Destination.Direction = toTarget; } else { LeadTask.Destination.Direction = Vector3D.Zero; } } else { LeadTask.Destination.Direction = Vector3D.Zero; } LastAcceleration = Vector3D.Zero; LastReference = MatrixD.Zero; LastEnemyVelocity = Vector3D.Zero; LastEnemyPosition = Vector3D.Zero; LastRelativeAttackPoint = Vector3D.Zero; // targetLastPoweredRun = 0; } // Orbiting a Target else { CombatSystem.MarkEngaged(); LeadTask.Destination.MaxSpeed = Autopilot.CombatSpeed; Vector3D targetPosition = orbitIntel.GetPositionFromCanonicalTime(canonicalTime); var periodicFactor = runs * Math.PI * CombatSystem.EngageTheta / 4; Vector3D periodicDirection = Math.Sin(periodicFactor) * controller.WorldMatrix.Left + Math.Cos(periodicFactor) * controller.WorldMatrix.Up; var Acceleration = linearVelocity - LastLinearVelocity; if (LastAcceleration == Vector3D.Zero) { LastAcceleration = Acceleration; } if (LastReference == MatrixD.Zero) { LastReference = controller.WorldMatrix; } if (LastEnemyVelocity == Vector3D.Zero) { LastEnemyVelocity = shootIntel.GetVelocity(); } if (LastEnemyPosition == Vector3D.Zero) { LastEnemyPosition = shootIntel.GetPositionFromCanonicalTime(canonicalTime); } var enemyAcceleration = shootIntel.GetVelocity() - LastEnemyVelocity; var enemyVelocityAdjust = shootIntel.GetVelocity() * 2 - LastEnemyVelocity; var CurrentAccelerationPreviousFrame = Vector3D.TransformNormal(Acceleration, MatrixD.Transpose(LastReference)); var accelerationAdjust = Vector3D.TransformNormal(CurrentAccelerationPreviousFrame, controller.WorldMatrix); var velocityAdjust = linearVelocity + accelerationAdjust * 0.4; velocityAdjust *= CombatSystem.OwnSpeedMultiplier; Vector3D relativeAttackPoint = AttackHelpers.GetAttackPoint(enemyVelocityAdjust - velocityAdjust, shootIntel.GetPositionFromCanonicalTime(canonicalTime) + enemyVelocityAdjust * 0.25 - controller.WorldMatrix.Translation - velocityAdjust * 0.25, CombatSystem.ProjectileSpeed); relativeAttackPoint.Normalize(); if (LastRelativeAttackPoint == Vector3D.Zero) { LastRelativeAttackPoint = relativeAttackPoint; } LastAcceleration = linearVelocity - LastLinearVelocity; LeadTask.Destination.Direction = relativeAttackPoint; if ((controller.WorldMatrix.Translation - targetPosition).Length() < CombatSystem.FireDist && VectorHelpers.VectorAngleBetween(LeadTask.Destination.Direction, controller.WorldMatrix.Forward) < CombatSystem.FireTolerance) { CombatSystem.Fire(); } Vector3D dirTargetToMe = controller.WorldMatrix.Translation - targetPosition; var distTargetToMe = dirTargetToMe.Length(); dirTargetToMe.Normalize(); if (Mode == 0) { Vector3D dirTargetToOrbitTarget = Vector3D.Cross(dirTargetToMe, controller.WorldMatrix.Up); dirTargetToOrbitTarget.Normalize(); if (gravdir == Vector3D.Zero) { LeadTask.Destination.DirectionUp = Math.Sin(CombatSystem.EngageTheta) * controller.WorldMatrix.Right + Math.Cos(CombatSystem.EngageTheta) * controller.WorldMatrix.Up; LeadTask.Destination.Position = targetPosition + orbitIntel.GetVelocity() + dirTargetToMe * CombatSystem.EngageDist + dirTargetToOrbitTarget * 200; } else { var flatDirTargetToMe = dirTargetToMe - VectorHelpers.VectorProjection(dirTargetToMe, gravdir); flatDirTargetToMe.Normalize(); LeadTask.Destination.Position = targetPosition + orbitIntel.GetVelocity() + flatDirTargetToMe * CombatSystem.EngageDist * 0.9 - gravdir * 300 + periodicDirection * 100; } LeadTask.Destination.Velocity = orbitIntel.GetVelocity() * 0.5; } else if (Mode == 2) { LeadTask.Destination.Position = targetPosition + dirTargetToMe * (CombatSystem.EngageDist + (CombatSystem.EngageDist - distTargetToMe)); LeadTask.Destination.Velocity = orbitIntel.GetVelocity(); } LastReference = controller.WorldMatrix; LastEnemyVelocity = shootIntel.GetVelocity(); LastEnemyPosition = shootIntel.GetPositionFromCanonicalTime(canonicalTime); LastRelativeAttackPoint = relativeAttackPoint; //var n = VectorHelpers.VectorProjection(enemyAcceleration, gravdir).Length() / enemyAcceleration.Length(); // //if (targetLastPoweredRun == 0 || n < 0.6) // targetLastPoweredRun = runs; // //if (runs - targetLastPoweredRun > 20) // IntelProvider.SetPriority(shootIntel.ID, 1); } if (!Attack) { Vector3D toTarget = TargetPosition - Program.Me.WorldMatrix.Translation; if (toTarget.LengthSquared() > 100) { LeadTask.Destination.Position = TargetPosition; } else { LeadTask.Destination.Position = Vector3D.Zero; } LeadTask.Destination.Velocity = Vector3D.Zero; } if (Mode == 1) { //TODO: Add support for disabling dampeners in this mode - let pilot have full control aside from aiming LeadTask.Destination.Position = controller.GetPosition(); LeadTask.Destination.Velocity = Vector3D.Zero; if (shootIntel == null) { LeadTask.Destination.Direction = Vector3D.Zero; LeadTask.Destination.DirectionUp = Vector3D.Zero; } } LastLinearVelocity = linearVelocity; if (LeadTask.Status == TaskStatus.Incomplete) { LeadTask.Do(IntelItems, canonicalTime, profiler); } }
public void SelectTarget(List <EnemyShipIntel> targets, TimeSpan timestamp) { // Auto reset targetAzimuth = restAzimuth; targetElevation = restElevation; if (Elevation == null || Azimuth == null) { return; } var reference = WeaponGroup.Reference; if (!WeaponGroup.Active) { return; } if (!active) { return; } var myVel = Host.IntelProvider.Controller.GetShipVelocities().LinearVelocity; var canonicalTime = Host.IntelProvider.CanonicalTimeDiff + timestamp; foreach (var target in targets) { var targetVel = target.GetVelocity(); var targetPos = target.GetPositionFromCanonicalTime(canonicalTime); // Get attack position var relativeAttackPoint = AttackHelpers.GetAttackPoint(targetVel - myVel, targetPos - (reference.WorldMatrix.Translation), projectileSpeed); var relativeAttackDirection = Vector3D.Normalize(relativeAttackPoint); // Check range if (relativeAttackPoint.Length() > range) { continue; } // Calculate azimuth angle var azimuthVector = relativeAttackDirection - VectorHelpers.VectorProjection(relativeAttackDirection, Azimuth.WorldMatrix.Up); var azimuthAngle = VectorHelpers.VectorAngleBetween(azimuthVector, Azimuth.WorldMatrix.Backward) * Math.Sign(azimuthVector.Dot(Azimuth.WorldMatrix.Left)); //statusBuilder.AppendLine("AZM: " + (azimuthAngle * 180 / Math.PI).ToString()); // Check if azimuth is OK if (azimuthAngle > AzimuthMax || azimuthAngle < AzimuthMin) { continue; } // Calculate elevation angle var elevationAngle = VectorHelpers.VectorAngleBetween(azimuthVector, relativeAttackDirection) * Math.Sign(relativeAttackDirection.Dot(Azimuth.WorldMatrix.Up)); if (elevationAngle > ElevationMax || elevationAngle < ElevationMin) { continue; } //statusBuilder.AppendLine("ELV: " + (elevationAngle * 180 / Math.PI).ToString()); // Found best target, set target az, el, and return targetAzimuth = azimuthAngle; targetElevation = elevationAngle; return; } }
public void Update(TimeSpan timestamp, UpdateFrequency updateFlags) { if (timestamp == TimeSpan.Zero) { return; } foreach (var bird in Hummingbirds) { if (bird.IsAlive()) { bird.Update(); } else { DeadBirds.Add(bird); } } foreach (var bird in DeadBirds) { DeregisterBird(bird); } runs++; if (runs % 20 == 0) { var intelItems = IntelProvider.GetFleetIntelligences(timestamp); // Get the top targets TopEnemies.Clear(); EnemyToScore.Clear(); foreach (var intelItem in intelItems) { if (intelItem.Key.Item1 == IntelItemType.Enemy) { var esi = (EnemyShipIntel)intelItem.Value; var dist = (esi.GetPositionFromCanonicalTime(timestamp + IntelProvider.CanonicalTimeDiff) - Context.Reference.WorldMatrix.Translation).Length(); if (dist > MaxEngagementDist) { continue; } var priority = IntelProvider.GetPriority(esi.ID); var size = esi.Radius; if (size < MinEngagementSize && priority < 3) { continue; } if (priority < 2) { continue; } int score = (int)(priority * 10000 + size); EnemyToScore[esi] = score; for (int i = 0; i <= TopEnemies.Count; i++) { if (i == TopEnemies.Count || score > EnemyToScore[TopEnemies[i]]) { TopEnemies.Insert(i, esi); break; } } } } // Determine how many birds should be assigned to each enemy EnemyToNumBirds.Clear(); int totalNeededBirds = 0; for (int i = 0; i < TopEnemies.Count && i < 4; i++) { EnemyToNumBirds[TopEnemies[i]] = EnemyCountToNumBirdsPerEnemy[TopEnemies.Count][i]; EnemyToAssignedBirds[TopEnemies[i]] = 0; totalNeededBirds += EnemyToNumBirds[TopEnemies[i]]; } // Remove excess birds from enemies foreach (var bird in Hummingbirds) { var birdTargetID = BirdToEnemy[bird]; if (birdTargetID == 0) { continue; } if (!bird.IsCombatCapable()) { BirdToEnemy[bird] = 0; continue; } var birdTargetKey = MyTuple.Create(IntelItemType.Enemy, birdTargetID); if (!intelItems.ContainsKey(birdTargetKey)) { BirdToEnemy[bird] = 0; continue; } var birdTarget = (EnemyShipIntel)intelItems[birdTargetKey]; if (!EnemyToNumBirds.ContainsKey(birdTarget) || EnemyToNumBirds[birdTarget] == 0) { BirdToEnemy[bird] = 0; continue; } EnemyToNumBirds[birdTarget]--; totalNeededBirds--; } // Assign birds to enemies foreach (var bird in Hummingbirds) { if (totalNeededBirds == 0) { break; } // Bird can't fight, keep looking if (!bird.IsCombatCapable()) { continue; } // Bird already has target, keep looking if (BirdToEnemy[bird] != 0) { continue; } EnemyShipIntel targetEnemy = null; foreach (var enemy in EnemyToNumBirds.Keys) { if (EnemyToNumBirds[enemy] > 0) { targetEnemy = enemy; break; } } BirdToEnemy[bird] = targetEnemy.ID; EnemyToNumBirds[targetEnemy]--; totalNeededBirds--; } NeedsMoreBirds = totalNeededBirds > 0; int birdIndex; // ASSUME birds are not far enough from main controller that gravity direction matters too much var gravDir = Controller.GetTotalGravity(); gravDir.Normalize(); // For each enemy, assign bird target and destination foreach (var enemy in TopEnemies) { birdIndex = 0; foreach (var bird in Hummingbirds) { if (BirdToEnemy[bird] != enemy.ID) { continue; } if (bird.Gats.Count == 0) { continue; } var birdAltitudeTheta = Math.PI * ((runs / (BirdSineConstantSeconds * 30) % 2) - 1); var birdSwayTheta = Math.PI * ((runs / (BirdPendulumConstantSeconds * 30) % 2) - 1); var targetPos = enemy.GetPositionFromCanonicalTime(timestamp + IntelProvider.CanonicalTimeDiff); bird.SetTarget(targetPos, enemy.GetVelocity() - gravDir * (float)TrigHelpers.FastCos(birdAltitudeTheta) * 2); var targetToBase = bird.Base.WorldMatrix.Translation - targetPos; targetToBase -= VectorHelpers.VectorProjection(targetToBase, gravDir); var targetToBaseDist = targetToBase.Length(); targetToBase.Normalize(); var engageLocationLocus = targetToBase * Math.Min(600, targetToBaseDist + 400) + targetPos; var engageLocationSwayDir = targetToBase.Cross(gravDir); var engageLocationSwayDist = (TrigHelpers.FastCos(birdSwayTheta) - EnemyToAssignedBirds[enemy] * 0.5 + birdIndex + 0.5) * 100; bird.SetDest(engageLocationLocus + engageLocationSwayDist * engageLocationSwayDir); var birdDir = bird.Controller.WorldMatrix.Translation - Controller.WorldMatrix.Translation; birdDir -= VectorHelpers.VectorProjection(birdDir, gravDir);; var birdDist = birdDir.Length(); bird.Drive.DesiredAltitude = birdDist < 100 ? Hummingbird.RecommendedServiceCeiling : (float)TrigHelpers.FastSin(birdAltitudeTheta + Math.PI * 0.5) * (Hummingbird.RecommendedServiceCeiling - Hummingbird.RecommendedServiceFloor) + Hummingbird.RecommendedServiceFloor; birdIndex++; } } // Assign orbit task for unassigned birds int numReserveBirds = 0; foreach (var bird in Hummingbirds) { if (BirdToEnemy[bird] == 0 && bird.IsCombatCapable()) { numReserveBirds++; } } birdIndex = 0; var randomPoint = new Vector3D(190, 2862, 809); randomPoint -= VectorHelpers.VectorProjection(randomPoint, gravDir); randomPoint.Normalize(); var randomPointCross = randomPoint.Cross(gravDir); foreach (var bird in Hummingbirds) { if (BirdToEnemy[bird] != 0) { continue; } bird.SetTarget(Vector3D.Zero, Vector3D.Zero); bird.Drive.DesiredAltitude = 30; if (bird.IsCombatCapable() && !bird.IsRetiring) { var birdOrbitTheta = Math.PI * (((2 * birdIndex / (float)numReserveBirds) + runs / (BirdOrbitSeconds * 30)) % 2 - 1); var birdOrbitDest = Controller.WorldMatrix.Translation + TrigHelpers.FastCos(birdOrbitTheta) * randomPoint * BirdOrbitDist + TrigHelpers.FastSin(birdOrbitTheta) * randomPointCross * BirdOrbitDist; bird.SetDest(birdOrbitDest); birdIndex++; } else if (!bird.IsRetiring) { RetireBird(bird); } else if (bird.IsRetiring) { if (!bird.IsLanding) { var birdDir = bird.Controller.WorldMatrix.Translation - bird.Destination; birdDir -= VectorHelpers.VectorProjection(birdDir, gravDir); var birdDist = birdDir.Length(); birdDir.Normalize(); if (birdDist < 50) { bird.SetDest(Vector3D.Zero); bird.Drive.Flush(); foreach (var engine in bird.Drive.HoverEngines) { engine.AltitudeMin = 0; } bird.IsLanding = true; } } else { double altitude; bird.Controller.TryGetPlanetElevation(MyPlanetElevation.Surface, out altitude); if (altitude < 6) { foreach (var engine in bird.Drive.HoverEngines) { engine.Block.Enabled = false; DeadBirds.Add(bird); } } } } } } foreach (var cradle in Cradles) { if (cradle == null) { continue; } cradle.Update(); } if (runs % 60 == 0) { BirdReleaseTimeout--; for (int i = 0; i < Cradles.Count(); i++) { if (Cradles[i] == null) { continue; } if (Cradles[i].Hummingbird == null) { Cradles[i].CheckHummingbird(); } else if (NeedsMoreBirds && BirdReleaseTimeout <= 0) { Hummingbird bird = Cradles[i].Release(); bird.Base = Context.Reference; RegisterBird(bird); BirdReleaseTimeout = 5; } } } DeadBirds.Clear(); }
public void Update() { LifeTimeTicks++; // Startup Subroutine if (LifeTimeTicks == 1) { foreach (var engine in Drive.HoverEngines) { engine.AltitudeMin = 1; engine.PushOnly = true; } } if (LifeTimeTicks == 60) { foreach (var engine in Drive.HoverEngines) { engine.AltitudeMin = 2; } } if (LifeTimeTicks == 120) { foreach (var engine in Drive.HoverEngines) { engine.AltitudeMin = 7; } } if (LifeTimeTicks % kRunEveryXUpdates == 0) { Vector3D PlanetDir = PlanetPos - Controller.WorldMatrix.Translation; PlanetDir.Normalize(); // Orient Self Drive.Turn(Gats.Count > 0 ? Gats[0].WorldMatrix : Controller.WorldMatrix, target); // Aim Turret if (TurretRotor != null) { if (target != Vector3D.Zero && Drive.GravAngle < Math.PI * 0.1) { var TurretAngle = TrigHelpers.FastAsin(Gats[0].WorldMatrix.Forward.Dot(PlanetDir)); Vector3D TargetDir = target - Gats[0].WorldMatrix.Translation; var targetDist = TargetDir.Length(); TargetDir.Normalize(); var TargetAngle = TrigHelpers.FastAsin(TargetDir.Dot(PlanetDir)); var angleDiff = TargetAngle - TurretAngle; if (VectorHelpers.VectorAngleBetween(Gats[0].WorldMatrix.Forward, TargetDir) < 0.05 && targetDist < 800) { Fire(); } TurretRotor.TargetVelocityRPM = (float)TurretPID.Control(angleDiff); } else { TurretPID.Reset(); TurretRotor.TargetVelocityRPM = 0; } } // Check your fire fireTicks--; if (fireTicks == -1) { foreach (var gat in Gats) { TerminalPropertiesHelper.SetValue(gat, "Shoot", false); } } // Check Movement if (Destination != Vector3D.Zero) { Drive.Drive(Destination); if (Drive.Arrived) { Destination = Vector3D.Zero; Drive.Flush(); } } } }
public void Update(TimeSpan timestamp, UpdateFrequency updateFlags) { if (runs % 240 == 0) { statusBuilder.Clear(); foreach (var tube in LandpedoTubes) { tube.CheckLandpedo(); // statusBuilder.AppendLine(tube.GetStatus()); } } if (runs % 10 == 0) { statusBuilder.Clear(); var targets = IntelProvider.GetFleetIntelligences(timestamp); var canonicalTime = IntelProvider.CanonicalTimeDiff + timestamp; DeadLandpedos.Clear(); foreach (var landpedo in Landpedos) { statusBuilder.AppendLine("LANDPEDO==="); if (landpedo.Fired) { landpedo.DeadCount--; } if (!landpedo.IsOK()) { DeadLandpedos.Add(landpedo); continue; } landpedo.runs++; var landpedoPosition = landpedo.Controller.WorldMatrix.Translation; var landpedoVelocity = landpedo.Controller.GetShipVelocities().LinearVelocity; var gravDir = landpedo.Controller.GetNaturalGravity(); var gravStr = gravDir.Normalize(); var planarVelocity = landpedoVelocity - VectorHelpers.VectorProjection(landpedoVelocity, gravDir); if (landpedo.TargetID != -1) { var key = MyTuple.Create(IntelItemType.Enemy, landpedo.TargetID); if (targets.ContainsKey(key)) { var target = targets[key]; landpedo.TargetPosition = target.GetPositionFromCanonicalTime(canonicalTime); landpedo.TargetVelocity = target.GetVelocity(); } } statusBuilder.AppendLine(landpedo.TargetPosition.ToString()); if (landpedo.TargetPosition != Vector3D.Zero) { var relativeVector = landpedo.TargetPosition - landpedoPosition; var planarVector = relativeVector - VectorHelpers.VectorProjection(relativeVector, gravDir); var targetPoint = AttackHelpers.GetAttackPoint(landpedo.TargetVelocity, landpedo.TargetPosition - landpedoPosition, landpedo.lastSpeed); if (targetPoint == Vector3D.Zero) { targetPoint = landpedo.TargetPosition - landpedoPosition; } var targetPointDist = targetPoint.Length(); var planarDist = planarVector.Length(); var velocity = landpedo.Controller.GetShipVelocities().LinearVelocity; var verticalVelocity = VectorHelpers.VectorProjection(velocity, gravDir); var planarLeft = landpedo.Controller.WorldMatrix.Left - VectorHelpers.VectorProjection(landpedo.Controller.WorldMatrix.Left, gravDir); planarLeft.Normalize(); var planarForward = landpedo.Controller.WorldMatrix.Forward - VectorHelpers.VectorProjection(landpedo.Controller.WorldMatrix.Forward, gravDir); planarForward.Normalize(); double altitude; landpedo.Controller.TryGetPlanetElevation(MyPlanetElevation.Surface, out altitude); if (targetPointDist > 350 || landpedo.Launchers.Count == 0) { landpedo.desiredAltitude = planarVector.Length() > 200 ? 10 : 50; planarVector.Normalize(); MatrixD orientationMatrix = MatrixD.Identity; orientationMatrix.Translation = landpedo.Controller.WorldMatrix.Translation; orientationMatrix.Up = -gravDir; orientationMatrix.Left = planarLeft; orientationMatrix.Forward = planarForward; var spinAngle = VectorHelpers.VectorAngleBetween(planarForward, planarVector) * Math.Sign(-planarLeft.Dot(planarVector)); // var planarVelocity = velocity - verticalVelocity; // var velocityAdjust = planarVelocity - VectorHelpers.VectorProjection(velocity, planarVector); // velocityAdjust.Normalize(); // planarVector -= velocityAdjust; // var MoveIndicator = Vector3D.TransformNormal(planarVector, MatrixD.Transpose(orientationMatrix)); var rangeVector = planarVector; var waypointVector = rangeVector; var distTargetSq = rangeVector.LengthSquared(); var targetPlanarVelocity = landpedo.TargetVelocity - VectorHelpers.VectorProjection(landpedo.TargetVelocity, gravDir); Vector3D velocityVector = targetPlanarVelocity - planarVelocity; var speed = planarVelocity.Length(); Vector3D AccelerationVector; double alignment = planarVelocity.Dot(ref waypointVector); if (alignment > 0) { Vector3D rangeDivSqVector = waypointVector / waypointVector.LengthSquared(); Vector3D compensateVector = velocityVector - (velocityVector.Dot(ref waypointVector) * rangeDivSqVector); Vector3D targetANVector; var targetAccel = (landpedo.lastTargetVelocity - targetPlanarVelocity) * 0.16667; targetANVector = targetAccel - (targetAccel.Dot(ref waypointVector) * rangeDivSqVector); bool accelerating = speed > landpedo.lastSpeed + 1; if (accelerating) { AccelerationVector = planarVelocity + (10 * 1.5 * (compensateVector + (0.5 * targetANVector))); } else { AccelerationVector = planarVelocity + (10 * (compensateVector + (0.5 * targetANVector))); } } // going backwards or perpendicular else { AccelerationVector = (waypointVector * 0.1) + velocityVector; } landpedo.lastTargetVelocity = landpedo.TargetVelocity; landpedo.lastSpeed = speed; var MoveIndicator = Vector3D.TransformNormal(AccelerationVector, MatrixD.Transpose(orientationMatrix)); MoveIndicator.Y = 0; MoveIndicator.Normalize(); statusBuilder.AppendLine(MoveIndicator.ToString()); landpedo.Drive.MoveIndicators = MoveIndicator; landpedo.Drive.RotationIndicators = new Vector3(0, spinAngle, 0); landpedo.Drive.Drive(); if (verticalVelocity.Length() > 10 && verticalVelocity.Dot(gravDir) > 0) { landpedo.Drive.maxFlightPitch = 20; landpedo.Drive.maxFlightRoll = 20; } else { landpedo.Drive.maxFlightPitch = 60; landpedo.Drive.maxFlightRoll = 60; } if (targetPointDist < 1000) { landpedo.Drive.maxFlightPitch = 20; } } else if (landpedo.TargetID != -1) { var key = MyTuple.Create(IntelItemType.Enemy, landpedo.TargetID); if (!targets.ContainsKey(key)) { return; } var target = targets[key]; var posDiff = target.GetPositionFromCanonicalTime(canonicalTime) - landpedoPosition; var avgVel = 400 * Math.Sqrt(posDiff.Length() / 400); var relativeAttackPoint = AttackHelpers.GetAttackPoint(landpedo.TargetVelocity - velocity, posDiff, avgVel); targetPointDist = relativeAttackPoint.Length(); double yawAngle, pitchAngle; TrigHelpers.GetRotationAngles(relativeAttackPoint, landpedo.Controller.WorldMatrix.Forward, landpedo.Controller.WorldMatrix.Left, landpedo.Controller.WorldMatrix.Up, out yawAngle, out pitchAngle); TrigHelpers.ApplyGyroOverride(landpedo.PitchPID.Control(pitchAngle), landpedo.YawPID.Control(yawAngle), 0, landpedo.Gyros, landpedo.Controller.WorldMatrix); if ((targetPointDist < 125 || landpedo.minDist < planarDist)) { foreach (var weapon in landpedo.Launchers) { weapon.Enabled = true; } landpedo.Fired = true; } landpedo.minDist = Math.Min(landpedo.minDist, planarDist); } var verticalThrustRatio = TrigHelpers.FastCos(VectorHelpers.VectorAngleBetween(landpedo.Controller.WorldMatrix.Down, gravDir)); var desiredThrust = ((landpedo.desiredAltitude - altitude) + verticalVelocity.LengthSquared() * 0.1 + gravStr) * landpedo.Controller.CalculateShipMass().PhysicalMass / verticalThrustRatio; var individualThrust = desiredThrust / landpedo.Thrusters.Count(); if (individualThrust <= 0) { individualThrust = 0.001; } foreach (var thruster in landpedo.Thrusters) { thruster.Enabled = ((verticalVelocity.Length() > 20 && verticalVelocity.Dot(gravDir) < 0) || ((verticalVelocity.Length() > 2 && verticalVelocity.Dot(gravDir) < 0) && targetPointDist < 1000)) ? false : true; thruster.ThrustOverride = (float)individualThrust; } statusBuilder.AppendLine($"{landpedo.Drive.thrustController.CalculateThrustToHover()}"); statusBuilder.AppendLine($"{landpedo.Drive.thrustController.upThrusters.Count} : {landpedo.Drive.thrustController.downThrusters.Count}"); } } foreach (var landpedo in DeadLandpedos) { Landpedos.Remove(landpedo); } } runs++; }