private void CalculateExtendedParameters() { if (IsStationary) { return; } // Calculate extended parameters. // http://en.wikipedia.org/wiki/Standard_gravitational_parameter#Two_bodies_orbiting_each_other GravitationalParameter = GameConstants.Science.GravitationalConstant * (_parentMass + _myMass) / (1000 * 1000 * 1000); // Normalize GravitationalParameter from m^3/s^2 to km^3/s^2 GravitationalParameterAU = GameConstants.Science.GravitationalConstant * (_parentMass + _myMass) / 3.347928976e33; // (149597870700 * 149597870700 * 149597870700); // http://en.wikipedia.org/wiki/Orbital_period#Two_bodies_orbiting_each_other double orbitalPeriod = 2 * Math.PI * Math.Sqrt(Math.Pow(Distance.AuToKm(SemiMajorAxis), 3) / (GravitationalParameter)); if (orbitalPeriod * 10000000 > long.MaxValue) { OrbitalPeriod = TimeSpan.MaxValue; } else { OrbitalPeriod = TimeSpan.FromSeconds(orbitalPeriod); } // http://en.wikipedia.org/wiki/Mean_motion MeanMotion = Math.Sqrt(GravitationalParameter / Math.Pow(Distance.AuToKm(SemiMajorAxis), 3)); // Calculated in radians. MeanMotion = Angle.ToDegrees(MeanMotion); // Stored in degrees. Apoapsis = (1 + Eccentricity) * SemiMajorAxis; Periapsis = (1 - Eccentricity) * SemiMajorAxis; }
private void CalculateExtendedParameters() { if (IsStationary) { return; } // Calculate extended parameters. // http://en.wikipedia.org/wiki/Standard_gravitational_parameter#Two_bodies_orbiting_each_other GravitationalParameter_Km3S2 = GMath.GravitationalParameter_Km3s2(_parentMass + _myMass); // Normalize GravitationalParameter from m^3/s^2 to km^3/s^2 GravitationalParameterAU = GMath.GrabitiationalParameter_Au3s2(_parentMass + _myMass); // (149597870700 * 149597870700 * 149597870700); GravitationalParameter_m3S2 = GMath.StandardGravitationalParameter(_parentMass + _myMass); double orbitalPeriod = 2 * Math.PI * Math.Sqrt(Math.Pow(Distance.AuToKm(SemiMajorAxis_AU), 3) / (GravitationalParameter_Km3S2)); if (orbitalPeriod * 10000000 > long.MaxValue) { OrbitalPeriod = TimeSpan.MaxValue; } else { OrbitalPeriod = TimeSpan.FromSeconds(orbitalPeriod); } // http://en.wikipedia.org/wiki/Mean_motion MeanMotion_DegreesSec = Math.Sqrt(GravitationalParameter_Km3S2 / Math.Pow(Distance.AuToKm(SemiMajorAxis_AU), 3)); // Calculated in radians. MeanMotion_DegreesSec = Angle.ToDegrees(MeanMotion_DegreesSec); // Stored in degrees. Apoapsis_AU = (1 + Eccentricity) * SemiMajorAxis_AU; Periapsis_AU = (1 - Eccentricity) * SemiMajorAxis_AU; SOI_m = OrbitMath.GetSOI(SemiMajorAxis, _myMass, _parentMass); }
internal static void FirstRun(Entity entity) { CargoTransferDB datablob = entity.GetDataBlob <CargoTransferDB>(); double?dv; if (entity.HasDataBlob <OrbitDB>() && datablob.CargoToEntity.HasDataBlob <OrbitDB>()) { dv = CalcDVDifferenceKmPerSecond(entity.GetDataBlob <OrbitDB>(), datablob.CargoToEntity.GetDataBlob <OrbitDB>()); } else { OrbitDB orbitDB; if (entity.HasDataBlob <ColonyInfoDB>()) { orbitDB = entity.GetDataBlob <ColonyInfoDB>().PlanetEntity.GetDataBlob <OrbitDB>(); } else//if (datablob.CargoToEntity.HasDataBlob<ColonyInfoDB>()) { orbitDB = datablob.CargoToEntity.GetDataBlob <ColonyInfoDB>().PlanetEntity.GetDataBlob <OrbitDB>(); } dv = Distance.AuToKm(OrbitMath.MeanOrbitalVelocityInAU(orbitDB)); } if (dv != null) { datablob.TransferRateInKG = CalcTransferRate((double)dv, datablob.CargoFromDB, datablob.CargoToDB); } }
/// <summary> /// Calculates the DVD ifference. /// </summary> /// <returns>The delaV Difference in Km/s, null if not in imediate orbit</returns> public static double?CalcDVDifferenceKmPerSecond(OrbitDB orbitDBFrom, OrbitDB orbitDBTo) { Entity toEntity = orbitDBTo.OwningEntity; double?dv = null; if (orbitDBFrom.Parent == toEntity) //Cargo going up the gravity well { dv = OrbitMath.MeanOrbitalVelocityInAU(orbitDBFrom); } else if (orbitDBFrom.Children.Contains(toEntity)) //Cargo going down the gravity well { dv = OrbitMath.MeanOrbitalVelocityInAU(orbitDBTo); } else if (orbitDBFrom.Parent == toEntity.GetDataBlob <OrbitDB>().Parent) //cargo going between objects orbiting the same body { dv = Math.Abs(OrbitMath.MeanOrbitalVelocityInAU(orbitDBFrom) - OrbitMath.MeanOrbitalVelocityInAU(orbitDBTo)); } if (dv == null) { return(dv); } else { return(Distance.AuToKm((double)dv)); } }
/// <summary> /// Calculates the cartesian coordinates (relative to it's parent) of an orbit for a given angle. /// </summary> /// <param name="orbit">OrbitDB to calculate position from.</param> /// <param name="trueAnomaly">Angle in Radians.</param> public static Vector4 GetPosition(OrbitDB orbit, double trueAnomaly) { if (orbit.IsStationary) { return(new Vector4(0, 0, 0, 0)); } // http://en.wikipedia.org/wiki/True_anomaly#Radius_from_true_anomaly double radius = Distance.AuToKm(orbit.SemiMajorAxis) * (1 - orbit.Eccentricity * orbit.Eccentricity) / (1 + orbit.Eccentricity * Math.Cos(trueAnomaly)); // Adjust TrueAnomaly by the Argument of Periapsis (converted to radians) trueAnomaly += Angle.ToRadians(orbit.ArgumentOfPeriapsis); double inclination = Angle.ToRadians(orbit.Inclination); // Convert KM to AU radius = Distance.KmToAU(radius); //https://downloads.rene-schwarz.com/download/M001-Keplerian_Orbit_Elements_to_Cartesian_State_Vectors.pdf double lofAN = Angle.ToRadians(orbit.LongitudeOfAscendingNode); double aofP = Angle.ToRadians(orbit.ArgumentOfPeriapsis); double tA = trueAnomaly; double incl = inclination; double x = Math.Cos(lofAN) * Math.Cos(aofP + tA) - Math.Sin(lofAN) * Math.Sin(aofP + tA) * Math.Cos(incl); double y = Math.Sin(lofAN) * Math.Cos(aofP + tA) + Math.Cos(lofAN) * Math.Sin(aofP + tA) * Math.Cos(incl); double z = Math.Sin(incl) * Math.Sin(aofP + tA); return(new Vector4(x, y, z, 0) * radius); }
/// <summary> /// This intercept only works if time to intercept is less than the orbital period. /// </summary> /// <returns>The ntercept.</returns> /// <param name="mover">Mover.</param> /// <param name="targetOrbit">Target orbit.</param> /// <param name="atDateTime">At date time.</param> public static (Vector3, TimeSpan) FTLIntercept(Entity mover, OrbitDB targetOrbit, DateTime atDateTime) { //OrbitDB targetOrbit = target.GetDataBlob<OrbitDB>(); //PositionDB targetPosition = target.GetDataBlob<PositionDB>(); //PositionDB moverPosition = mover.GetDataBlob<PositionDB>(); OrbitDB moverOrbit = mover.GetDataBlob <OrbitDB>(); Vector3 moverPosInKM = Distance.AuToKm(OrbitProcessor.GetAbsolutePosition_AU(moverOrbit, atDateTime)); PropulsionAbilityDB moverPropulsion = mover.GetDataBlob <PropulsionAbilityDB>(); Vector3 targetPosInKM = Distance.AuToKm((OrbitProcessor.GetAbsolutePosition_AU(targetOrbit, atDateTime))); int speed = 25000;//moverPropulsion.MaximumSpeed * 100; //299792458; (Vector3, TimeSpan)intercept = (new Vector3(), TimeSpan.Zero); TimeSpan eti = new TimeSpan(); TimeSpan eti_prev = new TimeSpan(); DateTime edi = atDateTime; DateTime edi_prev = atDateTime; Vector3 predictedPosKM = Distance.AuToKm(OrbitProcessor.GetAbsolutePosition_AU(targetOrbit, edi_prev)); double distance = (predictedPosKM - moverPosInKM).Length(); eti = TimeSpan.FromSeconds((distance * 1000) / speed); int steps = 0; if (eti < targetOrbit.OrbitalPeriod) { double timeDifference = double.MaxValue; double distanceDifference = timeDifference * speed; while (distanceDifference >= 1000) { eti_prev = eti; edi_prev = edi; predictedPosKM = Distance.AuToKm(OrbitProcessor.GetAbsolutePosition_AU(targetOrbit, edi_prev)); distance = (predictedPosKM - moverPosInKM).Length(); eti = TimeSpan.FromSeconds((distance * 1000) / speed); edi = atDateTime + eti; timeDifference = Math.Abs(eti.TotalSeconds - eti_prev.TotalSeconds); distanceDifference = timeDifference * speed; steps++; } } return(intercept); }
/// <summary> /// Creates on Orbit at current location from a given velocity /// </summary> /// <returns>The Orbit Does not attach the OrbitDB to the entity!</returns> /// <param name="parent">Parent.</param> /// <param name="entity">Entity.</param> /// <param name="velocityAU">Velocity.</param> public static OrbitDB FromVector(Entity parent, Entity entity, Vector3 velocityAU, DateTime atDateTime) { var parentMass = parent.GetDataBlob <MassVolumeDB>().Mass; var myMass = entity.GetDataBlob <MassVolumeDB>().Mass; var epoch1 = parent.Manager.ManagerSubpulses.StarSysDateTime; //getting epoch from here is incorrect as the local datetime doesn't change till after the subpulse. var parentPos = OrbitProcessor.GetAbsolutePosition_AU(parent.GetDataBlob <OrbitDB>(), atDateTime); //need to use the parent position at the epoch var posdb = entity.GetDataBlob <PositionDB>(); posdb.SetParent(parent); var ralitivePos = posdb.RelativePosition_AU;//entity.GetDataBlob<PositionDB>().AbsolutePosition_AU - parentPos; if (ralitivePos.Length() > OrbitProcessor.GetSOI(parent)) { throw new Exception("Entity not in target SOI"); } var sgp = GameConstants.Science.GravitationalConstant * (myMass + parentMass) / 3.347928976e33; var ke = OrbitMath.KeplerFromPositionAndVelocity(sgp, ralitivePos, velocityAU, atDateTime); var epoch = atDateTime;// - TimeSpan.FromSeconds(ke.Epoch); //ke.Epoch is seconds from periapsis. OrbitDB orbit = new OrbitDB(parent, parentMass, myMass, Math.Abs(ke.SemiMajorAxis), ke.Eccentricity, Angle.ToDegrees(ke.Inclination), Angle.ToDegrees(ke.LoAN), Angle.ToDegrees(ke.AoP), Angle.ToDegrees(ke.MeanAnomalyAtEpoch), epoch); var pos = OrbitProcessor.GetPosition_AU(orbit, atDateTime); var d = Distance.AuToKm(pos - ralitivePos).Length(); if (d > 1) { var e = new Event(atDateTime, "Positional difference of " + d + "Km when creating orbit from velocity"); e.Entity = entity; e.SystemGuid = entity.Manager.ManagerGuid; e.EventType = EventType.Opps; //e.Faction = entity.FactionOwner; StaticRefLib.EventLog.AddEvent(e); //other info: var keta = Angle.ToDegrees(ke.TrueAnomalyAtEpoch); var obta = Angle.ToDegrees(OrbitProcessor.GetTrueAnomaly(orbit, atDateTime)); var tadif = Angle.ToDegrees(Angle.DifferenceBetweenRadians(keta, obta)); var pos1 = OrbitProcessor.GetPosition_AU(orbit, atDateTime); var pos2 = OrbitProcessor.GetPosition_AU(orbit, ke.TrueAnomalyAtEpoch); var d2 = Distance.AuToKm(pos1 - pos2).Length(); } return(orbit); }
internal override void ActionCommand(Game game) { if (!IsRunning) { (Vector3 pos, DateTime eti)targetIntercept = InterceptCalcs.GetInterceptPosition(_entityCommanding, _targetEntity.GetDataBlob <OrbitDB>(), TransitStartDateTime, TargetOffsetPosition_AU); OrbitDB orbitDB = _entityCommanding.GetDataBlob <OrbitDB>(); Vector3 currentPos = OrbitProcessor.GetAbsolutePosition_AU(orbitDB, TransitStartDateTime); var ralPos = OrbitProcessor.GetPosition_AU(orbitDB, TransitStartDateTime); var masses = _entityCommanding.GetDataBlob <MassVolumeDB>().Mass + orbitDB.Parent.GetDataBlob <MassVolumeDB>().Mass; var sgp = GameConstants.Science.GravitationalConstant * masses / 3.347928976e33; //Vector4 currentVec = OrbitProcessor.PreciseOrbitalVector(sgp, ralPos, orbitDB.SemiMajorAxis); Vector2 currentVec = OrbitProcessor.GetOrbitalVector(orbitDB, TransitStartDateTime); _db = new TranslateMoveDB(targetIntercept.pos); _db.TranslateRalitiveExit_AU = TargetOffsetPosition_AU; _db.EntryDateTime = TransitStartDateTime; _db.PredictedExitTime = targetIntercept.eti; _db.TranslateEntryPoint_AU = currentPos; _db.SavedNewtonionVector_AU = currentVec; _db.ExpendDeltaV_AU = ExpendDeltaV; if (_targetEntity.HasDataBlob <SensorInfoDB>()) { _db.TargetEntity = _targetEntity.GetDataBlob <SensorInfoDB>().DetectedEntity; } else { _db.TargetEntity = _targetEntity; } if (EntityCommanding.HasDataBlob <OrbitDB>()) { EntityCommanding.RemoveDataBlob <OrbitDB>(); } EntityCommanding.SetDataBlob(_db); TranslateMoveProcessor.StartNonNewtTranslation(EntityCommanding); IsRunning = true; var distance = (currentPos - targetIntercept.Item1).Length(); var distancekm = Distance.AuToKm(distance); var time = targetIntercept.Item2 - TransitStartDateTime; double spd = _entityCommanding.GetDataBlob <PropulsionAbilityDB>().MaximumSpeed_MS; spd = Distance.MToAU(spd); var distb = spd * time.TotalSeconds; var distbKM = Distance.AuToKm(distb); var dif = distancekm - distbKM; //Assert.AreEqual(distancekm, distbKM); } }
/// <summary> /// Creates orbit here using the current distance between the two entites as aphelion(furthest distance) and a given semiMajorAxis /// *NOTE BUG* this only returns a correct orbit DB if the position is y=0 and is +x (ie the position is in the reference direction) /// </summary> /// <returns>An OrbitDB. Does Not set DB to Entity.</returns> /// <param name="shipEntity">Ship entity.</param> /// <param name="parentEntity">The Entity to orbit</param> /// <param name="semiMajorAxsis">Largest Radius</param> public static OrbitDB CreateOrbitHereWithSemiMajAxis(Entity shipEntity, Entity parentEntity, double semiMajAxsisKM, DateTime time) { PositionDB parentPosition = parentEntity.GetDataBlob <PositionDB>(); PositionDB myPosition = shipEntity.GetDataBlob <PositionDB>(); double parentMass = parentEntity.GetDataBlob <MassVolumeDB>().Mass; double myMass = shipEntity.GetDataBlob <MassVolumeDB>().Mass; double aphelionAU = PositionDB.GetDistanceBetween(parentPosition, myPosition); double semiMajAxisAU = semiMajAxsisKM / GameConstants.Units.KmPerAu; double linierEcentricity = aphelionAU - semiMajAxisAU; double semiMinorAxsis = Math.Sqrt(Math.Pow(semiMajAxisAU, 2) - Math.Pow(linierEcentricity, 2)); double ecentricity = linierEcentricity / semiMajAxisAU; Vector3 ralitivePos = myPosition.RelativePosition_AU; double angle = Math.Atan2(ralitivePos.Y, ralitivePos.X); var theta = Angle.ToDegrees(angle); OrbitDB newOrbit = OrbitDB.FromAsteroidFormat(parentEntity, parentMass, myMass, semiMajAxisAU, ecentricity, 0, 0, angle, angle, time); var pos = OrbitProcessor.GetPosition_AU(newOrbit, time); var pos2 = Distance.AuToKm(pos); return(newOrbit); }
/// <summary> /// Calculates volume in Km^3 from a radius in Au. /// </summary> /// <param name="radius">Radius in AU</param> /// <returns>Volume_km3 in Km^3</returns> public static double CalculateVolume_Km3(double radius_au) { return((4.0 / 3.0) * Math.PI * Math.Pow(Distance.AuToKm(radius_au), 3)); }
public static Entity CreateShip(Entity classEntity, EntityManager systemEntityManager, Entity ownerFaction, Entity parent, StarSystem starsys, string shipName = null) { Vector3 position = parent.GetDataBlob <PositionDB>().AbsolutePosition_AU; var distanceFromParent = parent.GetDataBlob <MassVolumeDB>().Radius * 2; position.X += distanceFromParent; Entity ship = CreateShip(classEntity, systemEntityManager, ownerFaction, position, starsys, shipName); ship.GetDataBlob <PositionDB>().SetParent(parent); var orbitDB = ShipMovementProcessor.CreateOrbitHereWithSemiMajAxis(ship, parent, Distance.AuToKm(distanceFromParent), systemEntityManager.ManagerSubpulses.StarSysDateTime); ship.SetDataBlob(orbitDB); return(ship); }
/// <summary> /// This was designed so that fast moving objects will get interpolated a lot more than slow moving objects /// so fast moving objects shouldn't loose positional acuracy when close to a planet, /// and slow moving objects won't have processor time wasted on them by calulcating too often. /// However this seems to be unstable and looses energy, unsure why. currently set it to just itterate/interpolate every second. /// so currently will be using more time to get through this than neccisary. /// </summary> /// <param name="entity">Entity.</param> /// <param name="deltaSeconds">Delta seconds.</param> public static void NewtonMove(Entity entity, int deltaSeconds) { NewtonMoveDB newtonMoveDB = entity.GetDataBlob <NewtonMoveDB>(); PositionDB positionDB = entity.GetDataBlob <PositionDB>(); double Mass_Kg = entity.GetDataBlob <MassVolumeDB>().Mass; double ParentMass_kg = newtonMoveDB.ParentMass; var manager = entity.Manager; DateTime dateTimeFrom = newtonMoveDB.LastProcessDateTime; DateTime dateTimeNow = manager.ManagerSubpulses.StarSysDateTime; DateTime dateTimeFuture = dateTimeNow + TimeSpan.FromSeconds(deltaSeconds); double deltaT = (dateTimeFuture - dateTimeFrom).TotalSeconds; double secondsToItterate = deltaT; while (secondsToItterate > 0) { double speed_kms = newtonMoveDB.CurrentVector_kms.Length(); //double timeStep = Math.Max(secondsToItterate / speed_kms, 1); //timeStep = Math.Min(timeStep, secondsToItterate); double timeStep = 1;//because the above seems unstable and looses energy. double distanceToParent_m = Distance.AuToMt(positionDB.GetDistanceTo(newtonMoveDB.SOIParent.GetDataBlob <PositionDB>())); distanceToParent_m = Math.Max(distanceToParent_m, 0.1); //don't let the distance be 0 (once collision is in this will likely never happen anyway) double gravForce = GameConstants.Science.GravitationalConstant * (Mass_Kg * ParentMass_kg / Math.Pow(distanceToParent_m, 2)); Vector3 gravForceVector = gravForce * -Vector3.Normalise(positionDB.RelativePosition_AU); double distance = Distance.AuToKm(positionDB.RelativePosition_AU).Length(); Vector3 totalForce = gravForceVector + newtonMoveDB.ThrustVector; Vector3 acceleration_mps = totalForce / Mass_Kg; Vector3 newVelocity = (acceleration_mps * timeStep * 0.001) + newtonMoveDB.CurrentVector_kms; newtonMoveDB.CurrentVector_kms = newVelocity; Vector3 deltaPos = (newtonMoveDB.CurrentVector_kms + newVelocity) / 2 * timeStep; //Vector4 deltaPos = newtonMoveDB.CurrentVector_kms * timeStep; positionDB.RelativePosition_AU += Distance.KmToAU(deltaPos); double sOIRadius_AU = OrbitProcessor.GetSOI(newtonMoveDB.SOIParent); if (positionDB.RelativePosition_AU.Length() >= sOIRadius_AU) { Entity newParent; Vector3 parentRalitiveVector; //if our parent is a regular kepler object (normaly this is the case) if (newtonMoveDB.SOIParent.HasDataBlob <OrbitDB>()) { var orbitDB = newtonMoveDB.SOIParent.GetDataBlob <OrbitDB>(); newParent = orbitDB.Parent; var parentVelocity = OrbitProcessor.InstantaneousOrbitalVelocityVector(orbitDB, entity.Manager.ManagerSubpulses.StarSysDateTime); parentRalitiveVector = Distance.KmToAU(newtonMoveDB.CurrentVector_kms) + parentVelocity; var pvlen = Distance.AuToKm(parentVelocity.Length()); var vlen = newtonMoveDB.CurrentVector_kms.Length(); var rvlen = Distance.AuToKm(parentRalitiveVector.Length()); } else //if (newtonMoveDB.SOIParent.HasDataBlob<NewtonMoveDB>()) { //this will pretty much never happen. newParent = newtonMoveDB.SOIParent.GetDataBlob <NewtonMoveDB>().SOIParent; var parentVelocity = newtonMoveDB.SOIParent.GetDataBlob <NewtonMoveDB>().CurrentVector_kms; parentRalitiveVector = Distance.KmToAU(newtonMoveDB.CurrentVector_kms + parentVelocity); } double newParentMass = newParent.GetDataBlob <MassVolumeDB>().Mass; double sgp = GameConstants.Science.GravitationalConstant * (newParentMass + Mass_Kg) / 3.347928976e33; Vector3 posRalitiveToNewParent = positionDB.AbsolutePosition_AU - newParent.GetDataBlob <PositionDB>().AbsolutePosition_AU; var dateTime = dateTimeNow + TimeSpan.FromSeconds(deltaSeconds - secondsToItterate); var kE = OrbitMath.KeplerFromPositionAndVelocity(sgp, posRalitiveToNewParent, parentRalitiveVector, dateTime); if (kE.Eccentricity < 1) //if we're going to end up in a regular orbit around our new parent { /* * var newOrbit = OrbitDB.FromKeplerElements( * newParent, * newParentMass, * Mass_Kg, * kE, * dateTime); */ var newOrbit = OrbitDB.FromVector(newParent, entity, parentRalitiveVector, dateTime); entity.RemoveDataBlob <NewtonMoveDB>(); entity.SetDataBlob(newOrbit); positionDB.SetParent(newParent); var currentPos = Distance.AuToKm(positionDB.RelativePosition_AU); var newPos = OrbitProcessor.GetPosition_AU(newOrbit, dateTime); var newPosKM = Distance.AuToKm(newPos); positionDB.RelativePosition_AU = newPos; break; } else //else we're in a hyperbolic trajectory around our new parent, so just coninue the newtonion move. { positionDB.SetParent(newParent); newtonMoveDB.ParentMass = newParentMass; newtonMoveDB.SOIParent = newParent; } } secondsToItterate -= timeStep; } newtonMoveDB.LastProcessDateTime = dateTimeFuture; }
// sets the speed of the ship to the maximum speed allowed in the direction of the target. // Returns true if the destination has been reached or the target no longer exists. public override bool processOrder() { double speedMultiplier = 1.0; //was this just for debugging? if so we should remove it, if not, then maybe move it to game settings? double minimumDistance = 1000.0; PositionDB currentPosition = Owner.GetDataBlob <PositionDB>(); PositionDB targetPosition = null; double AUSpeed, kmSpeed; kmSpeed = Owner.GetDataBlob <PropulsionDB>().MaximumSpeed *speedMultiplier; AUSpeed = Distance.KmToAU(kmSpeed); currentPosition.SetParent(null); if (PositionTarget != null) { // just head straight towards the target position targetPosition = PositionTarget; // Assume that 1000 is extremely close, if (Distance.AuToKm(distanceBetweenPositions(currentPosition, targetPosition)) <= minimumDistance) { setPositionToTarget(Owner, targetPosition); Owner.GetDataBlob <PropulsionDB>().CurrentSpeed = new Vector4(0, 0, 0, 0); return(true); } else { Owner.GetDataBlob <PropulsionDB>().CurrentSpeed = getSpeed(currentPosition, targetPosition, kmSpeed); return(false); } } else if (Target == null || Target == Entity.InvalidEntity) // Target no longer exists { return(true); } else { targetPosition = Target.GetDataBlob <PositionDB>(); // Assume that 1000 is extremely close, if (Distance.AuToKm(distanceBetweenPositions(currentPosition, targetPosition)) <= minimumDistance) { setPositionToTarget(Owner, targetPosition); currentPosition.SetParent(Target); return(true); } if (Target.HasDataBlob <OrbitDB>()) { if (Target.GetDataBlob <OrbitDB>().IsStationary) { // just head straight towards the target position targetPosition = Target.GetDataBlob <PositionDB>(); Owner.GetDataBlob <PropulsionDB>().CurrentSpeed = getSpeed(currentPosition, targetPosition, kmSpeed); } else { // TODO: Figure out an intercept based on OrbitProcessor.GetPosition // for now, just head straight towards the target position targetPosition = Target.GetDataBlob <PositionDB>(); Owner.GetDataBlob <PropulsionDB>().CurrentSpeed = getSpeed(currentPosition, targetPosition, kmSpeed); return(false); } } else if (Target.HasDataBlob <PropulsionDB>()) { if (Target.GetDataBlob <PropulsionDB>().MaximumSpeed >= Owner.GetDataBlob <PropulsionDB>().MaximumSpeed) // Target is faster than our ship, and cannot intercept { // Just head in a straight line targetPosition = Target.GetDataBlob <PositionDB>(); Owner.GetDataBlob <PropulsionDB>().CurrentSpeed = getSpeed(currentPosition, targetPosition, kmSpeed); } else { // Calculate an intercept targetPosition = Target.GetDataBlob <PositionDB>(); Vector4 targetPos = new Vector4(targetPosition.X, targetPosition.Y, targetPosition.Z, 0); Vector4 currentPos = new Vector4(currentPosition.X, currentPosition.Y, currentPosition.Z, 0); targetPos = Find_collision_point(targetPos, Target.GetDataBlob <PropulsionDB>().CurrentSpeed, currentPos, AUSpeed); targetPosition = new PositionDB(targetPos, targetPosition.SystemGuid); Owner.GetDataBlob <PropulsionDB>().CurrentSpeed = getSpeed(currentPosition, targetPosition, kmSpeed); } } } return(false); }