/// <summary>process a rule and add/remove the resources from the simulator</simulator> private void Process_rule_inner_body(double k, Part p, Rule r, EnvironmentAnalyzer env, VesselAnalyzer va) { // deduce rate per-second double rate = va.crew_count * (r.interval > 0.0 ? r.rate / r.interval : r.rate); // prepare recipe if (r.output.Length == 0) { Resource(r.input).Consume(rate * k, r.name); } else if (rate > double.Epsilon) { // simulate recipe if output_only is false if (!r.monitor) { // - rules always dump excess overboard (because it is waste) SimulatedRecipe recipe = new SimulatedRecipe(p, r.name); recipe.Input(r.input, rate * k); recipe.Output(r.output, rate * k * r.ratio, true); recipes.Add(recipe); } // only simulate output else { Resource(r.output).Produce(rate * k, r.name); } } }
/// <summary>process the process and add/remove the resources from the simulator</summary> private void Process_process_inner_body(double k, Part p, Process pr, EnvironmentAnalyzer env, VesselAnalyzer va) { // prepare recipe SimulatedRecipe recipe = new SimulatedRecipe(p, pr.name); foreach (KeyValuePair<string, double> input in pr.inputs) { recipe.Input(input.Key, input.Value * k); } foreach (KeyValuePair<string, double> output in pr.outputs) { recipe.Output(output.Key, output.Value * k, pr.dump.Check(output.Key)); } recipes.Add(recipe); }
void Process_harvester(Harvester harvester, VesselAnalyzer va) { if (harvester.running && harvester.simulated_abundance > harvester.min_abundance) { SimulatedRecipe recipe = new SimulatedRecipe(harvester.part, "harvester"); if (harvester.ec_rate > double.Epsilon) { recipe.Input("ElectricCharge", harvester.ec_rate); } recipe.Output( harvester.resource, Harvester.AdjustedRate(harvester, new CrewSpecs("Engineer@0"), va.crew, harvester.simulated_abundance), dump: false); recipes.Add(recipe); } }
void Process_generator(ModuleGenerator generator, Part p) { // skip launch clamps, that include a generator if (Lib.PartName(p) == "launchClamp1") return; SimulatedRecipe recipe = new SimulatedRecipe(p, "generator"); foreach (ModuleResource res in generator.resHandler.inputResources) { recipe.Input(res.name, res.rate); } foreach (ModuleResource res in generator.resHandler.outputResources) { recipe.Output(res.name, res.rate, true); } recipes.Add(recipe); }
void Process_harvester(ModuleResourceHarvester harvester, VesselAnalyzer va) { // calculate experience bonus float exp_bonus = harvester.UseSpecialistBonus ? harvester.EfficiencyBonus * (harvester.SpecialistBonusBase + (harvester.SpecialistEfficiencyFactor * (va.crew_engineer_maxlevel + 1))) : 1.0f; // use part name as recipe name // - include crew bonus in the recipe name string recipe_name = Lib.BuildString(harvester.part.partInfo.title, " (efficiency: ", Lib.HumanReadablePerc(exp_bonus), ")"); // generate recipe SimulatedRecipe recipe = new SimulatedRecipe(harvester.part, recipe_name); foreach (ResourceRatio res in harvester.inputList) { recipe.Input(res.ResourceName, res.Ratio); } recipe.Output(harvester.ResourceName, harvester.Efficiency * exp_bonus, true); recipes.Add(recipe); }
void Process_greenhouse(Greenhouse g, EnvironmentAnalyzer env, VesselAnalyzer va) { // skip disabled greenhouses if (!g.active) return; // shortcut to resources SimulatedResource ec = Resource("ElectricCharge"); SimulatedResource res = Resource(g.crop_resource); // calculate natural and artificial lighting double natural = env.solar_flux; double artificial = Math.Max(g.light_tolerance - natural, 0.0); // if lamps are on and artificial lighting is required if (artificial > 0.0) { // consume ec for the lamps ec.Consume(g.ec_rate * (artificial / g.light_tolerance), "greenhouse"); } // execute recipe SimulatedRecipe recipe = new SimulatedRecipe(g.part, "greenhouse"); foreach (ModuleResource input in g.resHandler.inputResources) { // WasteAtmosphere is primary combined input if (g.WACO2 && input.name == "WasteAtmosphere") recipe.Input(input.name, env.breathable ? 0.0 : input.rate, "CarbonDioxide"); // CarbonDioxide is secondary combined input else if (g.WACO2 && input.name == "CarbonDioxide") recipe.Input(input.name, env.breathable ? 0.0 : input.rate, ""); // if atmosphere is breathable disable WasteAtmosphere / CO2 else if (!g.WACO2 && (input.name == "CarbonDioxide" || input.name == "WasteAtmosphere")) recipe.Input(input.name, env.breathable ? 0.0 : input.rate, ""); else recipe.Input(input.name, input.rate); } foreach (ModuleResource output in g.resHandler.outputResources) { // if atmosphere is breathable disable Oxygen if (output.name == "Oxygen") recipe.Output(output.name, env.breathable ? 0.0 : output.rate, true); else recipe.Output(output.name, output.rate, true); } recipes.Add(recipe); // determine environment conditions bool lighting = natural + artificial >= g.light_tolerance; bool pressure = va.pressurized || g.pressure_tolerance <= double.Epsilon; bool radiation = (env.landed ? env.surface_rad : env.magnetopause_rad) * (1.0 - va.shielding) < g.radiation_tolerance; // if all conditions apply // note: we are assuming the inputs are satisfied, we can't really do otherwise here if (lighting && pressure && radiation) { // produce food res.Produce(g.crop_size * g.crop_rate, "greenhouse"); // add harvest info res.harvests.Add(Lib.BuildString(g.crop_size.ToString("F0"), " in ", Lib.HumanReadableDuration(1.0 / g.crop_rate))); } }