void Analyze_qol(List <Part> parts, ResourceSimulator sim, EnvironmentAnalyzer env) { // calculate living space factor living_space = Lib.Clamp((volume / Math.Max(crew_count, 1u)) / PreferencesComfort.Instance.livingSpace, 0.1, 1.0); // calculate comfort factor comforts = new Comforts(parts, env.landed, crew_count > 1, has_comms); }
// execute the recipe public bool Execute(Vessel v, Vessel_resources resources) { // determine worst input ratio // - pure input recipes can just underflow double worst_input = left; if (outputs.Count > 0) { for (int i = 0; i < inputs.Count; ++i) { Entry e = inputs[i]; Resource_info_view res = GetResourceInfoView(v, resources, e.name); // handle combined inputs if (e.combined != null) { // is combined resource the primary if (e.combined != "") { Entry sec_e = inputs.Find(x => x.name.Contains(e.combined)); Resource_info_view sec = GetResourceInfoView(v, resources, sec_e.name); double pri_worst = Lib.Clamp((res.amount + res.deferred) * e.inv_quantity, 0.0, worst_input); if (pri_worst > 0.0) { worst_input = pri_worst; } else { worst_input = Lib.Clamp((sec.amount + sec.deferred) * sec_e.inv_quantity, 0.0, worst_input); } } } else { worst_input = Lib.Clamp((res.amount + res.deferred) * e.inv_quantity, 0.0, worst_input); } } } // determine worst output ratio // - pure output recipes can just overflow double worst_output = left; if (inputs.Count > 0) { for (int i = 0; i < outputs.Count; ++i) { Entry e = outputs[i]; if (!e.dump) // ignore outputs that can dump overboard { Resource_info_view res = GetResourceInfoView(v, resources, e.name); worst_output = Lib.Clamp((res.capacity - (res.amount + res.deferred)) * e.inv_quantity, 0.0, worst_output); } } } // determine worst-io double worst_io = Math.Min(worst_input, worst_output); // consume inputs for (int i = 0; i < inputs.Count; ++i) { Entry e = inputs[i]; Resource_info_view res = GetResourceInfoView(v, resources, e.name); // handle combined inputs if (e.combined != null) { // is combined resource the primary if (e.combined != "") { Entry sec_e = inputs.Find(x => x.name.Contains(e.combined)); Resource_info_view sec = GetResourceInfoView(v, resources, sec_e.name); double need = (e.quantity * worst_io) + (sec_e.quantity * worst_io); // do we have enough primary to satisfy needs, if so don't consume secondary if (res.amount + res.deferred >= need) { resources.Consume(v, e.name, need, name); } // consume primary if any available and secondary else { need -= res.amount + res.deferred; res.Consume(res.amount + res.deferred, name); sec.Consume(need, name); } } } else { res.Consume(e.quantity * worst_io, name); } } // produce outputs for (int i = 0; i < outputs.Count; ++i) { Entry e = outputs[i]; Resource_info_view res = GetResourceInfoView(v, resources, e.name); res.Produce(e.quantity * worst_io, name); } // produce cures for (int i = 0; i < cures.Count; ++i) { Entry entry = cures[i]; List <RuleData> curingRules = new List <RuleData>(); foreach (ProtoCrewMember crew in v.GetVesselCrew()) { KerbalData kd = DB.Kerbal(crew.name); if (kd.sickbay.IndexOf(entry.combined + ",", StringComparison.Ordinal) >= 0) { curingRules.Add(kd.Rule(entry.name)); } } foreach (RuleData rd in curingRules) { rd.problem -= entry.quantity * worst_io / curingRules.Count; rd.problem = Math.Max(rd.problem, 0); } } // update amount left to execute left -= worst_io; // the recipe was executed, at least partially return(worst_io > double.Epsilon); }
// execute the recipe public bool Execute(ResourceSimulator sim) { // determine worst input ratio double worst_input = left; if (outputs.Count > 0) { for (int i = 0; i < inputs.Count; ++i) { Resource_recipe.Entry e = inputs[i]; SimulatedResourceView res = sim.Resource(e.name).GetSimulatedResourceView(loaded_part); // handle combined inputs if (e.combined != null) { // is combined resource the primary if (e.combined != "") { Resource_recipe.Entry sec_e = inputs.Find(x => x.name.Contains(e.combined)); SimulatedResourceView sec = sim.Resource(sec_e.name).GetSimulatedResourceView(loaded_part); double pri_worst = Lib.Clamp(res.amount * e.inv_quantity, 0.0, worst_input); if (pri_worst > 0.0) { worst_input = pri_worst; } else { worst_input = Lib.Clamp(sec.amount * sec_e.inv_quantity, 0.0, worst_input); } } } else { worst_input = Lib.Clamp(res.amount * e.inv_quantity, 0.0, worst_input); } } } // determine worst output ratio double worst_output = left; if (inputs.Count > 0) { for (int i = 0; i < outputs.Count; ++i) { Resource_recipe.Entry e = outputs[i]; if (!e.dump) // ignore outputs that can dump overboard { SimulatedResourceView res = sim.Resource(e.name).GetSimulatedResourceView(loaded_part); worst_output = Lib.Clamp((res.capacity - res.amount) * e.inv_quantity, 0.0, worst_output); } } } // determine worst-io double worst_io = Math.Min(worst_input, worst_output); // consume inputs for (int i = 0; i < inputs.Count; ++i) { Resource_recipe.Entry e = inputs[i]; SimulatedResource res = sim.Resource(e.name); // handle combined inputs if (e.combined != null) { // is combined resource the primary if (e.combined != "") { Resource_recipe.Entry sec_e = inputs.Find(x => x.name.Contains(e.combined)); SimulatedResourceView sec = sim.Resource(sec_e.name).GetSimulatedResourceView(loaded_part); double need = (e.quantity * worst_io) + (sec_e.quantity * worst_io); // do we have enough primary to satisfy needs, if so don't consume secondary if (res.amount >= need) { res.Consume(need, name); } // consume primary if any available and secondary else { need -= res.amount; res.Consume(res.amount, name); sec.Consume(need, name); } } } else { res.Consume(e.quantity * worst_io, name); } } // produce outputs for (int i = 0; i < outputs.Count; ++i) { Resource_recipe.Entry e = outputs[i]; SimulatedResourceView res = sim.Resource(e.name).GetSimulatedResourceView(loaded_part); res.Produce(e.quantity * worst_io, name); } // update amount left to execute left -= worst_io; // the recipe was executed, at least partially return(worst_io > double.Epsilon); }