private void onLevelWasLoaded(GameScenes scene) { if (scene != GameScenes.MAINMENU) { return; } Log("MAINMENU is loaded. Waiting 60 frames and loading the save."); StartCoroutine(CallbackUtil.DelayedCallback(60, LoadGame)); }
private void OnLevelWasLoaded(GameScenes scene) { PatchColliders(); PatchFlightIntegrator(); FixCameras(); PatchTimeOfDayAnimation(); StartCoroutine(CallbackUtil.DelayedCallback(3, FixFlags)); PatchContracts(); previousScene = HighLogic.LoadedScene; }
public override void OnStart(StartState state) { base.OnStart(state); just_started = true; StartCoroutine(CallbackUtil.DelayedCallback(1, create_deploy_hint_mesh)); if (State == DeplyomentState.DEPLOYING) { StartCoroutine(deploy()); } }
//the initiation of callback utility must be in a main tread and before any possible call on it. public static void Init() { if (instance == null) { obj = new GameObject(); obj.name = "CallbackFunctionalityObject"; obj.SetActive(true); DontDestroyOnLoad(obj); instance = obj.AddComponent <CallbackUtil>(); } }
void Start() { this.Log("Starting WorldSpaceTrace for {}s at {}", Delay, transform.position); StartCoroutine(CallbackUtil.DelayedCallback (Delay, () => { if (gameObject != null) { Destroy(gameObject); } })); }
private void OnLevelWasLoaded(GameScenes scene) { PatchFlightIntegrator(); FixCameras(); PatchTimeOfDayAnimation(); StartCoroutine(CallbackUtil.DelayedCallback(3, FixFlags)); for (Int32 i = 0; i < PSystemManager.Instance.localBodies.Count; i++) { PatchStarReferences(PSystemManager.Instance.localBodies[i]); PatchContractWeight(PSystemManager.Instance.localBodies[i]); } }
void fromEVA(GameEvents.FromToAction <Part, Part> data) { // use Hydrazine instead of MonoPropellant if RealFuel is installed string monoprop_name = detected_mods.RealFuels ? "Hydrazine" : "MonoPropellant"; // get any leftover EVA Fuel from EVA vessel double monoprop = data.from.Resources.list[0].amount; // add the leftover monoprop back to the pod data.to.RequestResource(monoprop_name, -monoprop); // manage resources in rules foreach (Rule r in rules) { if (r.resource_name.Length == 0 || r.on_eva <= double.Epsilon) { continue; } double leftover = ResourceCache.Info(data.from.vessel, r.resource_name).amount; data.to.RequestResource(r.resource_name, -leftover); } // merge EVA computer files into vessel Computer a = DB.VesselData(data.from.vessel.id).computer; Computer b = DB.VesselData(data.to.vessel.id).computer; b.merge(a); // forget vessel data DB.ForgetVessel(data.from.vessel.id); // purge vessel from resource cache ResourceCache.Purge(data.from.vessel.id); // execute script on vessel computer if (DB.Ready()) { DB.VesselData(data.to.vessel.id).computer.execute("run", "auto/eva_in", string.Empty, data.to.vessel); } // mute messages for a couple seconds to avoid warning messages from the vessel resource amounts Message.MuteInternal(); base.StartCoroutine(CallbackUtil.DelayedCallback(2.0f, Message.UnmuteInternal)); // if vessel info is open, switch to the vessel if (Info.IsOpen()) { Info.Open(data.to.vessel); } }
void onPartJointBreak(PartJoint joint, float force) { if (state != State.Fixed || !IsDocked) { return; } var dockedPart = vessel[dockedPartUId]; if (joint.Parent == part && joint.Child == dockedPart || joint.Parent == dockedPart && joint.Child == part) { state = State.Broken; StartCoroutine(CallbackUtil.DelayedCallback(3, part.explode)); } }
public static void CreateMissingPartsInCurrentProtoVessel(Vessel vessel, ProtoVessel protoVessel) { //TODO: This is old code where we created parts dinamically but it's quite buggy. It create parts in the CURRENT vessel so it wont work for other vessels //We've run trough all the vessel parts and removed the ones that don't exist in the definition. //Now run trough the parts in the definition and add the parts that don't exist in the vessel. var partsToInit = new List <ProtoPartSnapshot>(); foreach (var partSnapshot in protoVessel.protoPartSnapshots) { if (partSnapshot.FindModule("ModuleDockingNode") != null) { //We are in a docking port part so remove it from our own vessel if we have it if (FlightGlobals.FindLoadedPart(partSnapshot.persistentId, out var vesselPart)) { vesselPart.Die(); } } //Skip parts that already exists if (FlightGlobals.FindLoadedPart(partSnapshot.persistentId, out _)) { continue; } var newPart = partSnapshot.Load(vessel, false); vessel.parts.Add(newPart); partsToInit.Add(partSnapshot); } //Init new parts. This must be done in another loop as otherwise new parts won't have their correct attachment parts. foreach (var partSnapshot in partsToInit) { partSnapshot.Init(vessel); } vessel.RebuildCrewList(); MainSystem.Singleton.StartCoroutine(CallbackUtil.DelayedCallback(0.25f, () => { if (FlightGlobals.ActiveVessel) { FlightGlobals.ActiveVessel.SpawnCrew(); } })); MainSystem.Singleton.StartCoroutine(CallbackUtil.DelayedCallback(0.5f, () => { if (KerbalPortraitGallery.Instance) { KerbalPortraitGallery.Instance.SetActivePortraitsForVessel(FlightGlobals.ActiveVessel); } })); }
public void ShowGroup() { var group = GetGroup(); group.ForEach(m => m.part.HighlightAlways(m.TCA_Active? Color.green : (m.GroupMaster? Color.magenta : Color.cyan))); StartCoroutine(CallbackUtil.DelayedCallback(3.0f, () => group.ForEach(m => { if (m != null && m.part != null) { m.part.SetHighlightDefault(); } }))); }
public void ShowGroup() { var group = GetGroup(); group.ForEach(m => m.part.HighlightAlways(m.TCA_Active ? Colors.Enabled : (m.GroupMaster ? Colors.Selected2 : Colors.Selected1))); StartCoroutine(CallbackUtil.DelayedCallback(3.0f, () => group.ForEach(m => { if (m != null && m.part != null) { m.part.SetHighlightDefault(); } }))); }
private void OnLevelWasLoaded(GameScenes scene) { PatchColliders(); PatchFlightIntegrator(); FixCameras(); PatchTimeOfDayAnimation(); StartCoroutine(CallbackUtil.DelayedCallback(3, FixFlags)); //Small Contract fixer to remove Sentinel Contracts Type contractTypeToRemove = null; try { foreach (Type contract in Contracts.ContractSystem.ContractTypes) { try { if (contract.FullName.Contains("SentinelContract")) { contractTypeToRemove = contract; } } catch { continue; } } if (!(contractTypeToRemove == null)) { ContractSystem.ContractTypes.Remove(contractTypeToRemove); contractTypeToRemove = null; Debug.Log("[Kopernicus] ScenarioDiscoverableObjects is removed, scrubbing SENTINEL contracts."); } } catch { contractTypeToRemove = null; } //Patch weights of contracts for (Int32 i = 0; i < PSystemManager.Instance.localBodies.Count; i++) { PatchStarReferences(PSystemManager.Instance.localBodies[i]); PatchContractWeight(PSystemManager.Instance.localBodies[i]); } }
private void updatePhysicsParams() { updateCoMOffset(); delayedUpdateInertiaTensor(); #if DEBUG StartCoroutine(CallbackUtil.DelayedCallback(3, () => { if (vessel != null) { VesselMass = vessel.GetTotalMass(); } else if (HighLogic.LoadedSceneIsEditor) { VesselMass = EditorLogic.fetch.ship.GetTotalMass(); } })); #endif }
public void UpdateMesh() { if (body_mesh == null || body_collider == null) { return; } update_body(); update_attach_nodes(); update_passage(); var data = new BaseEventDetails(BaseEventDetails.Sender.AUTO); data.Set <string>("volName", "Tankage"); data.Set <double>("newTotalVolume", body.current.V * UsableVolumeRatio); part.SendEvent("OnPartVolumeChanged", data); old_size = size; old_aspect = aspect; Utils.UpdateEditorGUI(); StartCoroutine(CallbackUtil.DelayedCallback(1, UpdateDragCube)); just_loaded = false; }
public void Decouple() { var dockedPart = vessel[dockedPartUId]; if (dockedPart != null) { restore_docking_info(dockedPart); var parent = part.parent; var old_vessel = vessel; var referenceTransformId = vessel.referenceTransformId; if (parent != dockedPart) { dockedPart.Undock(docked_vessel); dockedPart.attachNodes.Remove(grappleNode); } else { part.Undock(this_vessel); part.attachNodes.Remove(grappleNode); } grappleNode.attachedPart = null; grappleNode.owner = null; part.fuelLookupTargets.Remove(dockedPart); dockedPart.fuelLookupTargets.Remove(part); GameEvents.onPartFuelLookupStateChange.Fire(new GameEvents.HostedFromToAction <bool, Part>(true, part, dockedPart)); AddForceAlongGrapples(dockedPart, -GrappleForce); if (old_vessel == FlightGlobals.ActiveVessel) { if (old_vessel[referenceTransformId] == null) { StartCoroutine(CallbackUtil.DelayedCallback(1, () => FlightGlobals.ForceSetActiveVessel(vessel))); } } } if (armAnimator != null) { armAnimator.Close(); } state = State.Idle; update_part_menu(); }
void Rescale() { if (model == null) { return; } var scale = GetScale(); update_model(scale); //update modules updaters.ForEach(u => u.OnRescale(scale)); //save size and aspect old_size = size; old_aspect = aspect; old_local_scale = model.localScale; Utils.UpdateEditorGUI(); if (HighLogic.LoadedSceneIsFlight) { StartCoroutine(CallbackUtil.DelayedCallback(1, UpdateDragCube)); } just_loaded = false; }
public void OnGUILaunchScreenVesselSelected(ShipTemplate t) { StartCoroutine(CallbackUtil.DelayedCallback(1, BuildCrewAssignmentDialogue)); }
public void OnGUIAstronautComplexSpawn() { StartCoroutine(CallbackUtil.DelayedCallback(1, BuildAstronautComplex)); }
public static void respawnCrew(Vessel V) { Vessel.CrewWasModified(V); FlightGlobals.ActiveVessel.DespawnCrew(); V.StartCoroutine(CallbackUtil.DelayedCallback(1, FlightGlobals.ActiveVessel.SpawnCrew)); }
protected override IEnumerable <YieldInstruction> before_vessel_launch(PackedVessel vsl) { if (fairings.Count == 0 || jettisoned) { yield break; } //save part mass for the future var partMass = part.Rigidbody.mass - vsl.mass - part.resourceMass; //store crew vsl.crew.Clear(); vsl.crew.AddRange(part.protoModuleCrew); //decouple surface attached parts and decoupleNodes var decouple = part.children .Where(p => p.srfAttachNode?.attachedPart == part) .ToList(); // ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator foreach (var node in decoupleNodes) { if (node.attachedPart == null) { continue; } decouple.Add(node.attachedPart == part.parent ? part : node.attachedPart); disable_decouplers(node.id); } jettisonForces.Clear(); var jettisonPower = JettisonPower <= 1 ? Mathf.LerpUnclamped(MinJettisonPower, 1, JettisonPower) : JettisonPower; var jettisonForce = JettisonForce * jettisonPower / 2; var jettisonTorque = JettisonTorque * jettisonPower; foreach (var p in decouple) { var force_target = p; if (p == part) { force_target = part.parent; } p.decouple(); if (force_target.Rigidbody != null) { var pos = force_target.Rigidbody.worldCenterOfMass; var minForce = (float)(force_target == part.parent ? vessel.totalMass - part.MassWithChildren() : force_target.MassWithChildren()) / TimeWarp.fixedDeltaTime; var force = (pos - part.Rigidbody.worldCenterOfMass).normalized * Utils.Clamp(jettisonForce, minForce, minForce * 10); jettisonForces.Add(force_target.Rigidbody, force, pos); } yield return(null); force_target.vessel.IgnoreGForces(10); } //apply force to decoupled parts and wait for them to clear away if (jettisonForces.Count > 0) { FX?.Burst(); jettisonForces.Apply(part.Rigidbody); yield return(new WaitForSeconds(3)); } //spawn debris debris.Clear(); debris_cost = 0; debris_mass = 0; var debrisDestroyCountdown = Utils.ClampL(DestroyDebrisIn, 1); jettisonForce /= fairingsSpecificMass.Values.Max(); foreach (var f in fairings) { var specMass = fairingsSpecificMass[f]; var d = Debris.SetupOnTransform(part, f, partMass * specMass, FairingsCost, DebrisLifetime); var force = f.TransformDirection(JettisonDirection) * (jettisonForce * specMass); var pos = d.Rigidbody.worldCenterOfMass; if (!JettisonForcePos.IsZero()) { pos += f.TransformVector(JettisonForcePos); } jettisonForces.Add(d.Rigidbody, force, pos, jettisonTorque); if (DestroyDebrisIn > 0) { d.selfDestruct = debrisDestroyCountdown; } d.DetectCollisions(false); d.vessel.IgnoreGForces(10); debris_cost += FairingsCost; debris_mass += d.Rigidbody.mass; if (DestroyDebrisIn > 0) { d.selfDestructPower = explosionPower(d.Rigidbody); } debris.Add(d); } vessel.IgnoreGForces(10); jettisonForces.Apply(part.Rigidbody #if DEBUG , false #endif ); //update drag cubes part.DragCubes.SetCubeWeight("Fairing ", 0f); part.DragCubes.SetCubeWeight("Clean ", 1f); part.DragCubes.ForceUpdate(true, true, true); //this event is catched by FlightLogger StartCoroutine(CallbackUtil.DelayedCallback(10, update_debris_after_launch)); GameEvents.onStageSeparation.Fire(new EventReport(FlightEvents.STAGESEPARATION, part, vsl.name, vessel.GetDisplayName(), vessel.currentStage, $"{vsl.name} separated from {vessel.GetDisplayName()}")); FX?.Burst(); if (DestroyDebrisIn > 0 && vessel.Parts.Count == 1 && vessel.Parts.First() == part) { StartCoroutine(self_destruct(debrisDestroyCountdown)); } part.UpdateCoMOffset(Vector3.Lerp( BaseCoMOffset, part.CoMOffset, vsl.mass / (part.Rigidbody.mass - debris_mass))); jettisoned = true; update_PAW(); }
public void EditorStarted() { // The ER, on startup, sets a 3s delayed callback. We run right after it. _kctInstance.StartCoroutine(CallbackUtil.DelayedCallback(3.1f, () => { ClobberEngineersReport(); })); }
public override void OnStart(StartState state) { base.OnStart(state); StartCoroutine(CallbackUtil.DelayedCallback(5, () => { enabled = isEnabled = part.Resources.Count > 0; })); }
public void RebuildAstronautComplex(KSP.UI.CrewListItem.ButtonTypes type, KSP.UI.CrewListItem cic) { StartCoroutine(CallbackUtil.DelayedCallback(1, BuildAstronautComplex)); }
private void Start() => StartCoroutine(CallbackUtil.DelayedCallback(timeout, Destroy, gameObject));
void toEVA(GameEvents.FromToAction <Part, Part> data) { // use Hydrazine instead of MonoPropellant if RealFuel is installed string monoprop_name = detected_mods.RealFuels ? "Hydrazine" : "MonoPropellant"; // determine if inside breathable atmosphere // note: the user can force the helmet + oxygen by pressing shift when going on eva bool breathable = Sim.Breathable(data.from.vessel) && !(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)); // get total crew in the origin vessel double tot_crew = (double)data.from.vessel.GetVesselCrew().Count + 1.0; // EVA vessels start with 5 units of eva fuel, remove them data.to.RequestResource("EVA Propellant", 5.0); // determine how much MonoPropellant to get // note: never more that the 'share' of this kerbal double monoprop = Math.Min(ResourceCache.Info(data.from.vessel, monoprop_name).amount / tot_crew, Settings.MonoPropellantOnEVA); // get monoprop from the vessel monoprop = data.from.RequestResource(monoprop_name, monoprop); // transfer monoprop to the EVA kerbal data.to.RequestResource("EVA Propellant", -monoprop); // show warning if there isn't monoprop in the eva suit if (monoprop <= double.Epsilon && !Lib.Landed(data.from.vessel)) { Message.Post(Severity.danger, Lib.BuildString("There isn't any <b>", monoprop_name, "</b> in the EVA suit", "Don't let the ladder go!")); } // manage resources from rules foreach (Rule r in rules) { if (r.resource_name.Length == 0 || r.on_eva <= double.Epsilon) { continue; } // determine amount to take, never more that his own share double amount = Math.Min(ResourceCache.Info(data.from.vessel, r.resource_name).amount / tot_crew, r.on_eva); // deal with breathable modifier if (breathable && r.modifier.Contains("breathable")) { continue; } // remove resource from the vessel amount = data.from.RequestResource(r.resource_name, amount); // create new resource in the eva kerbal Lib.SetupResource(data.to, r.resource_name, amount, r.on_eva); } // get KerbalEVA KerbalEVA kerbal = data.to.FindModuleImplementing <KerbalEVA>(); // turn off headlamp light, to avoid stock bug that show the light for a split second when going on eva EVA.SetHeadlamp(kerbal, false); EVA.SetFlares(kerbal, false); // remove the helmet if inside breathable atmosphere // note: done in EVA::FixedUpdate(), but also done here avoid 'popping' of the helmet when going on eva EVA.SetHelmet(kerbal, !breathable); // remember if the kerbal has an helmet EVA.KerbalData(data.to.vessel).has_helmet = !breathable; // execute script on vessel computer if (DB.Ready()) { DB.VesselData(data.from.vessel.id).computer.execute("run", "auto/eva_out", string.Empty, data.from.vessel); } // mute messages for a couple seconds to avoid warning messages from the vessel resource amounts Message.MuteInternal(); base.StartCoroutine(CallbackUtil.DelayedCallback(2.0f, Message.UnmuteInternal)); // if vessel info is open, switch to the eva kerbal // note: for a single tick, the EVA vessel is not valid (sun_dist is zero) // this make IsVessel() return false, that in turn close the vessel info instantly // for this reason, we wait a small amount of time before switching the info window if (Info.IsOpen()) { Info.Open(data.to.vessel); } }
/// <summary> /// This method will take a vessel and update all it's parts and proto based on a protovessel we received /// Protovessel --------------> Vessel & ProtoVessel /// This way we avoid having to unload and reload a vessel with it's terrible performance /// </summary> public static void UpdateVesselPartsFromProtoVessel(Vessel vessel, ProtoVessel protoVessel, IEnumerable <uint> vesselPartsId = null) { if (vessel == null || protoVessel == null || vessel.state == Vessel.State.DEAD) { return; } if (vessel.id != protoVessel.vesselID) { LunaLog.LogError($"Tried to update a vessel id {vessel.id} with a protovessel of vessel id {protoVessel.vesselID}"); return; } var vesselProtoPartIds = vesselPartsId ?? protoVessel.protoPartSnapshots.Select(p => p.flightID); //If vessel is UNLOADED it won't have parts so we must take them from the proto... var vesselPartsIds = vessel.loaded ? vessel.parts.Select(p => p.flightID) : vessel.protoVessel.protoPartSnapshots.Select(p => p.flightID); var hasMissingparts = vesselProtoPartIds.Except(vesselPartsIds).Any(); if (hasMissingparts || !VesselCommon.IsSpectating && (vessel.isEVA && vessel.situation != protoVessel.situation || !vessel.Landed && protoVessel.landed || !vessel.Splashed && protoVessel.splashed || vessel.situation != protoVessel.situation && HighLogic.LoadedScene == GameScenes.TRACKSTATION)) { //Reload the whole vessel if vessel lands/splashes as otherwise map view puts the vessel next to the other player. //Also reload the whole vesse if it's a EVA and situation changed or in track station.... //Better to reload if has missing parts as creating them dinamically is a PIA VesselLoader.ReloadVessel(protoVessel); return; } var hasCrewChanges = false; //Never do vessel.protoVessel = protoVessel; not even if the vessel is not loaded as when it gets loaded the parts are created in the active vessel //and not on the target vessel //Run trough all the vessel parts and protoparts. //Vessel.parts will be empty if vessel is unloaded. var protoPartsToRemove = new List <ProtoPartSnapshot>(); for (var i = 0; i < vessel.protoVessel.protoPartSnapshots.Count; i++) { var protoPartToUpdate = vessel.protoVessel.protoPartSnapshots[i]; var partSnapshot = VesselCommon.FindProtoPartInProtovessel(protoVessel, protoPartToUpdate.flightID); if (partSnapshot == null) //Part does not exist in the protovessel definition so kill it { protoPartsToRemove.Add(protoPartToUpdate); continue; } AdjustCrewMembersInProtoPart(protoPartToUpdate, partSnapshot); protoPartToUpdate.state = partSnapshot.state; UpdatePartModulesInProtoPart(protoPartToUpdate, partSnapshot); UpdateProtoVesselResources(protoPartToUpdate, partSnapshot); var part = protoPartToUpdate.partRef; if (part != null) //Part can be null if the vessel is unloaded!! { //Remove or add crew members in given part and detect if there have been any change hasCrewChanges |= AdjustCrewMembersInPart(part, partSnapshot); //Set part "state" field... Important for fairings for example... StateField?.SetValue(part, partSnapshot.state); part.ResumeState = part.State; UpdatePartModules(partSnapshot, part); UpdateVesselResources(partSnapshot, part); UpdatePartFairings(partSnapshot, part); } } //Now kill both parts and protoparts that don't exist for (var i = 0; i < protoPartsToRemove.Count; i++) { //Part can be null if the vessel is unloaded. In this case, no need to kill it as it's already gone from the game. if (protoPartsToRemove[i].partRef != null) { if (protoPartsToRemove[i].partRef.FindModuleImplementing <ModuleDecouple>() != null) { protoPartsToRemove[i].partRef.decouple(); } else { protoPartsToRemove[i].partRef.Die(); } } vessel.protoVessel.protoPartSnapshots.Remove(protoPartsToRemove[i]); } if (hasCrewChanges) { //We must always refresh the crew in every part of the vessel, even if we don't spectate vessel.RebuildCrewList(); //IF we are spectating we must fix the portraits of the kerbals if (FlightGlobals.ActiveVessel?.id == vessel.id) { //If you don't call spawn crew and you do a crew transfer the transfered crew won't appear in the portraits... Client.Singleton.StartCoroutine(CallbackUtil.DelayedCallback(0.25f, () => { FlightGlobals.ActiveVessel?.SpawnCrew(); })); //If you don't call this the kerbal portraits appear in black... Client.Singleton.StartCoroutine(CallbackUtil.DelayedCallback(0.5f, () => { KerbalPortraitGallery.Instance?.SetActivePortraitsForVessel(FlightGlobals.ActiveVessel); })); } } }
public void RebuildCrewAssignmentDialogue(KSP.UI.CrewListItem.ButtonTypes type, KSP.UI.CrewListItem cic) { StartCoroutine(CallbackUtil.DelayedCallback(1, BuildCrewAssignmentDialogue)); }
void Start() { GameEvents.OnKSCFacilityUpgraded.Add(FixFlags); StartCoroutine(CallbackUtil.DelayedCallback(3, FixFlags)); }
public static void respawnCrew(Vessel fromV, Vessel toV) { fromV.DespawnCrew(); toV.DespawnCrew(); toV.StartCoroutine(CallbackUtil.DelayedCallback(1, FlightGlobals.ActiveVessel.SpawnCrew)); }
public override void OnLoad(ConfigNode node) { // get version of the savegame // note: if there isn't a version this is either a new game, or the first public release (that didn't have versioning) string version = node.HasValue("version") ? node.GetValue("version") : node.HasNode("kerbals") ? "0.9.9.0" : current_version; // this is an unsupported version, attempt a total clean up and pray // note: currently unused if (string.CompareOrdinal(version, "0.9.9.0") < 0) { Lib.Log("loading save from unsupported version " + version); kerbals.Clear(); vessels.Clear(); bodies.Clear(); notifications = new notification_data(); return; } kerbals.Clear(); if (node.HasNode("kerbals")) { ConfigNode kerbals_node = node.GetNode("kerbals"); foreach(ConfigNode kerbal_node in kerbals_node.GetNodes()) { kerbal_data kd = new kerbal_data(); kd.resque = Lib.ConfigValue(kerbal_node, "resque", 1u); kd.disabled = Lib.ConfigValue(kerbal_node, "disabled", 0u); kd.living_space = Lib.ConfigValue(kerbal_node, "living_space", 1.0); // since 0.9.9.4 kd.entertainment = Lib.ConfigValue(kerbal_node, "entertainment", 1.0); // since 0.9.9.4 kd.shielding = Lib.ConfigValue(kerbal_node, "shielding", 0.0); // since 0.9.9.4 kd.space_name = Lib.ConfigValue(kerbal_node, "space_name", ""); // since 0.9.9.4 kd.kmon = new Dictionary<string, kmon_data>(); if (kerbal_node.HasNode("kmon")) // since 0.9.9.5 { foreach(var cfg in kerbal_node.GetNode("kmon").GetNodes()) { kmon_data kmon = new kmon_data(); kmon.problem = Lib.ConfigValue(cfg, "problem", 0.0); kmon.message = Lib.ConfigValue(cfg, "message", 0u); kmon.time_since = Lib.ConfigValue(cfg, "time_since", 0.0); kd.kmon.Add(cfg.name, kmon); } } kerbals.Add(kerbal_node.name.Replace("___", " "), kd); } } vessels.Clear(); if (node.HasNode("vessels")) { ConfigNode vessels_node = node.GetNode("vessels"); foreach(ConfigNode vessel_node in vessels_node.GetNodes()) { vessel_data vd = new vessel_data(); vd.msg_signal = Lib.ConfigValue(vessel_node, "msg_signal", 0u); vd.msg_belt = Lib.ConfigValue(vessel_node, "msg_belt", 0u); vd.cfg_ec = Lib.ConfigValue(vessel_node, "cfg_ec", 1u); vd.cfg_supply = Lib.ConfigValue(vessel_node, "cfg_supply", 1u); vd.cfg_signal = Lib.ConfigValue(vessel_node, "cfg_signal", 1u); vd.cfg_malfunction = Lib.ConfigValue(vessel_node, "cfg_malfunction", 1u); vd.cfg_storm = Lib.ConfigValue(vessel_node, "cfg_storm", 1u); // since 0.9.9.5 vd.cfg_highlights = Lib.ConfigValue(vessel_node, "cfg_highlights", 1u); // since 0.9.9.5 vd.cfg_showlink = Lib.ConfigValue(vessel_node, "cfg_showlink", 0u); // since 0.9.9.8 vd.notes = Lib.ConfigValue(vessel_node, "notes", "").Replace("$NEWLINE", "\n"); // since 0.9.9.1 vd.group = Lib.ConfigValue(vessel_node, "group", "NONE"); // since 0.9.9.1 vd.vmon = new Dictionary<string, vmon_data>(); if (vessel_node.HasNode("vmon")) // since 0.9.9.5 { foreach(var cfg in vessel_node.GetNode("vmon").GetNodes()) { vmon_data vmon = new vmon_data(); vmon.message = Lib.ConfigValue(cfg, "message", 0u); vd.vmon.Add(cfg.name, vmon); } } vd.scansat_id = new List<uint>(); foreach(string s in vessel_node.GetValues("scansat_id")) // since 0.9.9.5 { vd.scansat_id.Add(Convert.ToUInt32(s)); } vessels.Add(new Guid(vessel_node.name), vd); } } bodies.Clear(); if (node.HasNode("bodies")) { ConfigNode bodies_node = node.GetNode("bodies"); foreach(ConfigNode body_node in bodies_node.GetNodes()) { body_data bd = new body_data(); bd.storm_time = Lib.ConfigValue(body_node, "storm_time", 0.0); bd.storm_age = Lib.ConfigValue(body_node, "storm_age", 0.0); bd.storm_state = Lib.ConfigValue(body_node, "storm_state", 0u); bd.msg_storm = Lib.ConfigValue(body_node, "msg_storm", 0u); bodies.Add(body_node.name.Replace("___", " "), bd); } } notifications = new notification_data(); if (node.HasNode("notifications")) { ConfigNode n_node = node.GetNode("notifications"); notifications.next_death_report = Lib.ConfigValue(n_node, "next_death_report", 0u); notifications.next_tutorial = Lib.ConfigValue(n_node, "next_tutorial", 0u); notifications.death_counter = Lib.ConfigValue(n_node, "death_counter", 0u); notifications.last_death_counter = Lib.ConfigValue(n_node, "last_death_counter", 0u); notifications.first_belt_crossing = Lib.ConfigValue(n_node, "first_belt_crossing", 0u); notifications.first_signal_loss = Lib.ConfigValue(n_node, "first_signal_loss", 0u); notifications.first_malfunction = Lib.ConfigValue(n_node, "first_malfunction", 0u); } // versions before 0.9.9.5 used a different structure to remember message sent // mute the message system for a few seconds to avoid the user being bombarded by messages if (string.CompareOrdinal(version, "0.9.9.5") < 0) { Message.MuteInternal(); base.StartCoroutine(CallbackUtil.DelayedCallback(10.0f, Message.UnmuteInternal)); } // versions before 0.9.9.5 didn't have profiles, and didn't use CRP food/oxygen values // scale all amounts of them in existing vessels, to not break savegames if (string.CompareOrdinal(version, "0.9.9.5") < 0) { foreach(Vessel v in FlightGlobals.Vessels.FindAll(k => !k.loaded)) { foreach(var part in v.protoVessel.protoPartSnapshots) { var food = part.resources.Find(k => k.resourceName == "Food"); if (food != null) { food.resourceValues.SetValue("amount", (Lib.ConfigValue(food.resourceValues, "amount", 0.0f) * 10.0f).ToString()); food.resourceValues.SetValue("maxAmount", (Lib.ConfigValue(food.resourceValues, "maxAmount", 0.0f) * 10.0f).ToString()); } var oxygen = part.resources.Find(k => k.resourceName == "Oxygen"); if (oxygen != null) { oxygen.resourceValues.SetValue("amount", (Lib.ConfigValue(oxygen.resourceValues, "amount", 0.0f) * 1000.0f).ToString()); oxygen.resourceValues.SetValue("maxAmount", (Lib.ConfigValue(oxygen.resourceValues, "maxAmount", 0.0f) * 1000.0f).ToString()); } } } } // if an old savegame was imported, log some debug info if (version != current_version) Lib.Log("savegame converted from version " + version); }