IEnumerable push_and_spin_launched_vessel(Vector3 dV) { FlightCameraOverride.UpdateDurationSeconds(1); var startP = part.Rigidbody.worldCenterOfMass; var startAV = part.Rigidbody.angularVelocity; var startAVm = startAV.sqrMagnitude; var vel = (Vector3d)part.Rigidbody.velocity; vel += Vector3d.Cross(startAV, launched_vessel.CoM - startP); if (!dV.IsZero()) { //conserve momentum var hM = vessel.GetTotalMass(); var lM = launched_vessel.GetTotalMass(); var lvel = dV * hM / (hM + lM); vel += lvel; part.Rigidbody.AddForce(-lvel * lM, ForceMode.Impulse); } launched_vessel.SetWorldVelocity(vel); for (int i = 0; i < 10; i++) { //this is a hack for incorrect VelocityChange mode (or whatever causing this); //if the startAV is applied once, the resulting vessel.angularVelocity is 2-3 times bigger var deltaAV = startAV - launched_vessel.transform.rotation * launched_vessel.angularVelocity; var deltaAVm = deltaAV.sqrMagnitude; if (deltaAVm < 1e-5) { break; } var av = deltaAVm > startAVm?deltaAV.ClampMagnitudeH(startAVm *Mathf.Sqrt(1 / deltaAVm)) : deltaAV / 3; var CoM = launched_vessel.CoM; foreach (Part p in launched_vessel.Parts) { if (p.Rigidbody != null) { p.Rigidbody.AddTorque(av, ForceMode.VelocityChange); p.Rigidbody.AddForce(Vector3.Cross(av, p.Rigidbody.worldCenterOfMass - CoM), ForceMode.VelocityChange); } } FlightCameraOverride.UpdateDurationSeconds(1); yield return(null); FlightCameraOverride.UpdateDurationSeconds(1); yield return(null); } }
public IEnumerator <YieldInstruction> SpawnShipConstructToGround(ShipConstruct construct, Transform spawn_transform, Vector3 spawn_offset, Callback <Vessel> on_vessel_positioned = null, Callback <Vessel> on_vessel_loaded = null, Callback <Vessel> on_vessel_off_rails = null, Callback <Vessel> on_vessel_launched = null, int easing_frames = 0) { begin_launch(spawn_transform); PutShipToGround(construct, spawn_transform, spawn_offset); ShipConstruction.AssembleForLaunch(construct, vessel.landedAt, vessel.displaylandedAt, part.flagURL, FlightDriver.FlightStateCache, new VesselCrewManifest()); launched_vessel = FlightGlobals.Vessels[FlightGlobals.Vessels.Count - 1]; on_vessel_positioned?.Invoke(launched_vessel); while (!launched_vessel.loaded) { FlightCameraOverride.UpdateDurationSeconds(1); yield return(new WaitForFixedUpdate()); } on_vessel_loaded?.Invoke(launched_vessel); while (launched_vessel.packed) { launched_vessel.precalc.isEasingGravity = true; launched_vessel.situation = Vessel.Situations.PRELAUNCH; stabilize_launched_vessel(0); FlightCameraOverride.UpdateDurationSeconds(1); yield return(new WaitForFixedUpdate()); } on_vessel_off_rails?.Invoke(launched_vessel); if (easing_frames > 0) { foreach (var n in stabilize_launched_vessel(easing_frames)) { FlightCameraOverride.UpdateDurationSeconds(1); yield return(new WaitForFixedUpdate()); } } on_vessel_launched?.Invoke(launched_vessel); StageManager.BeginFlight(); end_launch(); }
IEnumerable <YieldInstruction> launch_moving_vessel(Transform spawn_transform, Vector3 spawn_offset, Quaternion spawn_rot_offset, Vector3 dV, Callback <Vessel> on_vessel_loaded, Callback <Vessel> on_vessel_off_rails, Callback <Vessel> on_vessel_launched) { var vsl_colliders = new List <Collider>(); disable_vsl_colliders(launched_vessel, vsl_colliders); FlightCameraOverride.UpdateDurationSeconds(1); if (vessel.LandedOrSplashed) { while (launched_vessel.packed) { if (launched_vessel == null) { goto end; } launched_vessel.situation = Vessel.Situations.PRELAUNCH; run_on_vessel_loaded(on_vessel_loaded); FlightCameraOverride.UpdateDurationSeconds(1); try { launched_vessel.SetPosition(spawn_transform.TransformPointUnscaled(spawn_offset)); launched_vessel.SetRotation(spawn_transform.rotation * spawn_rot_offset); } catch (Exception e) { Utils.Log("Exception occured during launched_vessel.SetPosition/Rotation call. Ignoring it:\n{}", e.StackTrace); } launched_vessel.GoOffRails(); yield return(new WaitForFixedUpdate()); } if (launched_vessel == null) { goto end; } launched_vessel.SetPosition(spawn_transform.TransformPointUnscaled(spawn_offset)); launched_vessel.SetRotation(spawn_transform.rotation * spawn_rot_offset); } else { //hold the vessel inside the hangar until unpacked while (launched_vessel.packed) { if (launched_vessel == null) { goto end; } run_on_vessel_loaded(on_vessel_loaded); FlightCameraOverride.UpdateDurationSeconds(1); try { launched_vessel.SetPosition(spawn_transform.TransformPointUnscaled(spawn_offset)); launched_vessel.SetRotation(spawn_transform.rotation * spawn_rot_offset); } catch (Exception e) { Utils.Log("Exception occured during launched_vessel.SetPosition/Rotation call. Ignoring it:\n{}", e.StackTrace); } yield return(new WaitForFixedUpdate()); } if (launched_vessel == null) { goto end; } launched_vessel.SetPosition(spawn_transform.TransformPointUnscaled(spawn_offset)); launched_vessel.SetRotation(spawn_transform.rotation * spawn_rot_offset); } launched_vessel.situation = vessel.situation; FlightGlobals.ForceSetActiveVessel(launched_vessel); on_vessel_off_rails?.Invoke(launched_vessel); enable_vsl_colliders(vsl_colliders); launched_vessel.IgnoreGForces(10); foreach (var _ in push_and_spin_launched_vessel(spawn_transform.TransformDirection(dV))) { yield return(null); launched_vessel.IgnoreGForces(10); } on_vessel_launched?.Invoke(launched_vessel); end: { enable_vsl_colliders(vsl_colliders); yield break; } }