private static void ResUpdate(Vessel v, List <ResourceRatio> inputList, string ResourceName, float Efficiency, float systemHeatEfficiency, double abundance, double elapsed_s) { ResourceRecipe recipe = new ResourceRecipe(KERBALISM.ResourceBroker.GetOrCreate( brokerName, KERBALISM.ResourceBroker.BrokerCategory.Harvester, brokerTitle)); foreach (ResourceRatio ir in inputList) { recipe.AddInput(ir.ResourceName, ir.Ratio * elapsed_s); } recipe.AddOutput(ResourceName, Efficiency * systemHeatEfficiency * abundance * elapsed_s, dump: true); KERBALISM.ResourceCache.Get(v).AddRecipe(recipe); }
private static void ResUpdate(Vessel v, List <ResourceRatio> inputList, List <ResourceRatio> outputList, float systemHeatEfficiency, double elapsed_s) { ResourceRecipe recipe = new ResourceRecipe(KERBALISM.ResourceBroker.GetOrCreate(brokerName, KERBALISM.ResourceBroker.BrokerCategory.Converter, brokerTitle)); foreach (ResourceRatio ir in inputList) { recipe.AddInput(ir.ResourceName, ir.Ratio * elapsed_s); } foreach (ResourceRatio or in outputList) { recipe.AddOutput(or.ResourceName, or.Ratio * systemHeatEfficiency * elapsed_s, or.DumpExcess); } KERBALISM.ResourceCache.Get(v).AddRecipe(recipe); }
void Awake() { if (_instance != null && _instance != this) { throw new System.Exception("Multiple GameData instances are present. There should only be one instance of a Singleton."); } else { _instance = this; } // Load Resources nameToResource = new Dictionary <string, InGameResource>(); baseResources = new List <InGameResource>(); using (StringReader reader = new StringReader(resourceFile.text)) { string[] headers = reader.ReadLine().Split(','); string[] expectedHeaders = { "Name", "Is Base" }; CheckFileHeaders("resources", expectedHeaders, headers); while (reader.Peek() != -1) { string[] fields = reader.ReadLine().Split(','); InGameResource resource = new InGameResource(name: fields[0], isBaseResource: bool.Parse(fields[1])); nameToResource[resource.Name] = resource; if (resource.IsBaseResource) { baseResources.Add(resource); } } } // Load Units mainBaseUnitInfo = null; nameToUnitInfo = new Dictionary <string, UnitInfo>(); using (StringReader reader = new StringReader(unitsFile.text)) { string[] headers = reader.ReadLine().Split(','); string[] expectedHeaders = { "Name", "MoveRange", "Health", "CloseDefense", "LongDefense", "CloseAttack", "LongAttack", "AttackRange", "Extra" }; CheckFileHeaders("units", expectedHeaders, headers); while (reader.Peek() != -1) { string[] fields = reader.ReadLine().Split(','); Unit unitPrefab = Resources.Load <Unit>("UnitPrefabs/" + fields[0]); if (unitPrefab == null) { throw new System.Exception("Failed to load unit in Resources/UnitPrefabs: " + fields[0]); } UnitInfo unitInfo = new UnitInfo(name: fields[0], maxMoveRange: int.Parse(fields[1]), health: int.Parse(fields[2]), closeDefense: int.Parse(fields[3]), longDefense: int.Parse(fields[4]), closeAttack: int.Parse(fields[5]), longAttack: int.Parse(fields[6]), attackRange: int.Parse(fields[7]), extra: fields[8], unitPrefab: unitPrefab); nameToUnitInfo[fields[0]] = unitInfo; if (mainBaseUnitInfo != null) { mainBaseUnitInfo = unitInfo; } } } // Load Recipes nameToRecipes = new Dictionary <string, Recipe>(); using (StringReader reader = new StringReader(recipesFile.text)) { string[] headers = reader.ReadLine().Split(','); string[] expectedHeaders = { "Recipe Name", "Output", "Output Quantity", "Max Stack", "Input Item", "Input Quantity" }; CheckFileHeaders("recipes", expectedHeaders, headers); Recipe recipe = null; while (reader.Peek() != -1) { string[] fields = reader.ReadLine().Split(','); // Starting a new recipe if (fields[0] != "") { // recipe will be null in the first iteration if (recipe != null) { RegisterRecipe(recipe); } // Check whether the recipe creates a resource or a unit if (nameToResource.ContainsKey(fields[1])) { recipe = new ResourceRecipe(recipeName: fields[0], outputName: fields[1], outputQuantity: int.Parse(fields[2]), maxStack: int.Parse(fields[3])); } else if (nameToUnitInfo.ContainsKey(fields[1])) { recipe = new UnitRecipe( recipeName: fields[0], outputName: fields[1]); } else { throw new System.Exception($"The provided output {fields[1]} does not exist as a Resource or as a Unit"); } recipe.AddInput(nameToResource[fields[4]], int.Parse(fields[5])); } } RegisterRecipe(recipe); } }
// Simulate resources production/consumption for unloaded vessel public static string BackgroundUpdate(Vessel v, ProtoPartSnapshot part_snapshot, ProtoPartModuleSnapshot module_snapshot, PartModule proto_part_module, Part proto_part, Dictionary <string, double> availableResources, List <KeyValuePair <string, double> > resourceChangeRequest, double elapsed_s) { ProtoPartModuleSnapshot reactor = KSHUtils.FindPartModuleSnapshot(part_snapshot, engineModuleName); if (reactor != null) { if (Lib.Proto.GetBool(reactor, "Enabled") && Lib.Proto.GetBool(module_snapshot, "GeneratesElectricity")) { float curThrottle = Lib.Proto.GetFloat(reactor, "CurrentReactorThrottle") / 100f; float minThrottle = Lib.Proto.GetFloat(module_snapshot, "MinThrottle"); float maxThrottle = Lib.Proto.GetFloat(module_snapshot, "MaxThrottle"); float maxECGeneration = Lib.Proto.GetFloat(module_snapshot, "MaxECGeneration"); bool needToStopReactor = false; if (maxECGeneration > 0) { VesselResources resources = KERBALISM.ResourceCache.Get(v); if (!(proto_part_module as SystemHeatFissionEngineKerbalismUpdater).resourcesListParsed) { (proto_part_module as SystemHeatFissionEngineKerbalismUpdater).ParseResourcesList(proto_part); } // Mininum reactor throttle // Some input/output resources will always be consumed/produced as long as minThrottle > 0 if (minThrottle > 0) { ResourceRecipe recipe = new ResourceRecipe(KERBALISM.ResourceBroker.GetOrCreate( brokerName, KERBALISM.ResourceBroker.BrokerCategory.Converter, brokerTitle)); foreach (ResourceRatio ir in (proto_part_module as SystemHeatFissionEngineKerbalismUpdater).inputs) { recipe.AddInput(ir.ResourceName, ir.Ratio * minThrottle * elapsed_s); if (resources.GetResource(v, ir.ResourceName).Amount < double.Epsilon) { // Input resource amount is zero - stop reactor needToStopReactor = true; } } foreach (ResourceRatio or in (proto_part_module as SystemHeatFissionEngineKerbalismUpdater).outputs) { recipe.AddOutput(or.ResourceName, or.Ratio * minThrottle * elapsed_s, dump: false); if (1 - resources.GetResource(v, or.ResourceName).Level < double.Epsilon) { // Output resource is at full capacity needToStopReactor = true; Message.Post( Severity.warning, Localizer.Format( "#LOC_KerbalismSystemHeat_ReactorOutputResourceFull", or.ResourceName, v.GetDisplayName(), part_snapshot.partName) ); } } recipe.AddOutput("ElectricCharge", minThrottle * maxECGeneration * elapsed_s, dump: true); resources.AddRecipe(recipe); } if (!needToStopReactor) { if (!Lib.Proto.GetBool(reactor, "ManualControl")) { // Automatic reactor throttle mode curThrottle = maxThrottle; } curThrottle -= minThrottle; if (curThrottle > 0) { ResourceRecipe recipe = new ResourceRecipe(KERBALISM.ResourceBroker.GetOrCreate( brokerName, KERBALISM.ResourceBroker.BrokerCategory.Converter, brokerTitle)); foreach (ResourceRatio ir in (proto_part_module as SystemHeatFissionEngineKerbalismUpdater).inputs) { recipe.AddInput(ir.ResourceName, ir.Ratio * curThrottle * elapsed_s); if (resources.GetResource(v, ir.ResourceName).Amount < double.Epsilon) { // Input resource amount is zero - stop reactor needToStopReactor = true; } } foreach (ResourceRatio or in (proto_part_module as SystemHeatFissionEngineKerbalismUpdater).outputs) { recipe.AddOutput(or.ResourceName, or.Ratio * curThrottle * elapsed_s, dump: false); if (1 - resources.GetResource(v, or.ResourceName).Level < double.Epsilon) { // Output resource is at full capacity needToStopReactor = true; Message.Post( Severity.warning, Localizer.Format( "#LOC_KerbalismSystemHeat_ReactorOutputResourceFull", or.ResourceName, v.GetDisplayName(), part_snapshot.partName) ); } } recipe.AddOutput("ElectricCharge", curThrottle * maxECGeneration * elapsed_s, dump: false); resources.AddRecipe(recipe); } } } // Disable reactor if (needToStopReactor) { Lib.Proto.Set(reactor, "Enabled", false); } } else { // Reactor disabled - radiation decay mechanics if (Features.Radiation && Lib.Proto.GetBool(module_snapshot, "ReactorHasStarted") && Lib.Proto.GetDouble(module_snapshot, "ReactorStoppedTimestamp") > 0 && Lib.Proto.GetDouble(module_snapshot, "MinEmissionPercent") < 100) { ProtoPartModuleSnapshot emitter = KSHUtils.FindPartModuleSnapshot(part_snapshot, "Emitter"); if (emitter != null) { double EmitterMaxRadiation = Lib.Proto.GetDouble(module_snapshot, "EmitterMaxRadiation"); double MinEmissionPercent = Lib.Proto.GetDouble(module_snapshot, "MinEmissionPercent"); double EmissionDecayRate = Lib.Proto.GetDouble(module_snapshot, "EmissionDecayRate"); double MinRadiation = EmitterMaxRadiation * MinEmissionPercent / 100; if (EmissionDecayRate <= 0) { Lib.Proto.Set(emitter, "radiation", MinRadiation); Lib.Proto.Set(module_snapshot, "ReactorStoppedTimestamp", 0d); } else { double secondsPassed = Planetarium.GetUniversalTime() - Lib.Proto.GetDouble(module_snapshot, "ReactorStoppedTimestamp"); if (secondsPassed > 0) { double NewRadiation = EmitterMaxRadiation * (100 - secondsPassed / EmissionDecayRate) / 100; if (NewRadiation <= MinRadiation) { NewRadiation = MinRadiation; Lib.Proto.Set(module_snapshot, "ReactorStoppedTimestamp", 0d); } Lib.Proto.Set(emitter, "radiation", NewRadiation); } } } } } // Prevent resource consumption in ModuleSystemHeatFissionReactor.DoCatchup() // by setting LastUpdate to current time Lib.Proto.Set(reactor, "LastUpdateTime", Planetarium.GetUniversalTime()); return(brokerTitle); } return("ERR: no engine"); }