void pullLaunchTargetToLaunchPosition(float dt) { var subTransform = this.part.FindModelTransform("LoadingPoint"); var testlocation = subTransform.position; if (vLaunchTarget != null) { var pullVector = testlocation - vLaunchTarget.GetWorldPos3D(); // print("pull vector " + pullVector.ToString()); // print("acceleration " + (pullVector * dt).ToString()); double f = powerLevel * acceleratorForce / 100; var spent = part.RequestResource(resourceName, dt * resourceAmount * f); if (spent == 0) { f = 0; } double m = vLaunchTarget.RevealMass(); float a = (float)(f / m); double strength = 4 * (pullVector.magnitude - loadDistance) / (loadDistance) * a; pullVector.Normalize(); pullVector = pullVector * a; vLaunchTarget.ChangeWorldVelocity(pullVector * dt); m = this.vessel.RevealMass(); a = (float)(f / m); pullVector.Normalize(); pullVector = pullVector * -a; //for every action there is an equal and opposite reaction //this.vessel.ChangeWorldVelocity(pullVector); //calculate resource draw based on the applied power } }
/// <summary> /// Applies surface interpolation values /// </summary> private void ApplySurfaceInterpolation(float interpolationValue) { var currentAcc = GetInterpolatedAcceleration(interpolationValue); var currentVelocity = GetInterpolatedVelocity(interpolationValue, currentAcc); var currentPosition = GetInterpolatedPosition(interpolationValue, currentVelocity, currentAcc); var radarAlt = Lerp(Position[3], Target.Position[3], interpolationValue); Vessel.SetPosition(currentPosition); Vessel.ChangeWorldVelocity(currentVelocity - Vessel.srf_velocity); Vessel.acceleration = currentAcc; Vessel.radarAltitude = radarAlt; }
/// <summary> /// Applies surface interpolation values /// </summary> private void ApplySurfaceInterpolation(float interpolationValue) { var currentAcc = GetInterpolatedAcceleration(interpolationValue); var currentVelocity = GetInterpolatedVelocity(interpolationValue, currentAcc); //Use the average velocity to determine the new position //Displacement = v0*t + 1/2at^2. //var positionFudge = (currentVelocity*PlanetariumDifference) + (0.5d*currentAcc*PlanetariumDifference*PlanetariumDifference); //return Vector3d.Lerp(startPos + positionFudge, targetPos + positionFudge, interpolationValue); Vessel.latitude = Lerp(Position[0], Target.Position[0], interpolationValue); Vessel.longitude = Lerp(Position[1], Target.Position[1], interpolationValue); Vessel.altitude = Lerp(Position[2], Target.Position[2], interpolationValue); Vessel.radarAltitude = Lerp(Position[3], Target.Position[3], interpolationValue); Vessel.ChangeWorldVelocity(currentVelocity - Vessel.srf_velocity); Vessel.acceleration = currentAcc; }
/// <summary> /// Applies interpolation when above 10000m /// </summary> private void ApplyOrbitInterpolation(float interpolationValue) { var startOrbit = new Orbit(Orbit[0], Orbit[1], Orbit[2], Orbit[3], Orbit[4], Orbit[5], Orbit[6], Body); var targetOrbit = new Orbit(Target.Orbit[0], Target.Orbit[1], Target.Orbit[2], Target.Orbit[3], Target.Orbit[4], Target.Orbit[5], Target.Orbit[6], Body); var currentOrbit = OrbitLerp(startOrbit, targetOrbit, Body, interpolationValue); currentOrbit.Init(); currentOrbit.UpdateFromUT(Planetarium.GetUniversalTime()); var latitude = Body.GetLatitude(currentOrbit.pos); var longitude = Body.GetLongitude(currentOrbit.pos); var altitude = Body.GetAltitude(currentOrbit.pos); Vessel.latitude = latitude; Vessel.longitude = longitude; Vessel.altitude = altitude; Vessel.protoVessel.latitude = latitude; Vessel.protoVessel.longitude = longitude; Vessel.protoVessel.altitude = altitude; if (Vessel.packed) { //The OrbitDriver update call will set the vessel position on the next fixed update CopyOrbit(currentOrbit, Vessel.orbitDriver.orbit); Vessel.orbitDriver.pos = Vessel.orbitDriver.orbit.pos.xzy; Vessel.orbitDriver.vel = Vessel.orbitDriver.orbit.vel; } else { var posDelta = currentOrbit.getPositionAtUT(Planetarium.GetUniversalTime()) - Vessel.orbitDriver.orbit.getPositionAtUT(Planetarium.GetUniversalTime()); var velDelta = currentOrbit.getOrbitalVelocityAtUT(Planetarium.GetUniversalTime()).xzy - Vessel.orbitDriver.orbit.getOrbitalVelocityAtUT(Planetarium.GetUniversalTime()).xzy; Vessel.Translate(posDelta); Vessel.ChangeWorldVelocity(velDelta); } }
private IEnumerator<WaitForFixedUpdate> restoreVesselState(Vessel vessel, Vector3 newWorldPos, Vector3 newOrbitVel) { yield return new WaitForFixedUpdate(); if (newWorldPos != Vector3.zero) { { Log.Debug("repositioning"); vessel.transform.position = newWorldPos; } if (newOrbitVel != Vector3.zero) { Log.Debug("updating velocity"); vessel.ChangeWorldVelocity((-1 * vessel.GetObtVelocity()) + newOrbitVel); } } }
public void Apply() { if (HighLogic.LoadedScene == GameScenes.LOADING) { return; } //Ignore updates to our own vessel if we are in flight and we aren't spectating if (!vesselWorker.isSpectating && (FlightGlobals.fetch.activeVessel != null ? FlightGlobals.fetch.activeVessel.id == vesselID : false) && HighLogic.LoadedScene == GameScenes.FLIGHT) { return; } Vessel updateVessel = FlightGlobals.fetch.vessels.FindLast(v => v.id == vesselID); if (updateVessel == null) { //DarkLog.Debug("ApplyVesselUpdate - Got vessel update for " + vesselID + " but vessel does not exist"); return; } CelestialBody updateBody = FlightGlobals.Bodies.Find(b => b.bodyName == bodyName); if (updateBody == null) { //DarkLog.Debug("ApplyVesselUpdate - updateBody not found"); return; } Quaternion normalRotate = Quaternion.identity; //Position/Velocity if (isSurfaceUpdate) { //Get the new position/velocity double altitudeFudge = 0; VesselUtil.DMPRaycastPair dmpRaycast = VesselUtil.RaycastGround(position[0], position[1], updateBody); if (dmpRaycast.altitude != -1d && position[3] != -1d) { Vector3 theirNormal = new Vector3(terrainNormal[0], terrainNormal[1], terrainNormal[2]); altitudeFudge = dmpRaycast.altitude - position[3]; if (Math.Abs(position[2] - position[3]) < 50f) { normalRotate = Quaternion.FromToRotation(theirNormal, dmpRaycast.terrainNormal); } } double planetariumDifference = Planetarium.GetUniversalTime() - planetTime; //Velocity fudge Vector3d updateAcceleration = updateBody.bodyTransform.rotation * new Vector3d(acceleration[0], acceleration[1], acceleration[2]); Vector3d velocityFudge = Vector3d.zero; if (Math.Abs(planetariumDifference) < 3f) { //Velocity = a*t velocityFudge = updateAcceleration * planetariumDifference; } //Position fudge Vector3d updateVelocity = updateBody.bodyTransform.rotation * new Vector3d(velocity[0], velocity[1], velocity[2]) + velocityFudge; Vector3d positionFudge = Vector3d.zero; if (Math.Abs(planetariumDifference) < 3f) { //Use the average velocity to determine the new position //Displacement = v0*t + 1/2at^2. positionFudge = (updateVelocity * planetariumDifference) + (0.5d * updateAcceleration * planetariumDifference * planetariumDifference); } Vector3d updatePostion = updateBody.GetWorldSurfacePosition(position[0], position[1], position[2] + altitudeFudge) + positionFudge; double latitude = updateBody.GetLatitude(updatePostion); double longitude = updateBody.GetLongitude(updatePostion); double altitude = updateBody.GetAltitude(updatePostion); updateVessel.latitude = latitude; updateVessel.longitude = longitude; updateVessel.altitude = altitude; updateVessel.protoVessel.latitude = latitude; updateVessel.protoVessel.longitude = longitude; updateVessel.protoVessel.altitude = altitude; if (updateVessel.packed) { if (!updateVessel.LandedOrSplashed) { //Not landed but under 10km. Vector3d orbitalPos = updatePostion - updateBody.position; Vector3d surfaceOrbitVelDiff = updateBody.getRFrmVel(updatePostion); Vector3d orbitalVel = updateVelocity + surfaceOrbitVelDiff; updateVessel.orbitDriver.orbit.UpdateFromStateVectors(orbitalPos.xzy, orbitalVel.xzy, updateBody, Planetarium.GetUniversalTime()); updateVessel.orbitDriver.pos = updateVessel.orbitDriver.orbit.pos.xzy; updateVessel.orbitDriver.vel = updateVessel.orbitDriver.orbit.vel; } } else { Vector3d velocityOffset = updateVelocity - updateVessel.srf_velocity; updateVessel.SetPosition(updatePostion, true); updateVessel.ChangeWorldVelocity(velocityOffset); } } else { Orbit updateOrbit = new Orbit(orbit[0], orbit[1], orbit[2], orbit[3], orbit[4], orbit[5], orbit[6], updateBody); updateOrbit.Init(); updateOrbit.UpdateFromUT(Planetarium.GetUniversalTime()); double latitude = updateBody.GetLatitude(updateOrbit.pos); double longitude = updateBody.GetLongitude(updateOrbit.pos); double altitude = updateBody.GetAltitude(updateOrbit.pos); updateVessel.latitude = latitude; updateVessel.longitude = longitude; updateVessel.altitude = altitude; updateVessel.protoVessel.latitude = latitude; updateVessel.protoVessel.longitude = longitude; updateVessel.protoVessel.altitude = altitude; if (updateVessel.packed) { //The OrbitDriver update call will set the vessel position on the next fixed update VesselUtil.CopyOrbit(updateOrbit, updateVessel.orbitDriver.orbit); updateVessel.orbitDriver.pos = updateVessel.orbitDriver.orbit.pos.xzy; updateVessel.orbitDriver.vel = updateVessel.orbitDriver.orbit.vel; } else { //Vessel.SetPosition is full of fun and games. Avoid at all costs. //Also, It's quite difficult to figure out the world velocity due to Krakensbane, and the reference frame. Vector3d posDelta = updateOrbit.getPositionAtUT(Planetarium.GetUniversalTime()) - updateVessel.orbitDriver.orbit.getPositionAtUT(Planetarium.GetUniversalTime()); Vector3d velDelta = updateOrbit.getOrbitalVelocityAtUT(Planetarium.GetUniversalTime()).xzy - updateVessel.orbitDriver.orbit.getOrbitalVelocityAtUT(Planetarium.GetUniversalTime()).xzy; //Vector3d velDelta = updateOrbit.vel.xzy - updateVessel.orbitDriver.orbit.vel.xzy; updateVessel.Translate(posDelta); updateVessel.ChangeWorldVelocity(velDelta); } } //Rotation Quaternion unfudgedRotation = new Quaternion(rotation[0], rotation[1], rotation[2], rotation[3]); Quaternion updateRotation = normalRotate * unfudgedRotation; updateVessel.SetRotation(updateVessel.mainBody.bodyTransform.rotation * updateRotation); if (updateVessel.packed) { updateVessel.srfRelRotation = updateRotation; updateVessel.protoVessel.rotation = updateVessel.srfRelRotation; } //Angular velocity Vector3 angularVelocity = updateVessel.mainBody.bodyTransform.rotation * updateRotation * new Vector3(this.angularVelocity[0], this.angularVelocity[1], this.angularVelocity[2]); if (updateVessel.parts != null) { foreach (Part vesselPart in updateVessel.parts) { if (vesselPart.rb != null && !vesselPart.rb.isKinematic && vesselPart.State == PartStates.ACTIVE) { vesselPart.rb.angularVelocity = angularVelocity; if (vesselPart != updateVessel.rootPart) { Vector3 rootPos = FlightGlobals.ActiveVessel.rootPart.rb.position; Vector3 rootVel = FlightGlobals.ActiveVessel.rootPart.rb.velocity; Vector3 diffPos = vesselPart.rb.position - rootPos; Vector3 partVelDifference = Vector3.Cross(angularVelocity, diffPos); vesselPart.rb.velocity = rootVel + partVelDifference; } } } } //Flight state controls (Throttle etc) if (!vesselWorker.isSpectating) { updateVessel.ctrlState.CopyFrom(flightState); } else { FlightInputHandler.state.CopyFrom(flightState); } //Action group controls updateVessel.ActionGroups.SetGroup(KSPActionGroup.Gear, actiongroupControls[0]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.Light, actiongroupControls[1]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, actiongroupControls[2]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.SAS, actiongroupControls[3]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.RCS, actiongroupControls[4]); }
public void Apply() { if (HighLogic.LoadedScene == GameScenes.LOADING) { return; } //Get updating player string updatePlayer = LockSystem.fetch.LockExists(vesselID) ? LockSystem.fetch.LockOwner(vesselID) : "Unknown"; //Ignore updates to our own vessel if we are in flight and we aren't spectating if (!VesselWorker.fetch.isSpectating && (FlightGlobals.fetch.activeVessel != null ? FlightGlobals.fetch.activeVessel.id.ToString() == vesselID : false) && HighLogic.LoadedScene == GameScenes.FLIGHT) { DarkLog.Debug("ApplyVesselUpdate - Ignoring update for active vessel from " + updatePlayer); return; } Vessel updateVessel = FlightGlobals.fetch.vessels.FindLast(v => v.id.ToString() == vesselID); if (updateVessel == null) { //DarkLog.Debug("ApplyVesselUpdate - Got vessel update for " + vesselID + " but vessel does not exist"); return; } CelestialBody updateBody = FlightGlobals.Bodies.Find(b => b.bodyName == bodyName); if (updateBody == null) { DarkLog.Debug("ApplyVesselUpdate - updateBody not found"); return; } //Rotation Quaternion updateRotation = new Quaternion(rotation[0], rotation[1], rotation[2], rotation[3]); updateVessel.SetRotation(updateVessel.mainBody.bodyTransform.rotation * updateRotation); if (updateVessel.packed) { updateVessel.srfRelRotation = updateRotation; updateVessel.protoVessel.rotation = updateVessel.srfRelRotation; } //Position/Velocity if (isSurfaceUpdate) { //Get the new position/velocity Vector3d updatePostion = updateBody.GetWorldSurfacePosition(position[0], position[1], position[2]); Vector3d updateVelocity = updateBody.bodyTransform.rotation * new Vector3d(velocity[0], velocity[1], velocity[2]); Vector3d updateAcceleration = updateBody.bodyTransform.rotation * new Vector3d(acceleration[0], acceleration[1], acceleration[2]); if (updateVessel.packed) { updateVessel.latitude = position[0]; updateVessel.longitude = position[1]; updateVessel.altitude = position[2]; updateVessel.protoVessel.latitude = updateVessel.latitude; updateVessel.protoVessel.longitude = updateVessel.longitude; updateVessel.protoVessel.altitude = updateVessel.altitude; if (!updateVessel.LandedOrSplashed) { //Not landed but under 10km. Vector3d orbitalPos = updatePostion - updateBody.position; Vector3d surfaceOrbitVelDiff = updateBody.getRFrmVel(updatePostion); Vector3d orbitalVel = updateVelocity + surfaceOrbitVelDiff; updateVessel.orbitDriver.orbit.UpdateFromStateVectors(orbitalPos.xzy, orbitalVel.xzy, updateBody, Planetarium.GetUniversalTime()); updateVessel.orbitDriver.pos = updateVessel.orbitDriver.orbit.pos.xzy; updateVessel.orbitDriver.vel = updateVessel.orbitDriver.orbit.vel; } } else { double planetariumDifference = Planetarium.GetUniversalTime() - planetTime; Vector3d positionFudge = Vector3d.zero; Vector3d velocityFudge = Vector3d.zero; if (Math.Abs(planetariumDifference) < 3f) { velocityFudge = updateAcceleration * planetariumDifference; //Use the average velocity to determine the new position positionFudge = (updateVelocity + (velocityFudge / 2)) * planetariumDifference; } Vector3d velocityOffset = (updateVelocity + velocityFudge) - updateVessel.srf_velocity; updateVessel.SetPosition(updatePostion + positionFudge, true); updateVessel.ChangeWorldVelocity(velocityOffset); } } else { Orbit updateOrbit = new Orbit(orbit[0], orbit[1], orbit[2], orbit[3], orbit[4], orbit[5], orbit[6], updateBody); updateOrbit.Init(); updateOrbit.UpdateFromUT(Planetarium.GetUniversalTime()); if (updateVessel.packed) { //The OrbitDriver update call will set the vessel position on the next fixed update VesselUtil.CopyOrbit(updateOrbit, updateVessel.orbitDriver.orbit); updateVessel.orbitDriver.pos = updateVessel.orbitDriver.orbit.pos.xzy; updateVessel.orbitDriver.vel = updateVessel.orbitDriver.orbit.vel; } else { //Vessel.SetPosition is full of fun and games. Avoid at all costs. //Also, It's quite difficult to figure out the world velocity due to Krakensbane, and the reference frame. Vector3d posDelta = updateOrbit.getPositionAtUT(Planetarium.GetUniversalTime()) - updateVessel.orbitDriver.orbit.getPositionAtUT(Planetarium.GetUniversalTime()); Vector3d velDelta = updateOrbit.getOrbitalVelocityAtUT(Planetarium.GetUniversalTime()).xzy - updateVessel.orbitDriver.orbit.getOrbitalVelocityAtUT(Planetarium.GetUniversalTime()).xzy; //Vector3d velDelta = updateOrbit.vel.xzy - updateVessel.orbitDriver.orbit.vel.xzy; updateVessel.Translate(posDelta); updateVessel.ChangeWorldVelocity(velDelta); } } //Angular velocity //Vector3 angularVelocity = new Vector3(this.angularVelocity[0], this.angularVelocity[1], this.angularVelocity[2]); if (updateVessel.parts != null) { //Vector3 newAng = updateVessel.ReferenceTransform.rotation * angularVelocity; foreach (Part vesselPart in updateVessel.parts) { if (vesselPart.rb != null && !vesselPart.rb.isKinematic && vesselPart.State == PartStates.ACTIVE) { //The parts can have different rotations - This transforms them into the root part direction which is where the angular velocity is transferred. //vesselPart.rb.angularVelocity = (Quaternion.Inverse(updateVessel.rootPart.rb.rotation) * vesselPart.rb.rotation) * newAng; vesselPart.rb.angularVelocity = Vector3.zero; } } } //Flight state controls (Throttle etc) if (!VesselWorker.fetch.isSpectating) { updateVessel.ctrlState.CopyFrom(flightState); } else { FlightInputHandler.state.CopyFrom(flightState); } //Action group controls updateVessel.ActionGroups.SetGroup(KSPActionGroup.Gear, actiongroupControls[0]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.Light, actiongroupControls[1]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, actiongroupControls[2]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.SAS, actiongroupControls[3]); updateVessel.ActionGroups.SetGroup(KSPActionGroup.RCS, actiongroupControls[4]); }