public void prepareResourceList(StoredVessel sv) { if (resourceTransferList.Count > 0) { return; } foreach (var r in sv.resources.resourcesNames) { if (hangarResources.ResourceCapacity(r) == 0) { continue; } ResourceManifest rm = new ResourceManifest(); rm.name = r; rm.amount = sv.resources.ResourceAmount(r); rm.capacity = sv.resources.ResourceCapacity(r); rm.offset = rm.amount; rm.host_amount = hangarResources.ResourceAmount(r); rm.host_capacity = hangarResources.ResourceCapacity(r); rm.pool = rm.host_amount + rm.offset; rm.minAmount = Math.Max(0, rm.pool - rm.host_capacity); rm.maxAmount = Math.Min(rm.pool, rm.capacity); resourceTransferList.Add(rm); } }
public void transferResources(StoredVessel sv) { if (resourceTransferList.Count == 0) { return; } foreach (var r in resourceTransferList) { //transfer resource between hangar and protovessel var a = hangarResources.TransferResource(r.name, r.offset - r.amount); a = r.amount - r.offset + a; var b = sv.resources.TransferResource(r.name, a); hangarResources.TransferResource(r.name, b); //update masses PartResourceDefinition res_def = PartResourceLibrary.Instance.GetDefinition(r.name); if (res_def.density == 0) { continue; } float dM = (float)a * res_def.density; float dC = (float)a * res_def.unitCost; vessels_mass += dM; vessels_cost += dC; sv.mass += dM; sv.cost += dC; set_part_params(); } resourceTransferList.Clear(); }
public void TryRestoreVessel(StoredVessel stored_vessel) { if (!can_restore()) { return; } ScreenMessager.showMessage(string.Format("Launching {0}...", stored_vessel.vessel.vesselName), 3); //clean up stored_vessels.Remove(stored_vessel.vessel.vesselID); //switch hangar state hangar_state = HangarState.Inactive; //transfer resources transferResources(stored_vessel); //set restored vessel orbit GetLaunchTransform(); position_vessel(stored_vessel); //restore vessel stored_vessel.Load(); //get restored vessel from the world launched_vessel = stored_vessel.vessel.vesselRef; //transfer crew back to the launched vessel List <ProtoCrewMember> crew_to_transfer = CrewTransfer.delCrew(vessel, stored_vessel.crew); //change volume and mass change_part_params(stored_vessel.metric, -1f); //switch to restored vessel FlightGlobals.ForceSetActiveVessel(launched_vessel); SetupVessel(new LaunchedVessel(stored_vessel, launched_vessel, crew_to_transfer, part.flightID)); }
//build dropdown list of stored vessels void BuildVesselList(Hangar hangar) { //reset stat vessels.Clear(); vessel_list.Items = new List <string>(); selected_vessel = null; //check hangar if (hangar == null) { return; } //build new list vessels = hangar.GetVessels(); if (vessels.Count > 0) { selected_vessel = vessels.Find(v => v.vessel.vesselID == vessel_id); if (selected_vessel == null) { selected_vessel = vessels[0]; } var vessel_names = new List <string>(); for (int i = 0; i < vessels.Count; i++) { vessel_names.Add(string.Format("{0} {1}", i + 1, vessels[i].vessel.vesselName)); } vessel_list.Items = vessel_names; vessel_list.SelectItem(vessels.IndexOf(selected_vessel)); } }
public LaunchedVessel(StoredVessel sv, Vessel vsl, List<ProtoCrewMember> crew, uint hangar_id) : base(vsl) { this.sv = sv; this.crew = crew; this.hangar_id = hangar_id; }
public LaunchedVessel(StoredVessel sv, Vessel vsl, List <ProtoCrewMember> crew, uint hangar_id) : base(vsl) { this.sv = sv; this.crew = crew; this.hangar_id = hangar_id; }
void Select_Vessel(StoredVessel vsl) { vessel_id = vsl.vessel.vesselID; vessel_list.SelectItem(vessels.IndexOf(vsl)); if (vsl != selected_vessel) { selected_hangar.resourceTransferList.Clear(); } selected_vessel = vsl; }
//store vessel void store_vessel(Vessel vsl, bool perform_checks = true) { StoredVessel stored_vessel = new StoredVessel(); if (perform_checks) //for normal operation { //check momentary states if (!can_store(vsl)) { return; } //check if the vessel can be stored, if unknown, try to store bool storable; if (!probed_ids.TryGetValue(vsl.id, out storable)) { stored_vessel = try_store(vsl); storable = stored_vessel != null; probed_ids.Add(vsl.id, storable); } if (!storable) { return; } } else //for storing packed constructs upon hangar launch { stored_vessel = new StoredVessel(vsl); stored_vessels.ForceAdd(stored_vessel); } //get vessel crew on board List <ProtoCrewMember> _crew = new List <ProtoCrewMember>(stored_vessel.crew); CrewTransfer.delCrew(vsl, _crew); vsl.DespawnCrew(); //first of, add crew to the hangar if there's a place CrewTransfer.addCrew(part, _crew); //then add to other vessel parts if needed CrewTransfer.addCrew(vessel, _crew); //recalculate volume and mass change_part_params(stored_vessel.metric); //switch to hangar vessel before storing if (FlightGlobals.ActiveVessel.id == vsl.id) { FlightGlobals.ForceSetActiveVessel(vessel); } //destroy vessel vsl.Die(); ScreenMessager.showMessage("Vessel has been docked inside the hangar", 3); }
/// <summary> /// Set vessel orbit, transform, coordinates. /// </summary> /// <param name="sv">Stored vessel</param> void position_vessel(StoredVessel sv) { ProtoVessel pv = sv.vessel; //state pv.splashed = vessel.Landed; pv.landed = vessel.Splashed; //rotation //it is essential to use BackupVessel() instead of vessel.protoVessel, //because in general the latter does not store the current flight state of the vessel ProtoVessel hpv = vessel.BackupVessel(); Quaternion proto_rot = hpv.rotation; Quaternion hangar_rot = vessel.vesselTransform.rotation; //rotate launchTransform.rotation to protovessel's reference frame pv.rotation = proto_rot * hangar_rot.Inverse() * launchTransform.rotation; //calculate launch offset from vessel bounds Vector3 bounds_offset = launchTransform.TransformDirection(sv.CoM - sv.CoG); //set vessel's orbit Orbit horb = vessel.orbit; Orbit vorb = new Orbit(); Vector3 d_pos = launchTransform.position - vessel.findWorldCenterOfMass() + bounds_offset; Vector3d vpos = horb.pos + new Vector3d(d_pos.x, d_pos.z, d_pos.y); vorb.UpdateFromStateVectors(vpos, horb.vel, horb.referenceBody, Planetarium.GetUniversalTime()); pv.orbitSnapShot = new OrbitSnapshot(vorb); //position on a surface if (vessel.LandedOrSplashed) { //calculate launch offset from vessel bounds bounds_offset = launchTransform.TransformDirection(-sv.CoG); //set vessel's position vpos = Vector3d.zero + launchTransform.position + bounds_offset; pv.longitude = vessel.mainBody.GetLongitude(vpos); pv.latitude = vessel.mainBody.GetLatitude(vpos); pv.altitude = vessel.mainBody.GetAltitude(vpos); } }
StoredVessel try_store(Vessel vsl) { //check vessel crew if (vsl.GetCrewCount() > vessel.GetCrewCapacity() - vessel.GetCrewCount()) { ScreenMessager.showMessage("Not enough space for the crew of a docking vessel", 3); return(null); } //check vessel metrics GetLaunchTransform(); StoredVessel sv = new StoredVessel(vsl); if (!sv.metric.FitsAligned(launchTransform, part.partTransform, hangar_metric)) { ScreenMessager.showMessage("The vessel does not fit into this hangar", 3); return(null); } if (!stored_vessels.Add(sv)) { ScreenMessager.showMessage("There's no room in the hangar for this vessel", 3); return(null); } return(sv); }
protected abstract Vector3 get_vessel_offset(Transform launch_transform, StoredVessel sv);
protected virtual void on_vessel_launch(StoredVessel sv) { }
void load_vessel(StoredVessel sv) { sv.proto_vessel.Load(HighLogic.CurrentGame.flightState); StartCoroutine(wait_for_launched_vessel(sv.vessel)); }
StoredVessel try_store(Vessel vsl) { //check vessel crew if(vsl.GetCrewCount() > vessel.GetCrewCapacity()-vessel.GetCrewCount()) { ScreenMessager.showMessage("Not enough space for the crew of a docking vessel", 3); return null; } //check vessel metrics GetLaunchTransform(); StoredVessel sv = new StoredVessel(vsl); if(!sv.metric.FitsAligned(launchTransform, part.partTransform, hangar_metric)) { ScreenMessager.showMessage("The vessel does not fit into this hangar", 3); return null; } if(!stored_vessels.Add(sv)) { ScreenMessager.showMessage("There's no room in the hangar for this vessel", 3); return null; } return sv; }
StoredVessel try_store_vessel(Vessel vsl) { //check vessel crew var vsl_crew = vsl.GetCrewCount(); if(NoCrewTransfers && vsl_crew > 0) { ScreenMessager.showMessage("Crew cannot enter through this hangar. Leave your ship before docking."); return null; } if(vsl_crew > vessel.GetCrewCapacity()-vessel.GetCrewCount()) { ScreenMessager.showMessage("Not enough space for the crew of a docking vessel"); return null; } //check vessel metrics var sv = new StoredVessel(vsl, Storage.ComputeHull); return try_store_vessel(sv) ? sv : null; }
public static void SelectVessel(StoredVessel vsl) { instance.Select_Vessel(vsl); }
void onVesselGoOffRails(Vessel vsl) { if(launched_vessel == null) return; if(launched_vessel.vessel != vsl) return; launched_vessel = null; FlightGlobals.ForceSetActiveVessel(vsl); }
public void TryRestoreVessel(StoredVessel stored_vessel) { if(!can_restore()) return; ScreenMessager.showMessage(string.Format("Launching {0}...", stored_vessel.vessel.vesselName), 3); //clean up stored_vessels.Remove(stored_vessel.vessel.vesselID); //switch hangar state hangar_state = HangarState.Inactive; //transfer resources transferResources(stored_vessel); //set restored vessel orbit GetLaunchTransform(); position_vessel(stored_vessel); //restore vessel stored_vessel.Load(); //get restored vessel from the world launched_vessel = stored_vessel.vessel.vesselRef; //transfer crew back to the launched vessel List<ProtoCrewMember> crew_to_transfer = CrewTransfer.delCrew(vessel, stored_vessel.crew); //change volume and mass change_part_params(stored_vessel.metric, -1f); //switch to restored vessel FlightGlobals.ForceSetActiveVessel(launched_vessel); SetupVessel(new LaunchedVessel(stored_vessel, launched_vessel, crew_to_transfer, part.flightID)); }
public void transferResources(StoredVessel sv) { if(resourceTransferList.Count == 0) return; foreach(var r in resourceTransferList) { //transfer resource between hangar and protovessel var a = hangarResources.TransferResource(r.name, r.offset-r.amount); a = r.amount-r.offset + a; var b = sv.resources.TransferResource(r.name, a); hangarResources.TransferResource(r.name, b); //update masses PartResourceDefinition res_def = PartResourceLibrary.Instance.GetDefinition(r.name); if(res_def.density == 0) continue; float dM = (float)a*res_def.density; float dC = (float)a*res_def.unitCost; vessels_mass += dM; vessels_cost += dC; sv.mass += dM; sv.cost += dC; set_part_params(); } resourceTransferList.Clear(); }
public void prepareResourceList(StoredVessel sv) { if(resourceTransferList.Count > 0) return; foreach(var r in sv.resources.resourcesNames) { if(hangarResources.ResourceCapacity(r) == 0) continue; ResourceManifest rm = new ResourceManifest(); rm.name = r; rm.amount = sv.resources.ResourceAmount(r); rm.capacity = sv.resources.ResourceCapacity(r); rm.offset = rm.amount; rm.host_amount = hangarResources.ResourceAmount(r); rm.host_capacity = hangarResources.ResourceCapacity(r); rm.pool = rm.host_amount + rm.offset; rm.minAmount = Math.Max(0, rm.pool-rm.host_capacity); rm.maxAmount = Math.Min(rm.pool, rm.capacity); resourceTransferList.Add(rm); } }
public void TryRestoreVessel(StoredVessel stored_vessel) { if(!can_restore(stored_vessel)) return; //clean up if(!Storage.RemoveVessel(stored_vessel)) { ScreenMessager.showMessage("WARNING: restored vessel is not found in the Stored Vessels: {0}\n" + "This should never happen!", stored_vessel.id); return; } ScreenMessager.showMessage("Launching \"{0}\"...", stored_vessel.name); //switch hangar state Deactivate(); //transfer resources transferResources(stored_vessel); //set restored vessel orbit position_vessel(stored_vessel); //let child classes make their modifications on_vessel_launch(stored_vessel); //transfer crew back to the launched vessel List<ProtoCrewMember> crew_to_transfer = CrewTransfer.delCrew(vessel, stored_vessel.crew); CrewTransfer.addCrew(stored_vessel.proto_vessel, crew_to_transfer); //restore vessel launched_vessel = stored_vessel; load_vessel(stored_vessel); }
protected override Vector3 get_vessel_offset(Transform launch_transform, StoredVessel sv) { return vessel.LandedOrSplashed ? launch_transform.TransformDirection(-sv.CoG + Vector3.up*sv.size.y/2) : launch_transform.TransformDirection(sv.CoM - sv.CoG + Vector3.up*sv.size.y/2); }
/// <summary> /// Set vessel orbit, transform, coordinates. /// </summary> /// <param name="sv">Stored vessel</param> void position_vessel(StoredVessel sv) { ProtoVessel pv = sv.vessel; //state pv.splashed = vessel.Landed; pv.landed = vessel.Splashed; //rotation //it is essential to use BackupVessel() instead of vessel.protoVessel, //because in general the latter does not store the current flight state of the vessel ProtoVessel hpv = vessel.BackupVessel(); Quaternion proto_rot = hpv.rotation; Quaternion hangar_rot = vessel.vesselTransform.rotation; //rotate launchTransform.rotation to protovessel's reference frame pv.rotation = proto_rot*hangar_rot.Inverse()*launchTransform.rotation; //calculate launch offset from vessel bounds Vector3 bounds_offset = launchTransform.TransformDirection(sv.CoM - sv.CoG); //set vessel's orbit Orbit horb = vessel.orbit; Orbit vorb = new Orbit(); Vector3 d_pos = launchTransform.position-vessel.findWorldCenterOfMass()+bounds_offset; Vector3d vpos = horb.pos+new Vector3d(d_pos.x, d_pos.z, d_pos.y); vorb.UpdateFromStateVectors(vpos, horb.vel, horb.referenceBody, Planetarium.GetUniversalTime()); pv.orbitSnapShot = new OrbitSnapshot(vorb); //position on a surface if(vessel.LandedOrSplashed) { //calculate launch offset from vessel bounds bounds_offset = launchTransform.TransformDirection(-sv.CoG); //set vessel's position vpos = Vector3d.zero+launchTransform.position+bounds_offset; pv.longitude = vessel.mainBody.GetLongitude(vpos); pv.latitude = vessel.mainBody.GetLatitude(vpos); pv.altitude = vessel.mainBody.GetAltitude(vpos); } }
/// <summary> /// Set vessel orbit, transform, coordinates. /// </summary> /// <param name="sv">Stored vessel</param> void position_vessel(StoredVessel sv) { var pv = sv.proto_vessel; //state pv.splashed = vessel.Splashed; pv.landed = vessel.Landed; pv.landedAt = vessel.landedAt; //rotation //rotate spawn_transform.rotation to protovessel's reference frame var spawn_transform = get_spawn_transform(sv); pv.rotation = vessel.mainBody.bodyTransform.rotation.Inverse() * spawn_transform.rotation; //set vessel's orbit var UT = Planetarium.GetUniversalTime(); var horb = vessel.orbitDriver.orbit; var vorb = new Orbit(); var d_pos = spawn_transform.position-vessel.CurrentCoM+get_vessel_offset(spawn_transform, sv); var vpos = horb.pos - horb.GetRotFrameVel(horb.referenceBody)*TimeWarp.fixedDeltaTime + new Vector3d(d_pos.x, d_pos.z, d_pos.y); var vvel = horb.vel; if(LaunchWithPunch && LaunchVelocity != Vector3.zero) { //honor the momentum conservation law //:calculate launched vessel velocity var hM = vessel.GetTotalMass(); var tM = hM + sv.mass; var d_vel = part.transform.TransformDirection(LaunchVelocity); vvel += (Vector3d.zero + d_vel*hM/tM).xzy; //:calculate hangar's vessel velocity deltaV = d_vel*(-sv.mass)/tM; change_velocity = true; } vorb.UpdateFromStateVectors(vpos, vvel, horb.referenceBody, UT); pv.orbitSnapShot = new OrbitSnapshot(vorb); //position on a surface if(vessel.LandedOrSplashed) { vpos = spawn_transform.position+get_vessel_offset(spawn_transform, sv); pv.longitude = vessel.mainBody.GetLongitude(vpos); pv.latitude = vessel.mainBody.GetLatitude(vpos); pv.altitude = vessel.mainBody.GetAltitude(vpos); } }
//store vessel void store_vessel(Vessel vsl, bool perform_checks = true) { StoredVessel stored_vessel = new StoredVessel(); if(perform_checks) //for normal operation { //check momentary states if(!can_store(vsl)) return; //check if the vessel can be stored, if unknown, try to store bool storable; if(!probed_ids.TryGetValue(vsl.id, out storable)) { stored_vessel = try_store(vsl); storable = stored_vessel != null; probed_ids.Add(vsl.id, storable); } if(!storable) return; } else //for storing packed constructs upon hangar launch { stored_vessel = new StoredVessel(vsl); stored_vessels.ForceAdd(stored_vessel); } //get vessel crew on board List<ProtoCrewMember> _crew = new List<ProtoCrewMember>(stored_vessel.crew); CrewTransfer.delCrew(vsl, _crew); vsl.DespawnCrew(); //first of, add crew to the hangar if there's a place CrewTransfer.addCrew(part, _crew); //then add to other vessel parts if needed CrewTransfer.addCrew(vessel, _crew); //recalculate volume and mass change_part_params(stored_vessel.metric); //switch to hangar vessel before storing if(FlightGlobals.ActiveVessel.id == vsl.id) FlightGlobals.ForceSetActiveVessel(vessel); //destroy vessel vsl.Die(); ScreenMessager.showMessage("Vessel has been docked inside the hangar", 3); }
protected override void on_vessel_launch(StoredVessel sv) { sv.crew.Clear(); sv.crew.AddRange(part.protoModuleCrew); //transfer the target and controls var this_vsl = vessel.BackupVessel(); sv.proto_vessel.targetInfo = this_vsl.targetInfo; sv.proto_vessel.ctrlState = this_vsl.ctrlState; sv.proto_vessel.actionGroups = this_vsl.actionGroups; //transfer the flight plan if(vessel.patchedConicSolver != null && vessel.patchedConicSolver.maneuverNodes.Count > 0) { var nearest_node = vessel.patchedConicSolver.maneuverNodes[0]; var new_orbit = sv.proto_vessel.orbitSnapShot.Load(); var vvel = new_orbit.getOrbitalVelocityAtUT(nearest_node.UT).xzy; var vpos = new_orbit.getPositionAtUT(nearest_node.UT).xzy; nearest_node.nodeRotation = Quaternion.LookRotation(vvel, Vector3d.Cross(-vpos, vvel)); nearest_node.DeltaV = nearest_node.nodeRotation.Inverse() * (nearest_node.nextPatch.getOrbitalVelocityAtUT(nearest_node.UT).xzy-vvel); sv.proto_vessel.flightPlan.ClearData(); vessel.patchedConicSolver.Save(sv.proto_vessel.flightPlan); vessel.patchedConicSolver.maneuverNodes.Clear(); vessel.patchedConicSolver.flightPlan.Clear(); } jettison_fairings(); //turn everything off Storage.enabled = Storage.isEnabled = false; Events["LaunchVessel"].active = Actions["LaunchVesselAction"].active = false; //this event is catched by FlightLogger GameEvents.onStageSeparation.Fire(new EventReport(FlightEvents.STAGESEPARATION, part, null, null, Staging.CurrentStage, string.Empty)); }