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 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); } }
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); }