public override void Execute(SharedObjects shared) { double ut; // Accepts zero or one arg: int argCount = CountRemainingArgs(shared); // If one arg, then assume its seconds: if (argCount == 1) { ut = GetDouble(PopValueAssert(shared)); ReturnValue = new kOS.Suffixed.TimeSpan(ut); } // If more args, assume they are year, day, hour, minute, second, with optional // args at the end (eg. if there's only 3 args, it's year, day, hour with no minutes or seconds). else if (argCount == 2) { double day = GetDouble(PopValueAssert(shared)); double year = GetDouble(PopValueAssert(shared)); ReturnValue = new kOS.Suffixed.TimeSpan(year, day, 0.0, 0.0, 0.0); } else if (argCount == 3) { double hour = GetDouble(PopValueAssert(shared)); double day = GetDouble(PopValueAssert(shared)); double year = GetDouble(PopValueAssert(shared)); ReturnValue = new kOS.Suffixed.TimeSpan(year, day, hour, 0.0, 0.0); } else if (argCount == 4) { double minute = GetDouble(PopValueAssert(shared)); double hour = GetDouble(PopValueAssert(shared)); double day = GetDouble(PopValueAssert(shared)); double year = GetDouble(PopValueAssert(shared)); ReturnValue = new kOS.Suffixed.TimeSpan(year, day, hour, minute, 0.0); } else if (argCount == 5) { double second = GetDouble(PopValueAssert(shared)); double minute = GetDouble(PopValueAssert(shared)); double hour = GetDouble(PopValueAssert(shared)); double day = GetDouble(PopValueAssert(shared)); double year = GetDouble(PopValueAssert(shared)); ReturnValue = new kOS.Suffixed.TimeSpan(year, day, hour, minute, second); } AssertArgBottomAndConsume(shared); }
// Note: "TIME" is both a bound variable AND a built-in function now. // If it gets called with parentheses(), the script calls this built-in function. // If it gets called without them, then the bound variable is what gets called instead. // Calling it using parentheses but with empty args: TIME() gives the same result // as the bound variable. While it would be cleaner to make it JUST a built-in function, // the bound variable had to be retained for backward compatibility with scripts // that call TIME without parentheses. public override void Execute(SharedObjects shared) { double ut; // Accepts zero or one arg: int argCount = CountRemainingArgs(shared); // If zero args, then the default is to assume you want to // make a Timespan of "now": if (argCount == 0) { ut = Planetarium.GetUniversalTime(); } else { ut = GetDouble(PopValueAssert(shared)); } AssertArgBottomAndConsume(shared); ReturnValue = new kOS.Suffixed.TimeSpan(ut); }
/// <summary> /// Subclasses must override this method to return the OrbitableVelocity of this object at some /// arbitrary future time. It must take into account any orbital transfers to other SOI's /// and any planned maneuver nodes (It should return the predicted location under the /// assumption that the maneuver nodes currently planned will be executed as planned.) /// (Technically it can also describe positions in the past). /// </summary> /// <param name="timeStamp">The universal time of the future prediction</param> /// <returns> /// A OrbitableVelocity object containing both the orbital and surface velocities of the object in the /// <a href='http://ksp-kos.github.io/KOS_DOC/summary_topics/coordframe/raw/'> /// raw (soi-body-origin) /// </a> /// coordinate reference frame. /// </returns> abstract public OrbitableVelocity GetVelocitiesAtUT( TimeSpan timeStamp );
/// <summary> /// Subclasses must override this method to return the position of this object at some /// arbitrary future time. It must take into account any orbital transfers to other SOI's /// and any planned maneuver nodes (It should return the predicted location under the /// assumption that the maneuver nodes currently planned will be executed as planned.) /// (Technically it can also describe positions in the past). /// </summary> /// <param name="timeStamp">The universal time of the future prediction</param> /// <returns> /// The coords of the object in the /// <a href='http://ksp-kos.github.io/KOS_DOC/summary_topics/coordframe/raw/'> /// raw (cpu-vessel-origin) /// </a> /// coordinate reference frame. /// </returns> abstract public Vector GetPositionAtUT( TimeSpan timeStamp );
/// <summary> /// Calculates the velocities of this vessel at some future universal timestamp, /// taking into account all currently predicted SOI transition patches, and also /// assuming that all the planned manuever nodes will actually be executed precisely /// as planned. Note that this cannot "see" into the future any farther than the /// KSP orbit patches setting allows for. /// </summary> /// <param name="timeStamp">The time to predict for. Although the intention is to /// predict for a future time, it could be used to predict for a past time.</param> /// <returns>The orbit/surface velocity pair as a user-readable Vector in raw rotation coordinates.</returns> public override OrbitableVelocity GetVelocitiesAtUT(TimeSpan timeStamp) { double desiredUT = timeStamp.ToUnixStyleTime(); Orbit patch = GetOrbitAtUT( desiredUT ); Vector3d orbVel = patch.getOrbitalVelocityAtUT(desiredUT); // This is an ugly workaround to fix what is probably a bug in KSP's API: // If looking at a future orbit patch around a child body of the current body, then // the various get{Thingy}AtUT() methods return numbers calculated incorrectly as // if the child body was going to remain stationary where it is now, rather than // taking into account where it will be later when the intercept happens. // This corrects for that case: if (Utils.BodyOrbitsBody(patch.referenceBody, Vessel.orbit.referenceBody)) { Vector3d futureBodyVel = patch.referenceBody.orbit.getOrbitalVelocityAtUT(desiredUT); orbVel = orbVel + futureBodyVel; } // For some weird reason orbital velocities are returned by the KSP API // with Y and Z swapped, so swap them back: orbVel = new Vector3d( orbVel.x, orbVel.z, orbVel.y ); CelestialBody parent = patch.referenceBody; Vector surfVel; if (parent != null) { Vector3d pos = GetPositionAtUT( timeStamp ).ToVector3D(); surfVel = new Vector( orbVel - parent.getRFrmVel( pos + Shared.Vessel.GetWorldPos3D()) ); } else surfVel = new Vector( orbVel.x, orbVel.y, orbVel.z ); return new OrbitableVelocity( new Vector(orbVel), surfVel ); }
/// <summary> /// Calculates the position of this vessel at some future universal timestamp, /// taking into account all currently predicted SOI transition patches, and also /// assuming that all the planned manuever nodes will actually be executed precisely /// as planned. Note that this cannot "see" into the future any farther than the /// KSP orbit patches setting allows for. /// </summary> /// <param name="timeStamp">The time to predict for. Although the intention is to /// predict for a future time, it could be used to predict for a past time.</param> /// <returns>The position as a user-readable Vector in Shared.Vessel-origin raw rotation coordinates.</returns> public override Vector GetPositionAtUT(TimeSpan timeStamp) { double desiredUT = timeStamp.ToUnixStyleTime(); Orbit patch = GetOrbitAtUT( desiredUT ); Vector3d pos = patch.getPositionAtUT(desiredUT); // This is an ugly workaround to fix what is probably a bug in KSP's API: // If looking at a future orbit patch around a child body of the current body, then // the various get{Thingy}AtUT() methods return numbers calculated incorrectly as // if the child body was going to remain stationary where it is now, rather than // taking into account where it will be later when the intercept happens. // This corrects for that case: if (Utils.BodyOrbitsBody(patch.referenceBody, Vessel.orbit.referenceBody)) { Vector3d futureSOIPosNow = patch.referenceBody.position; Vector3d futureSOIPosLater = patch.referenceBody.getPositionAtUT(desiredUT); Vector3d offset = futureSOIPosLater - futureSOIPosNow; pos = pos + offset; } return new Vector( pos - Shared.Vessel.GetWorldPos3D() ); // Convert to ship-centered frame. }