public override void OnLoad(ConfigNode node) { // setups data from structured config node is only available at part compilation // for this reason, we parse it and then re-serialize it as a string if (HighLogic.LoadedScene == GameScenes.LOADING) { // parse all setups from config node and generate details setups = new List <ConfigureSetup>(); foreach (var setup_node in node.GetNodes("SETUP")) { setups.Add(new ConfigureSetup(setup_node, this)); } // serialize the setups to string data var archive = new WriteArchive(); archive.Save(setups.Count); foreach (var setup in setups) { setup.Save(archive); } data = archive.Serialize(); // serialize empty configuration to string data archive = new WriteArchive(); archive.Save(0); cfg = archive.Serialize(); // serialize empty previous configuration to string data archive = new WriteArchive(); archive.Save(0); prev_cfg = archive.Serialize(); } }
public void DoConfigure() { // shortcut to resource library var reslib = PartResourceLibrary.Instance.resourceDefinitions; // reset extra cost and mass extra_cost = 0.0; extra_mass = 0.0; // find modules unlocked by tech unlocked = new List <ConfigureSetup>(); foreach (ConfigureSetup setup in setups) { // if unlocked if (setup.tech.Length == 0 || Lib.HasTech(setup.tech)) { // unlock unlocked.Add(setup); } } // make sure configuration include all available slots // this also create default configuration // - we do it only in the editor // - we avoid corner case when cfg was never set up (because craft was never in VAB) if (Lib.IsEditor() || selected.Count == 0) { while (selected.Count < Math.Min(slots, (uint)unlocked.Count)) { selected.Add(unlocked.Find(k => selected.IndexOf(k.name) == -1).name); } } // for each setup foreach (ConfigureSetup setup in setups) { // detect if the setup is selected in multiple slots int count = (selected.FindAll(x => x == setup.name)).Count; // detect if the setup is selected bool active = count > 0; active &= enabled; // detect if the setup was previously selected in multiple slots int prev_count = (prev_selected.FindAll(x => x == setup.name)).Count; // detect if the setup was previously selected bool prev_active = prev_count > 0; // for each module specification in the setup foreach (ConfigureModule cm in setup.modules) { // try to find the module PartModule m = Find_module(cm); // if the module exist if (m != null) { // call configure/deconfigure functions on module if available if (m is IConfigurable configurable_module) { configurable_module.Configure(active); } // enable/disable the module m.isEnabled = active; m.enabled = active; } } // for each resource specification in the setup foreach (ConfigureResource cr in setup.resources) { // ignore non-existing resources if (!reslib.Contains(cr.name)) { continue; } // get resource unit cost double unit_cost = reslib[cr.name].unitCost; // parse resource amount and capacity double amount = Lib.Parse.ToDouble(cr.amount); double capacity = Lib.Parse.ToDouble(cr.maxAmount); // add/remove resource if ((prev_active != (active && capacity > 0.0)) || (reconfigure_cs && initialized) || (count != prev_count)) { // if previously selected if (prev_active) { // remove the resources prev_count = prev_count == 0 ? 1 : prev_count; Lib.RemoveResource(part, cr.name, amount * prev_count, capacity * prev_count); } // if selected if (active && capacity > 0.0) { // add the resources // - in flight, do not add amount Lib.AddResource(part, cr.name, Lib.IsFlight() ? 0.0 : amount * count, capacity * count); } } // add resource cost if (active) { extra_cost += amount * unit_cost * count; } } // add setup extra cost and mass if (active) { extra_cost += setup.cost * count; extra_mass += setup.mass * count; } } // remember previously selected setups prev_selected.Clear(); foreach (string s in selected) { prev_selected.Add(s); } // save configuration WriteArchive archive = new WriteArchive(); archive.Save(selected.Count); foreach (string s in selected) { archive.Save(s); } cfg = archive.Serialize(); // save previous configuration archive = new WriteArchive(); archive.Save(prev_selected.Count); foreach (string s in prev_selected) { archive.Save(s); } prev_cfg = archive.Serialize(); // in the editor if (Lib.IsEditor()) { // for each part in the symmetry group (avoid infinite recursion) if (!avoid_inf_recursion && symmetric) { avoid_inf_recursion = true; foreach (Part p in part.symmetryCounterparts) { // get the Configure module Configure c = p.FindModulesImplementing <Configure>().Find(k => k.title == title); // both modules will share configuration c.selected = selected; // re-configure the other module c.DoConfigure(); } avoid_inf_recursion = false; } } // refresh this part ui MonoUtilities.RefreshContextWindows(part); // refresh VAB ui if (Lib.IsEditor()) { GameEvents.onEditorShipModified.Fire(EditorLogic.fetch.ship); } // this was configured at least once initialized = true; }