public void configure() { // 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 if (Lib.IsEditor()) { 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 bool active = selected.Contains(setup.name); // detect if the setup was previously selected bool prev_active = prev_selected.Contains(setup.name); // 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 IConfigurable configurable_module = m as IConfigurable; if (configurable_module != null) { 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); // (de)install resource if ((prev_active != (active && capacity > 0.0)) || (reconfigure_cs && initialized)) { // if previously selected if (prev_active) { // remove the resources Lib.RemoveResource(part, cr.name, amount, capacity); } // 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, capacity); } } // add resource cost if (active) { extra_cost += amount * unit_cost; } } // add setup extra cost and mass if (active) { extra_cost += setup.cost; extra_mass += setup.mass; } } // 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) { 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.configure(); } 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; }