private void UpdateAtmosphereBuffer() { if (intakeOpen && resourceBuffers != null) { resourceBuffers.UpdateBuffers(); } }
private void UpdateAtmosphereBuffer() { if (intakeOpen) { resourceBuffers?.UpdateBuffers(); } }
public override void OnFixedUpdateResourceSuppliable(double fixedDeltaTime) { if (_moduleGenerator == null) { return; } if (_outputType == ResourceType.other) { return; } var generatorRate = _moduleOutputResource.rate; _mockInputResource.rate = generatorRate; double generatorSupply = _outputType == ResourceType.megajoule ? generatorRate : generatorRate / GameConstants.ecPerMJ; if (maintainsBuffer) { _resourceBuffers.UpdateBuffers(); } megaJouleGeneratorPowerSupply = supplyFNResourcePerSecondWithMax(generatorSupply, generatorSupply, ResourceSettings.Config.ElectricPowerInMegawatt); }
public override void OnFixedUpdate() // OnFixedUpdate is only called when (force) activated { _resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, this.part.mass); _resourceBuffers.UpdateBuffers(); var wasteheatResource = part.Resources["WasteHeat"]; }
public override void OnFixedUpdateResourceSuppliable(double fixedDeltaTime) { try { if (moduleGenerator == null) { return; } if (outputType == resourceType.other) { return; } double generatorRate = moduleOutputResource.rate; mockInputResource.rate = generatorRate; double generatorSupply = outputType == resourceType.megajoule ? generatorRate : generatorRate / 1000; resourceBuffers.UpdateBuffers(); megaJouleGeneratorPowerSupply = supplyFNResourcePerSecondWithMax(generatorSupply, generatorSupply, ResourceManager.FNRESOURCE_MEGAJOULES); } catch (Exception e) { Debug.LogError("[KSPI] - Exception in FNGeneratorAdapter.OnFixedUpdateResourceSuppliable " + e.Message); throw; } }
private void UpdateElectricChargeBuffer(double currentPowerUsage) { if (resourceBuffers == null) { return; } resourceBuffers.UpdateVariable(ResourceSettings.Config.ElectricPowerInKilowatt, currentPowerUsage); resourceBuffers.UpdateBuffers(); }
private void UpdateElectricChargeBuffer(double currentPowerUsage) { if (resourceBuffers == null) { return; } resourceBuffers.UpdateVariable(InterstellarResourcesConfiguration.Instance.ElectricCharge, currentPowerUsage); resourceBuffers.UpdateBuffers(); }
public override void OnFixedUpdate() { base.OnFixedUpdate(); resourceBuffers.UpdateVariable("Megajoules", currentPowerSupply); resourceBuffers.UpdateVariable("ElectricCharge", currentPowerSupply); resourceBuffers.UpdateBuffers(); currentPowerSupply = 0; }
public override void OnFixedUpdate() { base.OnFixedUpdate(); resourceBuffers.UpdateVariable(ResourceSettings.Config.ElectricPowerInMegawatt, currentPowerSupply); resourceBuffers.UpdateVariable(ResourceSettings.Config.ElectricPowerInKilowatt, currentPowerSupply); resourceBuffers.UpdateBuffers(); currentPowerSupply = 0; }
public override void OnFixedUpdateResourceSuppliable(double fixedDeltaTime) { try { if (microwavePowerReceiver != null) { return; } if (solarPanel == null) { return; } if (outputType == resourceType.other) { return; } // readout kerbalism solar power output so we use it if (_field_kerbalism_output != null) { // if GUI is inactive, then Panel doesn't produce power since Kerbalism doesn't reset the value on occlusion // to be fixed in Kerbalism! kerbalismPowerOutput = _field_kerbalism_output.guiActive == true?_field_kerbalism_output.GetValue <double>(warpfixer) : 0; } // solarPanel.resHandler.outputResource[0].rate is zeroed by Kerbalism, flowRate is bogus. // So we need to assume that Kerbalism Power Output is ok (if present), // since calculating output from flowRate (or _flowRate) will not be possible. double solar_rate = kerbalismPowerOutput > 0 ? kerbalismPowerOutput : solarPanel.flowRate > 0 ? solarPanel.flowRate : solarPanel.panelType == ModuleDeployableSolarPanel.PanelType.FLAT ? solarPanel._flowRate : solarPanel._flowRate * solarPanel.chargeRate; double maxSupply = solarPanel._distMult > 0 ? solarPanel.chargeRate * solarPanel._distMult * solarPanel._efficMult : solar_rate; resourceBuffers.UpdateBuffers(); // extract power otherwise we end up with double power // TODO MISSING IMPLEMENTATION solar_supply = outputType == resourceType.megajoule ? solar_rate : solar_rate / 1000; solar_maxSupply = outputType == resourceType.megajoule ? maxSupply : maxSupply / 1000; megaJouleSolarPowerSupply = supplyFNResourcePerSecondWithMax(solar_supply, solar_maxSupply, ResourceManager.FNRESOURCE_MEGAJOULES); } catch (Exception e) { Debug.LogError("[KSPI] - Exception in FNSolarPanelWasteHeatModule.OnFixedUpdateResourceSuppliable " + e.Message); throw; } }
public override void OnFixedUpdateResourceSuppliable(double fixedDeltaTime) { if (_solarPanel == null) { return; } if (_outputType == ResourceType.other) { return; } flowRate = _solarPanel.flowRate; chargeRate = _solarPanel.chargeRate; efficiencyMult = _solarPanel.efficiencyMult; _efficMult = _solarPanel._efficMult; calculatedEfficency = _solarPanel._efficMult > 0 ? _solarPanel._efficMult : (double)(decimal)_solarPanel.temperatureEfficCurve.Evaluate((Single)part.skinTemperature) * (double)(decimal)_solarPanel.timeEfficCurve.Evaluate((Single)((Planetarium.GetUniversalTime() - _solarPanel.launchUT) * 1.15740740740741E-05)) * (double)(decimal)_solarPanel.efficiencyMult; double maxSupply = 0; double solarRate = 0; sunAOA = 0; CalculateSolarFlowRate(calculatedEfficency / scale, ref maxSupply, ref solarRate); if (_resourceBuffers != null) { _resourceBuffers.UpdateBuffers(); } // extract power otherwise we end up with double power if (flowRate > 0 && solarRate > 0) { part.RequestResource(_solarPanel.resourceName, flowRate * fixedDeltaTime); } else { part.RequestResource(_solarPanel.resourceName, solarRate * fixedDeltaTime); } // provide power to supply manager solar_supply = _outputType == ResourceType.megajoule ? solarRate : solarRate * 0.001; solarMaxSupply = _outputType == ResourceType.megajoule ? maxSupply : maxSupply * 0.001; megaJouleSolarPowerSupply = supplyFNResourcePerSecondWithMax(solar_supply, solarMaxSupply, ResourceManager.FNRESOURCE_MEGAJOULES); }
public override void OnFixedUpdateResourceSuppliable(double fixedDeltaTime) { try { if (moduleGenerator == null) { return; } if (_field_status == null) { return; } if (_field_generated == null) { return; } bool status = _field_status.GetValue <bool>(moduleGenerator); float generatorRate = status ? _field_generated.GetValue <float>(moduleGenerator) : 0; float generatorMax = _field_max.GetValue <float>(moduleGenerator); // extract power otherwise we end up with double power if (_field_addedToTanks != null) { part.RequestResource(ResourceManager.STOCK_RESOURCE_ELECTRICCHARGE, _field_addedToTanks.GetValue <float>(moduleGenerator)); } resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, this.part.mass); resourceBuffers.UpdateBuffers(); megaJouleGeneratorPowerSupply = supplyFNResourcePerSecondWithMax(generatorRate / 1000, generatorMax / 1000, ResourceManager.FNRESOURCE_MEGAJOULES); if (!CheatOptions.IgnoreMaxTemperature) { supplyFNResourcePerSecond(generatorRate / 10000.0d, ResourceManager.FNRESOURCE_WASTEHEAT); } } catch (Exception e) { Debug.LogError("[KSPI] - Exception in FNFissionGeneratorAdapter.OnFixedUpdateResourceSuppliable " + e.Message); throw; } }
public override void OnFixedUpdateResourceSuppliable(double fixedDeltaTime) { if (_moduleGenerator == null || _fieldStatus == null || _fieldGenerated == null) { return; } bool status = _fieldStatus.GetValue <bool>(_moduleGenerator); float generatorRate = status ? _fieldGenerated.GetValue <float>(_moduleGenerator) : 0; float generatorMax = _fieldMax.GetValue <float>(_moduleGenerator); float generatorEfficiency = _fieldEfficiency.GetValue <float>(_moduleGenerator); efficiency = generatorEfficiency.ToString("P2"); //extract power otherwise we end up with double power part.RequestResource(ResourceSettings.Config.ElectricPowerInKilowatt, generatorRate * fixedDeltaTime); double megajoulesRate = generatorRate / GameConstants.ecPerMJ; double maxMegajoulesRate = generatorMax / GameConstants.ecPerMJ; _resourceBuffers.UpdateVariable(ResourceSettings.Config.ElectricPowerInMegawatt, megajoulesRate); _resourceBuffers.UpdateVariable(ResourceSettings.Config.WasteHeatInMegawatt, part.mass); _resourceBuffers.UpdateBuffers(); megaJouleGeneratorPowerSupply = supplyFNResourcePerSecondWithMax(megajoulesRate, maxMegajoulesRate, ResourceSettings.Config.ElectricPowerInMegawatt); if (CheatOptions.IgnoreMaxTemperature) { return; } double maxWasteheat = generatorEfficiency > 0.0 ? maxMegajoulesRate * (1.0 / generatorEfficiency - 1.0) : maxMegajoulesRate; double throttledWasteheat = generatorEfficiency > 0.0 ? megajoulesRate * (1.0 / generatorEfficiency - 1.0) : megajoulesRate; supplyFNResourcePerSecondWithMax(throttledWasteheat, maxWasteheat, ResourceSettings.Config.WasteHeatInMegawatt); }
public override void OnFixedUpdate() { temperatureStr = part.temperature.ToString("0.00") + "K / " + part.maxTemp.ToString("0.00") + "K"; MinIsp = BaseFloatCurve.Evaluate((float)Altitude); resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, this.part.mass); resourceBuffers.UpdateBuffers(); if (curEngineT == null || !curEngineT.isEnabled) { return; } throttle = curEngineT.currentThrottle > MinThrottleRatio ? curEngineT.currentThrottle : 0; if (throttle > 0) { if (maxAtmosphereDensity >= 0 && vessel.atmDensity > maxAtmosphereDensity) { ShutDown("Inertial Fusion cannot operate in atmosphere!"); } if (radhazard && rad_safety_features) { ShutDown("Engines throttled down as they presently pose a radiation hazard"); } if (SelectedIsp <= 10) { ShutDown("Engine Stall"); } } KillKerbalsWithRadiation(fusionRatio); hasIspThrottling = HasIspThrottling(); ShowIspThrottle = hasIspThrottling; availablePower = Math.Max(getResourceAvailability(ResourceManager.FNRESOURCE_MEGAJOULES), getAvailablePrioritisedStableSupply(ResourceManager.FNRESOURCE_MEGAJOULES)); if (throttle > 0) { var requestedPowerPerSecond = throttle * CurrentMaximumPowerRequirement; //var resourceBarRatio = getResourceBarRatio(ResourceManager.FNRESOURCE_MEGAJOULES); //var effectivePowerThrotling = useMegajouleBattery ? 1 : resourceBarRatio > 0.1 ? 1 : resourceBarRatio * 10; var requestedPower = Math.Min(requestedPowerPerSecond, availablePower); var recievedPowerPerSecond = requestedPower <= 0 ? 0 : CheatOptions.InfiniteElectricity ? requestedPowerPerSecond : consumeFNResourcePerSecond(requestedPower, ResourceManager.FNRESOURCE_MEGAJOULES); fusionRatio = requestedPowerPerSecond > 0 ? recievedPowerPerSecond / requestedPowerPerSecond : 1; laserWasteheat = recievedPowerPerSecond * (1 - LaserEfficiency); // Lasers produce Wasteheat if (!CheatOptions.IgnoreMaxTemperature && laserWasteheat > 0) { supplyFNResourcePerSecond(laserWasteheat, ResourceManager.FNRESOURCE_WASTEHEAT); } // The Aborbed wasteheat from Fusion rateMultplier = hasIspThrottling ? Math.Pow(SelectedIsp / MinIsp, 2) : 1; neutronbsorbionBonus = hasIspThrottling ? 1 - NeutronAbsorptionFractionAtMinIsp * (1 - ((SelectedIsp - MinIsp) / (MaxIsp - MinIsp))) : 0.5; absorbedWasteheat = FusionWasteHeat * wasteHeatMultiplier * fusionRatio * throttle * neutronbsorbionBonus; supplyFNResourcePerSecond(absorbedWasteheat, ResourceManager.FNRESOURCE_WASTEHEAT); SetRatios(); currentIsp = hasIspThrottling ? SelectedIsp : MinIsp; UpdateAtmosphereCurve(currentIsp); maximumThrust = hasIspThrottling ? MaximumThrust : FullTrustMaximum; // Update FuelFlow maxFuelFlow = fusionRatio * maximumThrust / currentIsp / GameConstants.STANDARD_GRAVITY; curEngineT.maxFuelFlow = (float)maxFuelFlow; curEngineT.maxThrust = (float)maximumThrust; if (!curEngineT.getFlameoutState && fusionRatio < 0.9 && recievedPowerPerSecond > 0) { curEngineT.status = "Insufficient Electricity"; } } else { enginePowerRequirement = 0; absorbedWasteheat = 0; laserWasteheat = 0; var requestedPowerPerSecond = CurrentMaximumPowerRequirement; fusionRatio = requestedPowerPerSecond > 0 ? availablePower / requestedPowerPerSecond : 1; currentIsp = hasIspThrottling ? SelectedIsp : MinIsp; maximumThrust = hasIspThrottling ? MaximumThrust : FullTrustMaximum; UpdateAtmosphereCurve(currentIsp); curEngineT.maxThrust = (float)maximumThrust; rateMultplier = hasIspThrottling ? Math.Pow(SelectedIsp / MinIsp, 2) : 1; maxFuelFlow = fusionRatio * maximumThrust / currentIsp / GameConstants.STANDARD_GRAVITY; curEngineT.maxFuelFlow = (float)maxFuelFlow; SetRatios(); } coldBathTemp = FNRadiator.getAverageRadiatorTemperatureForVessel(vessel); maxTempatureRadiators = FNRadiator.getAverageMaximumRadiatorTemperatureForVessel(vessel); radiatorPerformance = Math.Max(1 - (coldBathTemp / maxTempatureRadiators), 0.000001); partEmissiveConstant = part.emissiveConstant; base.OnFixedUpdate(); }
// FixedUpdate is also called in the Editor public void FixedUpdate() { if (HighLogic.LoadedSceneIsEditor) { return; } if (_attached_engine == null) { return; } if (_attached_reactor != null && _attached_reactor.ChargedParticlePropulsionEfficiency > 0) { if (_attached_reactor.Part != this.part) { resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, this.part.mass); resourceBuffers.UpdateBuffers(); } _max_charged_particles_power = _attached_reactor.MaximumChargedPower * exchanger_thrust_divisor * _attached_reactor.ChargedParticlePropulsionEfficiency; _charged_particles_requested = _attached_engine.isOperational && _attached_engine.currentThrottle > 0 ? _max_charged_particles_power : 0; _charged_particles_received = consumeFNResourcePerSecond(_charged_particles_requested, ResourceManager.FNRESOURCE_CHARGED_PARTICLES); // convert reactor product into propellants when possible var chargedParticleRatio = _attached_reactor.MaximumChargedPower > 0 ? _charged_particles_received / _attached_reactor.MaximumChargedPower : 0; // update Isp var currentIsp = !_attached_engine.isOperational || _attached_engine.currentThrottle == 0 ? maximum_isp : Math.Min(maximum_isp, minimum_isp / Math.Pow(_attached_engine.currentThrottle, throtleExponent)); var powerThrustModifier = GameConstants.BaseThrustPowerMultiplier * powerThrustMultiplier; var max_engine_thrust_at_max_isp = powerThrustModifier * _charged_particles_received / maximum_isp / GameConstants.STANDARD_GRAVITY; var calculatedConsumptionInTon = max_engine_thrust_at_max_isp / maximum_isp / GameConstants.STANDARD_GRAVITY; // generate addition propellant from reactor fuel consumption _attached_reactor.UseProductForPropulsion(chargedParticleRatio, calculatedConsumptionInTon); calculatedConsumptionPerSecond = calculatedConsumptionInTon * 1000; if (!CheatOptions.IgnoreMaxTemperature) { if (_attached_engine.isOperational && _attached_engine.currentThrottle > 0) { consumeFNResourcePerSecond(_charged_particles_received, ResourceManager.FNRESOURCE_WASTEHEAT); _previous_charged_particles_received = _charged_particles_received; } else if (_previous_charged_particles_received > 0) { consumeFNResourcePerSecond(_previous_charged_particles_received, ResourceManager.FNRESOURCE_WASTEHEAT); _previous_charged_particles_received = 0; } else { _charged_particles_received = 0; _previous_charged_particles_received = 0; } } // calculate power cost var ispPowerCostMultiplier = 1 + max_power_multiplier - Math.Log10(currentIsp / minimum_isp); var minimumEnginePower = _attached_reactor.MagneticNozzlePowerMult * _charged_particles_received * ispPowerCostMultiplier * 0.005 * Math.Max(_attached_reactor_distance, 1); var neededBufferPower = Math.Min(Math.Max(powerBufferMax - powerBufferStore, 0), minimumEnginePower); _requestedElectricPower = minimumEnginePower + neededBufferPower; _recievedElectricPower = CheatOptions.InfiniteElectricity ? _requestedElectricPower : consumeFNResourcePerSecond(_requestedElectricPower, ResourceManager.FNRESOURCE_MEGAJOULES); // adjust power buffer var powerSurplus = _recievedElectricPower - minimumEnginePower; if (powerSurplus < 0) { var powerFromBuffer = Math.Min(-powerSurplus, powerBufferStore); _recievedElectricPower += powerFromBuffer; powerBufferStore -= powerFromBuffer; } else { powerBufferStore += powerSurplus; } // calculate Power factor megajoulesRatio = Math.Min(_recievedElectricPower / minimumEnginePower, 1); megajoulesRatio = (double.IsNaN(megajoulesRatio) || double.IsInfinity(megajoulesRatio)) ? 0 : megajoulesRatio; var scaledPowerFactor = Math.Pow(megajoulesRatio, 0.5); double atmoIspFactor = 1; _engineMaxThrust = 0; if (_max_charged_particles_power > 0) { var enginethrust_from_recieved_particles = powerThrustModifier * _charged_particles_received * scaledPowerFactor / currentIsp / GameConstants.STANDARD_GRAVITY; var effective_thrust = Math.Max(enginethrust_from_recieved_particles - (radius * radius * vessel.atmDensity * 100), 0); var max_theoretical_thrust = powerThrustModifier * _max_charged_particles_power / currentIsp / GameConstants.STANDARD_GRAVITY; atmoIspFactor = max_theoretical_thrust > 0 ? effective_thrust / max_theoretical_thrust : 0; _engineMaxThrust = _attached_engine.currentThrottle > 0 ? Math.Max(effective_thrust, 0.000000001) : Math.Max(max_theoretical_thrust, 0.000000001); } // set isp FloatCurve newAtmosphereCurve = new FloatCurve(); newAtmosphereCurve.Add(0, (float)(currentIsp * scaledPowerFactor * atmoIspFactor), 0, 0); _attached_engine.atmosphereCurve = newAtmosphereCurve; var max_fuel_flow_rate = !double.IsInfinity(_engineMaxThrust) && !double.IsNaN(_engineMaxThrust) && currentIsp > 0 ? _engineMaxThrust / currentIsp / GameConstants.STANDARD_GRAVITY / (_attached_engine.currentThrottle > 0 ? _attached_engine.currentThrottle : 1) : 0; // set maximum flow _attached_engine.maxFuelFlow = Math.Max((float)max_fuel_flow_rate, 0.0000000001f); _attached_engine.useThrustCurve = false; // This whole thing may be inefficient, but it should clear up some confusion for people. if (_attached_engine.getFlameoutState) { return; } if (_attached_engine.currentThrottle < 0.99) { _attached_engine.status = "offline"; } else if (megajoulesRatio < 0.75 && _requestedElectricPower > 0) { _attached_engine.status = "Insufficient Electricity"; } else if (atmoIspFactor < 0.01) { _attached_engine.status = "Too dense atmospherere"; } } else { _attached_engine.maxFuelFlow = 0.0000000001f; _recievedElectricPower = 0; _charged_particles_requested = 0; _charged_particles_received = 0; _engineMaxThrust = 0; } }
// ReSharper disable once UnusedMember.Global public void FixedUpdate() { if (_initializationCountdown > 0) { _initializationCountdown--; } if (!HighLogic.LoadedSceneIsFlight) { return; } CalculateTimeDialation(); if (_attachedEngine == null) { return; } if (_attachedEngine is ModuleEnginesFX) { GetAllPropellants().ForEach(prop => part.Effect(prop.ParticleFXName, 0, -1)); // set all FX to zero } if (Current_propellant == null) { return; } resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, this.part.mass); resourceBuffers.UpdateBuffers(); if (!this.vessel.packed && !_warpToReal) { storedThrotle = vessel.ctrlState.mainThrottle; } // retrieve power maxEffectivePower = MaxEffectivePower; var sumOfAllEffectivePower = vessel.FindPartModulesImplementing <ElectricEngineControllerFX>().Where(ee => ee.IsOperational).Sum(ee => ee.MaxEffectivePower); _electrical_share_f = sumOfAllEffectivePower > 0 ? maxEffectivePower / sumOfAllEffectivePower : 1; maxThrottlePower = maxEffectivePower * ModifiedThrotte; var currentPropellantEfficiency = CurrentPropellantEfficiency; if (CheatOptions.InfiniteElectricity) { power_request = maxThrottlePower; } else { var availablePower = Math.Max(getStableResourceSupply(ResourceManager.FNRESOURCE_MEGAJOULES) - getCurrentHighPriorityResourceDemand(ResourceManager.FNRESOURCE_MEGAJOULES), 0); var megaJoulesBarRatio = getResourceBarRatio(ResourceManager.FNRESOURCE_MEGAJOULES); var effectiveResourceThrotling = megaJoulesBarRatio > OneThird ? 1 : megaJoulesBarRatio * 3; var powerPerEngine = effectiveResourceThrotling * ModifiedThrotte * EvaluateMaxThrust(availablePower * _electrical_share_f) * CurrentIspMultiplier * _modifiedEngineBaseIsp / GetPowerThrustModifier() * PluginHelper.GravityConstant; power_request = currentPropellantEfficiency <= 0 ? 0 : Math.Min(powerPerEngine / currentPropellantEfficiency, maxThrottlePower); } var powerReceived = CheatOptions.InfiniteElectricity ? power_request : consumeFNResourcePerSecond(power_request, ResourceManager.FNRESOURCE_MEGAJOULES); // produce waste heat var heatToProduce = powerReceived * (1 - currentPropellantEfficiency) * Current_propellant.WasteHeatMultiplier; var heatProduction = CheatOptions.IgnoreMaxTemperature ? heatToProduce : supplyFNResourcePerSecond(heatToProduce, ResourceManager.FNRESOURCE_WASTEHEAT); // update GUI Values _electrical_consumption_f = powerReceived; _heat_production_f = heatProduction; var effectiveIsp = _modifiedCurrentPropellantIspMultiplier * _modifiedEngineBaseIsp * ThrottleModifiedIsp(); var maxThrustInSpace = timeDilation * timeDilation * currentPropellantEfficiency * CurrentPropellantThrustMultiplier * ModifiedThrotte * GetPowerThrustModifier() * powerReceived / (effectiveIsp * PluginHelper.GravityConstant); _maxIsp = _modifiedEngineBaseIsp * _modifiedCurrentPropellantIspMultiplier * CurrentPropellantThrustMultiplier * ThrottleModifiedIsp(); _maxFuelFlowRate = _maxIsp <= 0 ? 0 : maxThrustInSpace / _maxIsp / PluginHelper.GravityConstant; var maxThrustWithCurrentThrottle = maxThrustInSpace * ModifiedThrotte; throtle_max_thrust = Current_propellant.SupportedEngines == 8 ? maxThrustWithCurrentThrottle : Math.Max(maxThrustWithCurrentThrottle - (exitArea * FlightGlobals.getStaticPressure(vessel.transform.position)), 0); var throttle = _attachedEngine.currentThrottle > 0 ? Mathf.Max(_attachedEngine.currentThrottle, 0.01f) : 0; //if (ModifiedThrotte > 0) if (throttle > 0 && !this.vessel.packed) { if (IsValidPositiveNumber(throtle_max_thrust) && IsValidPositiveNumber(maxThrustWithCurrentThrottle)) { UpdateIsp(throtle_max_thrust / maxThrustWithCurrentThrottle); _attachedEngine.maxFuelFlow = (float)Math.Max(_maxFuelFlowRate * (ModifiedThrotte / _attachedEngine.currentThrottle), 0.0000000001); } else { UpdateIsp(0.000001); _attachedEngine.maxFuelFlow = 0.0000000001f; } if (_attachedEngine is ModuleEnginesFX) { this.part.Effect(Current_propellant.ParticleFXName, Mathf.Min((float)Math.Pow(_electrical_consumption_f / maxEffectivePower, 0.5), _attachedEngine.finalThrust / _attachedEngine.maxThrust), -1); } } else if (this.vessel.packed && _attachedEngine.enabled && FlightGlobals.ActiveVessel == vessel && throttle > 0 && _initializationCountdown == 0) { _warpToReal = true; // Set to true for transition to realtime PersistantThrust(TimeWarp.fixedDeltaTime, Planetarium.GetUniversalTime(), this.part.transform.up, this.vessel.totalMass); } else { throtle_max_thrust = 0; var projected_max_thrust = Math.Max(maxThrustInSpace - (exitArea * FlightGlobals.getStaticPressure(vessel.transform.position)), 0); if (IsValidPositiveNumber(projected_max_thrust) && IsValidPositiveNumber(maxThrustInSpace)) { UpdateIsp(projected_max_thrust / maxThrustInSpace); _attachedEngine.maxFuelFlow = (float)Math.Max(_maxFuelFlowRate, 0.0000000001); } else { UpdateIsp(1); _attachedEngine.maxFuelFlow = 0.0000000001f; } if (_attachedEngine is ModuleEnginesFX) { this.part.Effect(Current_propellant.ParticleFXName, 0, -1); } } var vacuumPlasmaResource = part.Resources[InterstellarResourcesConfiguration.Instance.VacuumPlasma]; if (isupgraded && vacuumPlasmaResource != null) { var calculatedConsumptionInTon = this.vessel.packed ? 0 : maxThrustInSpace / engineIsp / PluginHelper.GravityConstant; vacuumPlasmaResource.maxAmount = Math.Max(0.0000001, calculatedConsumptionInTon * 200 * TimeWarp.fixedDeltaTime); part.RequestResource(InterstellarResourcesConfiguration.Instance.VacuumPlasma, -vacuumPlasmaResource.maxAmount); } }
public override void OnFixedUpdateResourceSuppliable(double fixedDeltaTime) { try { last_active_time = Planetarium.GetUniversalTime(); powerGeneratorPowerOutput = 0; powerGeneratorPowerInput = 0; if (moduleGenerator == null) { return; } if (outputType == ResourceType.other) { return; } if (!moduleGenerator.generatorIsActive && !moduleGenerator.isAlwaysActive) { mockInputResource.rate = 0; supplyFNResourcePerSecondWithMax(0, 0, ResourceManager.FNRESOURCE_MEGAJOULES); return; } if (maintainsBuffer) { resourceBuffers.UpdateBuffers(); } if (maximumPowerGeneration != 0) { currentMegajoulesDemand = Math.Max(0, GetCurrentUnfilledResourceDemand(ResourceManager.FNRESOURCE_MEGAJOULES)); currentMegajoulesSupply = Math.Min(currentMegajoulesDemand, maximumPowerGeneration); } if (moduleInputResource != null) { if (currentMegajoulesSupply > 0) { moduleInputResource.rate = currentMegajoulesSupply; } else { moduleInputResource.rate = initialInputAmount; } part.GetConnectedResourceTotals(moduleInputResource.id, out inputAmount, out inputMaxAmount); var availableRatio = Math.Min(1, inputAmount / (moduleInputResource.rate * fixedDeltaTime)); currentMegajoulesSupply *= availableRatio; moduleInputResource.rate *= availableRatio; generatorInputRate = moduleInputResource.rate; powerGeneratorPowerInput = inputType == ResourceType.megajoule ? generatorInputRate : generatorInputRate / 1000; } if (moduleOutputResource != null) { generatorOutputRateInElectricCharge = maximumPowerGeneration > 0 ? currentMegajoulesSupply * (outputType == ResourceType.megajoule ? 1 : 1000) : initialOutputAmount; if (maximumPowerGeneration > 0) { moduleOutputResource.rate = 1 + generatorOutputRateInElectricCharge; } else { moduleOutputResource.rate = 1 + generatorOutputRateInElectricCharge; } mockInputResource.rate = generatorOutputRateInElectricCharge; double generatorSupplyInMegajoules = outputType == ResourceType.megajoule ? generatorOutputRateInElectricCharge : generatorOutputRateInElectricCharge / 1000; powerGeneratorPowerOutput = supplyFNResourcePerSecondWithMax(generatorSupplyInMegajoules, generatorSupplyInMegajoules, ResourceManager.FNRESOURCE_MEGAJOULES); } } catch (Exception e) { Debug.LogError("[KSPI]: Exception in FNGeneratorAdapter.OnFixedUpdateResourceSuppliable " + e.Message); throw; } }
public void FixedUpdate() // FixedUpdate is also called when not activated { try { if (!HighLogic.LoadedSceneIsFlight) { return; } if (!active) { base.OnFixedUpdate(); } resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, this.part.mass); resourceBuffers.UpdateBuffers(); // get resource bar ratio at start of frame wasteheatManager = getManagerForVessel(ResourceManager.FNRESOURCE_WASTEHEAT); wasteheatRatio = wasteheatManager.ResourceBarRatioBegin; if (Double.IsNaN(wasteheatRatio)) { Debug.LogError("FNRadiator: FixedUpdate Single.IsNaN detected in wasteheatRatio"); return; } radiator_temperature_temp_val = external_temperature + Math.Min(temperatureDifferenceMaximumWithExternal * Math.Sqrt(wasteheatRatio), temperatureDifferenceCurrentWithExternal); var deltaTemp = Math.Max(radiator_temperature_temp_val - Math.Max(external_temperature * normalizedAtmosphere, 2.7), 0); var deltaTempToPowerFour = deltaTemp * deltaTemp * deltaTemp * deltaTemp; if (radiatorIsEnabled) { if (!CheatOptions.IgnoreMaxTemperature && wasteheatRatio >= 1 && CurrentRadiatorTemperature >= maxRadiatorTemperature) { explode_counter++; if (explode_counter > 25) { part.explode(); } } else { explode_counter = 0; } var efficiency = CalculateEfficiency(); thermalPowerDissipPerSecond = efficiency * deltaTempToPowerFour * GameConstants.stefan_const * effectiveRadiatorArea / 1e6; if (Double.IsNaN(thermalPowerDissipPerSecond)) { Debug.LogWarning("FNRadiator: FixedUpdate Single.IsNaN detected in fixed_thermal_power_dissip"); } radiatedThermalPower = canRadiateHeat ? consumeWasteHeatPerSecond(thermalPowerDissipPerSecond) : 0; if (Double.IsNaN(radiatedThermalPower)) { Debug.LogError("FNRadiator: FixedUpdate Single.IsNaN detected in radiatedThermalPower after call consumeWasteHeat (" + thermalPowerDissipPerSecond + ")"); } instantaneous_rad_temp = CalculateInstantaniousRadTemp(); CurrentRadiatorTemperature = instantaneous_rad_temp; if (_moduleDeployableRadiator) { _moduleDeployableRadiator.hasPivot = pivotEnabled; } } else { var efficiency = CalculateEfficiency(); thermalPowerDissipPerSecond = efficiency * deltaTempToPowerFour * GameConstants.stefan_const * effectiveRadiatorArea / 0.5e7; radiatedThermalPower = canRadiateHeat ? consumeWasteHeatPerSecond(thermalPowerDissipPerSecond) : 0; instantaneous_rad_temp = CalculateInstantaniousRadTemp(); CurrentRadiatorTemperature = instantaneous_rad_temp; } if (vessel.atmDensity > 0) { dynamic_pressure = 0.60205 * vessel.atmDensity * vessel.srf_velocity.sqrMagnitude / 101325; vessel.atmDensity += dynamic_pressure; var efficiency = CalculateEfficiency(); var convPowerDissip = efficiency * vessel.atmDensity * Math.Max(0, CurrentRadiatorTemperature - external_temperature) * effectiveRadiatorArea * 0.001 * convectiveBonus * Math.Max(part.submergedPortion * 10, 1); if (!radiatorIsEnabled) { convPowerDissip = convPowerDissip / 2; } convectedThermalPower = canRadiateHeat ? consumeWasteHeatPerSecond(convPowerDissip) : 0; if (update_count == DEPLOYMENT_DELAY) { DeployMentControl(dynamic_pressure); } } else { convectedThermalPower = 0; if (radiatorIsEnabled || !isAutomated || !canRadiateHeat || !showControls || update_count != DEPLOYMENT_DELAY) { return; } Debug.Log("[KSPI] - FixedUpdate Automated Deplotment "); Deploy(); } } catch (Exception e) { Debug.LogError("[KSPI] - Exception on " + part.name + " durring FNRadiator.FixedUpdate with message " + e.Message); } }
public override void OnFixedUpdateResourceSuppliable(double fixedDeltaTime) { last_active_time = Planetarium.GetUniversalTime(); powerGeneratorPowerOutput = 0; powerGeneratorPowerInput = 0; if (moduleGenerator == null) { return; } if (outputType == ResourceType.other) { return; } if (!moduleGenerator.generatorIsActive && !moduleGenerator.isAlwaysActive) { mockInputResource.rate = 0; SupplyFnResourcePerSecondWithMax(0, 0, ResourceSettings.Config.ElectricPowerInMegawatt); return; } if (maintainsBuffer) { resourceBuffers.UpdateBuffers(); } if (maximumPowerGeneration != 0) { currentMegajoulesDemand = Math.Max(0, GetCurrentUnfilledResourceDemand(ResourceSettings.Config.ElectricPowerInMegawatt)); currentMegajoulesSupply = Math.Min(currentMegajoulesDemand, maximumPowerGeneration); } if (moduleInputResource != null) { moduleInputResource.rate = currentMegajoulesSupply > 0 ? currentMegajoulesSupply : initialInputAmount; part.GetConnectedResourceTotals(moduleInputResource.id, out inputAmount, out inputMaxAmount); var availableRatio = Math.Min(1, inputAmount / (moduleInputResource.rate * fixedDeltaTime)); currentMegajoulesSupply *= availableRatio; moduleInputResource.rate *= availableRatio; generatorInputRate = moduleInputResource.rate; powerGeneratorPowerInput = inputType == ResourceType.megajoule ? generatorInputRate : generatorInputRate / GameConstants.ecPerMJ; } if (moduleOutputResource != null) { if (Kerbalism.IsLoaded) { moduleOutputResource.rate = 0; } generatorOutputRateInElectricCharge = maximumPowerGeneration > 0 ? currentMegajoulesSupply * (outputType == ResourceType.megajoule ? 1 : GameConstants.ecPerMJ) : initialOutputAmount; if (maximumPowerGeneration > 0) { moduleOutputResource.rate = 1 + generatorOutputRateInElectricCharge; } else { moduleOutputResource.rate = 1 + generatorOutputRateInElectricCharge; } mockInputResource.rate = generatorOutputRateInElectricCharge; double generatorSupplyInMegajoules = outputType == ResourceType.megajoule ? generatorOutputRateInElectricCharge : generatorOutputRateInElectricCharge / GameConstants.ecPerMJ; powerGeneratorPowerOutput = SupplyFnResourcePerSecondWithMax(generatorSupplyInMegajoules, generatorSupplyInMegajoules, ResourceSettings.Config.ElectricPowerInMegawatt); } }
public override void OnFixedUpdateResourceSuppliable(double fixedDeltaTime) { temperatureStr = part.temperature.ToString("0.00") + "K / " + part.maxTemp.ToString("0.00") + "K"; MinIsp = BaseFloatCurve.Evaluate((float)Altitude); resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, this.part.mass); resourceBuffers.UpdateBuffers(); if (curEngineT == null || !curEngineT.isEnabled) { return; } if (curEngineT.requestedThrottle > 0) { //if (vessel.atmDensity > maxAtmosphereDensity || vessel.atmDensity > _currentActiveConfiguration.maxAtmosphereDensity) // ShutDown(Localizer.Format("#LOC_KSPIE_FusionECU2_PostMsg1"));//"Inertial Fusion cannot operate in atmosphere!" if (radhazard && rad_safety_features) { ShutDown(Localizer.Format("#LOC_KSPIE_FusionECU2_PostMsg2"));//"Engines throttled down as they presently pose a radiation hazard" } //if (MinIsp <= 100) // ShutDown(Localizer.Format("#LOC_KSPIE_FusionECU2_PostMsg3"));//"Engine Stall" } KillKerbalsWithRadiation(fusionRatio); hasIspThrottling = HasIspThrottling(); ShowIspThrottle = hasIspThrottling; availablePower = Math.Max(getResourceAvailability(ResourceManager.FNRESOURCE_MEGAJOULES), getAvailablePrioritisedStableSupply(ResourceManager.FNRESOURCE_MEGAJOULES)); currentMaximumPowerProduction = GetCurrentMaximumPowerProduction(); currentMaximumPowerRequirement = GetCurrentMaximumPowerRequirement(); requiredPowerPerSecond = curEngineT.currentThrottle * currentMaximumPowerRequirement; if (curEngineT.currentThrottle > 0) { requestedPowerPerSecond = Math.Min(requiredPowerPerSecond, availablePower); recievedPowerPerSecond = requestedPowerPerSecond <= 0 ? 0 : CheatOptions.InfiniteElectricity ? requiredPowerPerSecond : consumeFNResourcePerSecond(requestedPowerPerSecond, ResourceManager.FNRESOURCE_MEGAJOULES); fusionRatio = requiredPowerPerSecond > 0 ? Math.Min(1, recievedPowerPerSecond / requiredPowerPerSecond) : 1; var inefficiency = 1 - LaserEfficiency; laserWasteheat = recievedPowerPerSecond * inefficiency; producedPowerPerSecond = fusionRatio * currentMaximumPowerProduction; if (!CheatOptions.InfiniteElectricity && currentMaximumPowerProduction > 0) { supplyFNResourcePerSecondWithMax(producedPowerPerSecond, currentMaximumPowerProduction, ResourceManager.FNRESOURCE_MEGAJOULES); } // Lasers produce Wasteheat if (!CheatOptions.IgnoreMaxTemperature && laserWasteheat > 0) { supplyFNResourcePerSecondWithMax(laserWasteheat, currentMaximumPowerRequirement * inefficiency, ResourceManager.FNRESOURCE_WASTEHEAT); } // The Aborbed wasteheat from Fusion rateMultplier = hasIspThrottling ? Math.Pow(SelectedIsp / MinIsp, 2) : 1; neutronbsorbionBonus = hasIspThrottling ? 1 - NeutronAbsorptionFractionAtMinIsp * (1 - ((SelectedIsp - MinIsp) / (MaxIsp - MinIsp))) : 0.5; absorbedWasteheat = FusionWasteHeat * wasteHeatMultiplier * fusionRatio * curEngineT.currentThrottle * neutronbsorbionBonus; supplyFNResourcePerSecond(absorbedWasteheat, ResourceManager.FNRESOURCE_WASTEHEAT); SetRatios(); currentIsp = hasIspThrottling ? SelectedIsp : MinIsp; UpdateAtmosphereCurve(currentIsp); maximumThrust = hasIspThrottling ? MaximumThrust : FullTrustMaximum; // Update FuelFlow maxFuelFlow = fusionRatio * maximumThrust / currentIsp / GameConstants.STANDARD_GRAVITY; if ((maxAtmosphereDensity >= 0 && vessel.atmDensity > maxAtmosphereDensity) || (_currentActiveConfiguration.maxAtmosphereDensity >= 0 && vessel.atmDensity > _currentActiveConfiguration.maxAtmosphereDensity)) { ScreenMessages.PostScreenMessage(Localizer.Format("#LOC_KSPIE_FusionECU2_PostMsg1"), 1.0f, ScreenMessageStyle.UPPER_CENTER); curEngineT.maxFuelFlow = 1e-10f; curEngineT.maxThrust = Mathf.Max((float)maximumThrust, 0.0001f); HideExhaust(); } else if (MinIsp < _currentActiveConfiguration.minIsp) { ScreenMessages.PostScreenMessage(Localizer.Format("#LOC_KSPIE_FusionECU2_PostMsg3"), 1.0f, ScreenMessageStyle.UPPER_CENTER); curEngineT.maxFuelFlow = 1e-10f; curEngineT.maxThrust = Mathf.Max((float)maximumThrust, 0.0001f); HideExhaust(); } else { curEngineT.maxFuelFlow = Mathf.Max((float)maxFuelFlow, 1e-10f); curEngineT.maxThrust = Mathf.Max((float)maximumThrust, 0.0001f); } if (!curEngineT.getFlameoutState && fusionRatio < 0.9 && recievedPowerPerSecond > 0) { curEngineT.status = Localizer.Format("#LOC_KSPIE_FusionECU2_statu1");//"Insufficient Electricity" } } else { absorbedWasteheat = 0; laserWasteheat = 0; requestedPowerPerSecond = 0; recievedPowerPerSecond = 0; fusionRatio = requiredPowerPerSecond > 0 ? Math.Min(1, availablePower / requiredPowerPerSecond) : 1; currentIsp = hasIspThrottling ? SelectedIsp : MinIsp; maximumThrust = hasIspThrottling ? MaximumThrust : FullTrustMaximum; UpdateAtmosphereCurve(currentIsp); rateMultplier = hasIspThrottling ? Math.Pow(SelectedIsp / MinIsp, 2) : 1; maxFuelFlow = fusionRatio * maximumThrust / currentIsp / GameConstants.STANDARD_GRAVITY; if ((maxAtmosphereDensity >= 0 && vessel.atmDensity > maxAtmosphereDensity) || (_currentActiveConfiguration.maxAtmosphereDensity >= 0 && vessel.atmDensity > _currentActiveConfiguration.maxAtmosphereDensity)) { curEngineT.maxFuelFlow = 1e-10f; curEngineT.maxThrust = Mathf.Max((float)maximumThrust, 0.0001f); HideExhaust(); } else if (MinIsp < _currentActiveConfiguration.minIsp) { curEngineT.maxFuelFlow = 1e-10f; curEngineT.maxThrust = Mathf.Max((float)maximumThrust, 0.0001f); HideExhaust(); } else { curEngineT.maxFuelFlow = Mathf.Max((float)maxFuelFlow, 1e-10f); curEngineT.maxThrust = Mathf.Max((float)maximumThrust, 0.0001f); } SetRatios(); } coldBathTemp = FNRadiator.getAverageRadiatorTemperatureForVessel(vessel); maxTempatureRadiators = FNRadiator.getAverageMaximumRadiatorTemperatureForVessel(vessel); radiatorPerformance = Math.Max(1 - (coldBathTemp / maxTempatureRadiators), 0.000001); partEmissiveConstant = part.emissiveConstant; //base.OnFixedUpdate(); }
public override void OnFixedUpdateResourceSuppliable(double fixedDeltaTime) { if (_solarPanel == null) { return; } if (_fieldKerbalismNominalRate != null) { kerbalism_nominalRate = _fieldKerbalismNominalRate.GetValue <double>(_solarPanelFixer); kerbalism_panelState = _fieldKerbalismPanelStatus.GetValue <string>(_solarPanelFixer); var kerbalismPanelStateArray = kerbalism_panelState.Split(' '); kerbalism_panelOutput = kerbalismPanelStateArray[0]; double.TryParse(kerbalism_panelOutput, out kerbalism_panelPower); } if (_outputResource != null && _solarPanel.deployState == ModuleDeployablePart.DeployState.EXTENDED) { outputResourceRate = _outputResource.rate; outputResourceCurrentRequest = _outputResource.currentRequest; } else { outputResourceRate = 0; outputResourceCurrentRequest = 0; } if (_outputType == ResourceType.other) { return; } chargeRate = _solarPanel.chargeRate; double age = (Planetarium.GetUniversalTime() - _solarPanel.launchUT) * 1.15740740740741E-05; calculatedEfficency = _solarPanel._efficMult > 0 ? _solarPanel._efficMult : _solarPanel.temperatureEfficCurve.Evaluate((float)part.skinTemperature) * _solarPanel.timeEfficCurve.Evaluate((float)age) * _solarPanel.efficiencyMult; double maxSupply = 0.0, solarRate = 0.0; sunAOA = 0; CalculateSolarFlowRate(calculatedEfficency / scale, ref maxSupply, ref solarRate); _resourceBuffers?.UpdateBuffers(); if (_outputResource != null) { if (Kerbalism.IsLoaded) { //if (kerbalism_panelPower > 0) // part.RequestResource(_solarPanel.resourceName, kerbalism_panelPower * fixedDeltaTime); } else if (_outputResource != null) { _outputResource.rate = 0; } else { part.RequestResource(_solarPanel.resourceName, solarRate * fixedDeltaTime); } } // provide power to supply manager solar_supply = _outputType == ResourceType.megajoule ? solarRate : solarRate / GameConstants.ecPerMJ; solarMaxSupply = _outputType == ResourceType.megajoule ? maxSupply : maxSupply / GameConstants.ecPerMJ; if (!Kerbalism.IsLoaded) { mjSolarSupply = PluginHelper.GetFormattedPowerString(SupplyFnResourcePerSecondWithMax(solar_supply, solarMaxSupply, ResourceSettings.Config.ElectricPowerInMegawatt)); mjMaxSupply = PluginHelper.GetFormattedPowerString(solarMaxSupply); } }
public override void OnFixedUpdate() { base.OnFixedUpdate(); if (_attached_engine == null) { return; } if (_attached_engine.currentThrottle > 0 && !exhaustAllowed) { string message = AttachedReactor.MayExhaustInLowSpaceHomeworld ? Localizer.Format("#LOC_KSPIE_MagneticNozzleControllerFX_PostMsg1") //"Engine halted - Radioactive exhaust not allowed towards or inside homeworld atmosphere" : Localizer.Format("#LOC_KSPIE_MagneticNozzleControllerFX_PostMsg2"); //"Engine halted - Radioactive exhaust not allowed towards or near homeworld atmosphere" ScreenMessages.PostScreenMessage(message, 5, ScreenMessageStyle.UPPER_CENTER); vessel.ctrlState.mainThrottle = 0; // Return to realtime if (vessel.packed) { TimeWarp.SetRate(0, true); } } _chargedParticleMaximumPercentageUsage = _attached_reactor != null ? _attached_reactor.ChargedParticlePropulsionEfficiency : 0; if (_chargedParticleMaximumPercentageUsage > 0) { if (_attached_reactor.Part != this.part) { resourceBuffers.UpdateVariable(ResourceSettings.Config.WasteHeatInMegawatt, this.part.mass); resourceBuffers.UpdateBuffers(); } maximumChargedPower = _attached_reactor.MaximumChargedPower; var currentMaximumChargedPower = maximum_isp == minimum_isp ? maximumChargedPower * _attached_engine.currentThrottle : maximumChargedPower; _max_charged_particles_power = currentMaximumChargedPower * exchanger_thrust_divisor * _attached_reactor.ChargedParticlePropulsionEfficiency; _charged_particles_requested = exhaustAllowed && _attached_engine.isOperational && _attached_engine.currentThrottle > 0 ? _max_charged_particles_power : 0; _charged_particles_received = _charged_particles_requested > 0 ? consumeFNResourcePerSecond(_charged_particles_requested, ResourceSettings.Config.ChargedParticleInMegawatt) : 0; // update Isp currentIsp = !_attached_engine.isOperational || _attached_engine.currentThrottle == 0 ? maximum_isp : Math.Min(maximum_isp, minimum_isp / Math.Pow(_attached_engine.currentThrottle, throtleExponent)); var powerThrustModifier = GameConstants.BaseThrustPowerMultiplier * powerThrustMultiplier; var max_engine_thrust_at_max_isp = powerThrustModifier * _charged_particles_received / maximum_isp / GameConstants.STANDARD_GRAVITY; var calculatedConsumptionInTon = max_engine_thrust_at_max_isp / maximum_isp / GameConstants.STANDARD_GRAVITY; UpdatePropellantBuffer(calculatedConsumptionInTon); // convert reactor product into propellants when possible and generate addition propellant from reactor fuel consumption chargedParticleRatio = currentMaximumChargedPower > 0 ? _charged_particles_received / currentMaximumChargedPower : 0; _attached_reactor.UseProductForPropulsion(chargedParticleRatio, calculatedConsumptionInTon); calculatedConsumptionPerSecond = calculatedConsumptionInTon * 1000; if (!CheatOptions.IgnoreMaxTemperature) { if (_attached_engine.isOperational && _attached_engine.currentThrottle > 0) { wasteheatConsumption = _charged_particles_received > _previous_charged_particles_received ? _charged_particles_received + (_charged_particles_received - _previous_charged_particles_received) : _charged_particles_received - (_previous_charged_particles_received - _charged_particles_received); _previous_charged_particles_received = _charged_particles_received; } //else if (_previous_charged_particles_received > 0) //{ // wasteheatConsumption = _previous_charged_particles_received; // _previous_charged_particles_received = 0; //} else { wasteheatConsumption = 0; _charged_particles_received = 0; _previous_charged_particles_received = 0; } consumeFNResourcePerSecond(wasteheatConsumption, ResourceSettings.Config.WasteHeatInMegawatt); } if (_charged_particles_received == 0) { _chargedParticleMaximumPercentageUsage = 0; UpdateRunningEffect(); UpdatePowerEffect(); } // calculate power cost var ispPowerCostMultiplier = 1 + max_power_multiplier - Math.Log10(currentIsp / minimum_isp); var minimumEnginePower = _attached_reactor.MagneticNozzlePowerMult * _charged_particles_received * ispPowerCostMultiplier * 0.005 * Math.Max(_attached_reactor_distance, 1); var neededBufferPower = Math.Min(getResourceAvailability(ResourceSettings.Config.ElectricPowerInMegawatt), Math.Min(Math.Max(powerBufferMax - powerBufferStore, 0), minimumEnginePower)); _requestedElectricPower = minimumEnginePower + neededBufferPower; _recievedElectricPower = CheatOptions.InfiniteElectricity || _requestedElectricPower == 0 ? _requestedElectricPower : consumeFNResourcePerSecond(_requestedElectricPower, ResourceSettings.Config.ElectricPowerInMegawatt); // adjust power buffer var powerSurplus = _recievedElectricPower - minimumEnginePower; if (powerSurplus < 0) { var powerFromBuffer = Math.Min(-powerSurplus, powerBufferStore); _recievedElectricPower += powerFromBuffer; powerBufferStore -= powerFromBuffer; } else { powerBufferStore += powerSurplus; } // calculate Power factor megajoulesRatio = Math.Min(_recievedElectricPower / minimumEnginePower, 1); megajoulesRatio = (double.IsNaN(megajoulesRatio) || double.IsInfinity(megajoulesRatio)) ? 0 : megajoulesRatio; var scaledPowerFactor = Math.Pow(megajoulesRatio, 0.5); double effectiveThrustRatio = 1; _engineMaxThrust = 0; if (_max_charged_particles_power > 0) { var max_thrust = powerThrustModifier * _charged_particles_received * scaledPowerFactor / currentIsp / GameConstants.STANDARD_GRAVITY; var effective_thrust = Math.Max(max_thrust - (radius * radius * vessel.atmDensity * 100), 0); effectiveThrustRatio = max_thrust > 0 ? effective_thrust / max_thrust : 0; _engineMaxThrust = _attached_engine.currentThrottle > 0 ? Math.Max(effective_thrust, 1e-9) : Math.Max(max_thrust, 1e-9); } // set isp FloatCurve newAtmosphereCurve = new FloatCurve(); engineIsp = _attached_engine.currentThrottle > 0 ? (currentIsp * scaledPowerFactor * effectiveThrustRatio) : currentIsp; newAtmosphereCurve.Add(0, (float)engineIsp, 0, 0); _attached_engine.atmosphereCurve = newAtmosphereCurve; var max_effective_fuel_flow_rate = !double.IsInfinity(_engineMaxThrust) && !double.IsNaN(_engineMaxThrust) && currentIsp > 0 ? _engineMaxThrust / currentIsp / GameConstants.STANDARD_GRAVITY / (_attached_engine.currentThrottle > 0 ? _attached_engine.currentThrottle : 1) : 0; max_theoretical_thrust = powerThrustModifier * maximumChargedPower * _chargedParticleMaximumPercentageUsage / currentIsp / GameConstants.STANDARD_GRAVITY; max_theoratical_fuel_flow_rate = max_theoretical_thrust / currentIsp / GameConstants.STANDARD_GRAVITY; // set maximum flow engineFuelFlow = _attached_engine.currentThrottle > 0 ? Math.Max((float)max_effective_fuel_flow_rate, 1e-9f) : (float)max_theoratical_fuel_flow_rate; _attached_engine.maxFuelFlow = engineFuelFlow; _attached_engine.useThrustCurve = false; // This whole thing may be inefficient, but it should clear up some confusion for people. if (_attached_engine.getFlameoutState) { return; } if (_attached_engine.currentThrottle < 0.01) { _attached_engine.status = Localizer.Format("#LOC_KSPIE_MagneticNozzleControllerFX_statu1");//"offline" } else if (megajoulesRatio < 0.75 && _requestedElectricPower > 0) { _attached_engine.status = Localizer.Format("#LOC_KSPIE_MagneticNozzleControllerFX_statu2");//"Insufficient Electricity" } else if (effectiveThrustRatio < 0.01 && vessel.atmDensity > 0) { _attached_engine.status = Localizer.Format("#LOC_KSPIE_MagneticNozzleControllerFX_statu3");//"Too dense atmospherere" } } else { _chargedParticleMaximumPercentageUsage = 0; _attached_engine.maxFuelFlow = 0.0000000001f; _recievedElectricPower = 0; _charged_particles_requested = 0; _charged_particles_received = 0; _engineMaxThrust = 0; } currentThrust = _attached_engine.GetCurrentThrust(); }
public override void OnFixedUpdate() { temperatureStr = part.temperature.ToString("0.00") + "K / " + part.maxTemp.ToString("0.00") + "K"; resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, this.part.mass); resourceBuffers.UpdateBuffers(); if (curEngineT == null) { return; } float throttle = curEngineT.currentThrottle > 0 ? Mathf.Max(curEngineT.currentThrottle, 0.01f) : 0; //double atmo_thrust_factor = Math.Min(1.0, Math.Max(1.0 - Math.Pow(vessel.atmDensity, 0.2), 0)); if (throttle > 0) { if (vessel.atmDensity > maxAtmosphereDensity) { ShutDown("Inertial Fusion cannot operate in atmosphere!"); } if (radhazard && rad_safety_features) { ShutDown("Engines throttled down as they presently pose a radiation hazard"); } } KillKerbalsWithRadiation(throttle); coldBathTemp = (float)FNRadiator.getAverageRadiatorTemperatureForVessel(vessel); maxTempatureRadiators = (float)FNRadiator.getAverageMaximumRadiatorTemperatureForVessel(vessel); if (throttle > 0) { // Calculate Fusion Ratio var recievedPower = CheatOptions.InfiniteElectricity ? powerRequirement : consumeFNResourcePerSecond(powerRequirement, ResourceManager.FNRESOURCE_MEGAJOULES); var plasma_ratio = recievedPower / powerRequirement; var fusionRatio = plasma_ratio >= 1 ? 1 : plasma_ratio > 0.75 ? plasma_ratio * plasma_ratio * plasma_ratio * plasma_ratio * plasma_ratio * plasma_ratio : 0; if (!CheatOptions.IgnoreMaxTemperature) { // Lasers produce Wasteheat supplyFNResourcePerSecond(recievedPower * (1 - efficiency), ResourceManager.FNRESOURCE_WASTEHEAT); // The Aborbed wasteheat from Fusion supplyFNResourcePerSecond(FusionWasteHeat * wasteHeatMultiplier * fusionRatio, ResourceManager.FNRESOURCE_WASTEHEAT); } // change ratio propellants Hydrogen/Fusion curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.LqdDeuterium).ratio = (float)(standard_deuterium_rate / throttle / throttle); curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.LqdTritium).ratio = (float)(standard_tritium_rate / throttle / throttle); // Update ISP var newISP = new FloatCurve(); var currentIsp = Math.Max(minISP * fusionRatio / throttle, minISP / 10); newISP.Add(0, (float)currentIsp); curEngineT.atmosphereCurve = newISP; // Update FuelFlow var maxFuelFlow = fusionRatio * MaximumThrust / currentIsp / GameConstants.STANDARD_GRAVITY; curEngineT.maxFuelFlow = Math.Max((float)maxFuelFlow, 0.0000001f); if (!curEngineT.getFlameoutState) { if (plasma_ratio < 0.75 && recievedPower > 0) { curEngineT.status = "Insufficient Electricity"; } } } else { var currentIsp = minISP * 100; var newISP = new FloatCurve(); newISP.Add(0, (float)currentIsp); curEngineT.atmosphereCurve = newISP; var maxFuelFlow = MaximumThrust / currentIsp / GameConstants.STANDARD_GRAVITY; curEngineT.maxFuelFlow = (float)maxFuelFlow; curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.LqdDeuterium).ratio = (float)(standard_deuterium_rate); curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.LqdTritium).ratio = (float)(standard_tritium_rate); } radiatorPerformance = (float)Math.Max(1 - (float)(coldBathTemp / maxTempatureRadiators), 0.000001); partEmissiveConstant = (float)part.emissiveConstant; }
public override void OnFixedUpdateResourceSuppliable(double fixedDeltaTime) { if (_solarPanel == null) { return; } if (_field_kerbalism_nominalRate != null) { kerbalism_nominalRate = _field_kerbalism_nominalRate.GetValue <double>(solarPanelFixer); kerbalism_panelState = _field_kerbalism_panelStatus.GetValue <string>(solarPanelFixer); var kerbalism_panelStateArray = kerbalism_panelState.Split(' '); kerbalism_panelOutput = kerbalism_panelStateArray[0]; double.TryParse(kerbalism_panelOutput, out kerbalism_panelPower); } if (outputResource != null && _solarPanel.deployState == ModuleDeployablePart.DeployState.EXTENDED) { outputResourceRate = outputResource.rate; outputResourceCurrentRequest = outputResource.currentRequest; } else { outputResourceRate = 0; outputResourceCurrentRequest = 0; } if (_outputType == ResourceType.other) { return; } chargeRate = _solarPanel.chargeRate; efficiencyMult = _solarPanel.efficiencyMult; _efficMult = _solarPanel._efficMult; calculatedEfficency = _solarPanel._efficMult > 0 ? _solarPanel._efficMult : _solarPanel.temperatureEfficCurve.Evaluate((float)part.skinTemperature) * _solarPanel.timeEfficCurve.Evaluate((float)((Planetarium.GetUniversalTime() - _solarPanel.launchUT) * 1.15740740740741E-05)) * _solarPanel.efficiencyMult; maxSupply = 0; solarRate = 0; sunAOA = 0; CalculateSolarFlowRate(calculatedEfficency / scale, ref maxSupply, ref solarRate); if (_resourceBuffers != null) { _resourceBuffers.UpdateBuffers(); } if (kerbalism_panelPower > 0) { part.RequestResource(_solarPanel.resourceName, kerbalism_panelPower * fixedDeltaTime); } else if (outputResourceCurrentRequest > 0) { part.RequestResource(_solarPanel.resourceName, outputResourceCurrentRequest); } else { part.RequestResource(_solarPanel.resourceName, solarRate * fixedDeltaTime); } // provide power to supply manager solar_supply = _outputType == ResourceType.megajoule ? solarRate : solarRate * 0.001; solarMaxSupply = _outputType == ResourceType.megajoule ? maxSupply : maxSupply * 0.001; megaJouleSolarPowerSupply = supplyFNResourcePerSecondWithMax(solar_supply, solarMaxSupply, ResourceManager.FNRESOURCE_MEGAJOULES); }
public override void OnFixedUpdate() // OnFixedUpdate is only called when (force) activated { _resourceBuffers.UpdateVariable(ResourceSettings.Config.WasteHeatInMegawatt, this.part.mass); _resourceBuffers.UpdateBuffers(); }
public void FixedUpdate() // FixedUpdate is also called when not activated { try { if (!HighLogic.LoadedSceneIsFlight) { return; } if (!active) { base.OnFixedUpdate(); } if (resourceBuffers != null) { resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, radiatorIsEnabled ? this.part.mass : this.part.mass * 1e-3); resourceBuffers.UpdateBuffers(); } // get resource bar ratio at start of frame ResourceManager wasteheatManager = getManagerForVessel(ResourceManager.FNRESOURCE_WASTEHEAT); if (Double.IsNaN(wasteheatManager.TemperatureRatio)) { Debug.LogError("[KSPI]: FNRadiator: FixedUpdate Single.IsNaN detected in TemperatureRatio"); return; } // ToDo replace wasteheatManager.SqrtResourceBarRatioBegin by ResourceBarRatioBegin after generators hotbath takes into account expected temperature radiator_temperature_temp_val = external_temperature + Math.Min(maximumTemperatureDifferenceWithExternal * wasteheatManager.TemperatureRatio, currentTemperatureDifferenceWithExternal); var deltaTemp = Math.Max(radiator_temperature_temp_val - Math.Max(external_temperature * Math.Min(1, vessel.atmDensity), PhysicsGlobals.SpaceTemperature), 0); var deltaTempToPowerFour = deltaTemp * deltaTemp * deltaTemp * deltaTemp; if (radiatorIsEnabled) { if (!CheatOptions.IgnoreMaxTemperature && wasteheatManager.ResourceBarRatioBegin >= 1 && CurrentRadiatorTemperature >= maxRadiatorTemperature) { explode_counter++; if (explode_counter > 25) { part.explode(); } } else { explode_counter = 0; } thermalPowerDissipPerSecond = (double)wasteheatManager.RadiatorEfficiency * deltaTempToPowerFour * stefanArea; if (Double.IsNaN(thermalPowerDissipPerSecond)) { Debug.LogWarning("[KSPI]: FNRadiator: FixedUpdate Single.IsNaN detected in thermalPowerDissipPerSecond"); } radiatedThermalPower = canRadiateHeat ? consumeWasteHeatPerSecond(thermalPowerDissipPerSecond, wasteheatManager) : 0; if (Double.IsNaN(radiatedThermalPower)) { Debug.LogError("[KSPI]: FNRadiator: FixedUpdate Single.IsNaN detected in radiatedThermalPower after call consumeWasteHeat (" + thermalPowerDissipPerSecond + ")"); } instantaneous_rad_temp = CalculateInstantaniousRadTemp(external_temperature); CurrentRadiatorTemperature = instantaneous_rad_temp; if (_moduleDeployableRadiator) { _moduleDeployableRadiator.hasPivot = pivotEnabled; } } else { thermalPowerDissipPerSecond = (double)wasteheatManager.RadiatorEfficiency * deltaTempToPowerFour * stefanArea * 0.5; radiatedThermalPower = canRadiateHeat ? consumeWasteHeatPerSecond(thermalPowerDissipPerSecond, wasteheatManager) : 0; instantaneous_rad_temp = CalculateInstantaniousRadTemp(external_temperature); CurrentRadiatorTemperature = instantaneous_rad_temp; } if (vessel.atmDensity > 0) { atmosphere_modifier = vessel.atmDensity * convectiveBonus + vessel.speed.Sqrt(); var heatTransferCooficient = 0.0005; // 500W/m2/K var temperatureDifference = Math.Max(0, CurrentRadiatorTemperature - external_temperature); var submergedModifier = Math.Max(part.submergedPortion * 10, 1); var convPowerDissip = (double)wasteheatManager.RadiatorEfficiency * atmosphere_modifier * temperatureDifference * effectiveRadiatorArea * heatTransferCooficient * submergedModifier; if (!radiatorIsEnabled) { convPowerDissip = convPowerDissip * 0.25; } convectedThermalPower = canRadiateHeat ? consumeWasteHeatPerSecond(convPowerDissip, wasteheatManager) : 0; if (radiator_deploy_delay >= DEPLOYMENT_DELAY) { DeployMentControl(); } } else { convectedThermalPower = 0; if (radiatorIsEnabled || !isAutomated || !canRadiateHeat || !showControls || radiator_deploy_delay < DEPLOYMENT_DELAY) { return; } Debug.Log("[KSPI]: FixedUpdate Automated Deployment "); Deploy(); } } catch (Exception e) { Debug.LogError("[KSPI]: Exception on " + part.name + " durring FNRadiator.FixedUpdate with message " + e.Message); } }
public override void OnFixedUpdate() { temperatureStr = part.temperature.ToString("0.00") + "K / " + part.maxTemp.ToString("0.00") + "K"; if (curEngineT == null) { return; } throttle = curEngineT.currentThrottle > MinThrottleRatio ? curEngineT.currentThrottle : 0; if (throttle > 0) { if (vessel.atmDensity > maxAtmosphereDensity) { ShutDown("Inertial Fusion cannot operate in atmosphere!"); } if (radhazard && rad_safety_features) { ShutDown("Engines throttled down as they presently pose a radiation hazard"); } } KillKerbalsWithRadiation(throttle); resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, this.part.mass); resourceBuffers.UpdateBuffers(); if (throttle > 0) { // Calculate Fusion Ratio enginePowerRequirement = CurrentPowerRequirement; var recievedPower = CheatOptions.InfiniteElectricity ? enginePowerRequirement : consumeFNResourcePerSecond(enginePowerRequirement, ResourceManager.FNRESOURCE_MEGAJOULES); var plasma_ratio = recievedPower / enginePowerRequirement; fusionRatio = plasma_ratio >= 1 ? 1 : plasma_ratio > 0.75 ? plasma_ratio * plasma_ratio * plasma_ratio * plasma_ratio * plasma_ratio * plasma_ratio : 0; laserWasteheat = recievedPower * (1 - LaserEfficiency); // The Aborbed wasteheat from Fusion var rateMultplier = minISP / SelectedIsp; var neutronbsorbionBonus = 1 - NeutronAbsorptionFractionAtMinIsp * (1 - ((SelectedIsp - minISP) / (MaxIsp - minISP))); absorbedWasteheat = FusionWasteHeat * wasteHeatMultiplier * fusionRatio * throttle * neutronbsorbionBonus; // Lasers produce Wasteheat if (!CheatOptions.IgnoreMaxTemperature) { supplyFNResourcePerSecond(laserWasteheat, ResourceManager.FNRESOURCE_WASTEHEAT); supplyFNResourcePerSecond(absorbedWasteheat, ResourceManager.FNRESOURCE_WASTEHEAT); } // change ratio propellants Hydrogen/Fusion curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.LqdDeuterium).ratio = (float)(standard_deuterium_rate / rateMultplier); curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.LqdTritium).ratio = (float)(standard_tritium_rate / rateMultplier); // Update ISP var currentIsp = SelectedIsp; var newISP = new FloatCurve(); newISP.Add(0, currentIsp); newISP.Add(1, 0); curEngineT.atmosphereCurve = newISP; // Update FuelFlow var maxFuelFlow = fusionRatio * MaximumThrust / currentIsp / GameConstants.STANDARD_GRAVITY; curEngineT.maxFuelFlow = (float)maxFuelFlow; curEngineT.maxThrust = MaximumThrust; maximumThrust = MaximumThrust; if (!curEngineT.getFlameoutState && plasma_ratio < 0.75 && recievedPower > 0) { curEngineT.status = "Insufficient Electricity"; } } else { enginePowerRequirement = 0; absorbedWasteheat = 0; laserWasteheat = 0; fusionRatio = 0; var currentIsp = SelectedIsp; var newISP = new FloatCurve(); newISP.Add(0, currentIsp); newISP.Add(1, 0); curEngineT.atmosphereCurve = newISP; curEngineT.maxThrust = MaximumThrust; var rateMultplier = minISP / SelectedIsp; var maxFuelFlow = MaximumThrust / currentIsp / GameConstants.STANDARD_GRAVITY; curEngineT.maxFuelFlow = (float)maxFuelFlow; curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.LqdDeuterium).ratio = (float)(standard_deuterium_rate / rateMultplier); curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.LqdTritium).ratio = (float)(standard_tritium_rate / rateMultplier); } coldBathTemp = FNRadiator.getAverageRadiatorTemperatureForVessel(vessel); maxTempatureRadiators = FNRadiator.getAverageMaximumRadiatorTemperatureForVessel(vessel); radiatorPerformance = Math.Max(1 - (coldBathTemp / maxTempatureRadiators), 0.000001); partEmissiveConstant = part.emissiveConstant; }
// ReSharper disable once UnusedMember.Global public void FixedUpdate() { if (_initializationCountdown > 0) { _initializationCountdown--; } if (_vesselChangedSIOCountdown > 0) { _vesselChangedSIOCountdown--; } if (!HighLogic.LoadedSceneIsFlight) { return; } if (_attachedEngine == null) { return; } CalculateTimeDialation(); if (_attachedEngine is ModuleEnginesFX) { GetAllPropellants().ForEach(prop => part.Effect(prop.ParticleFXName, 0, -1)); // set all FX to zero } if (Current_propellant == null) { return; } resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, (double)(decimal)this.part.mass); resourceBuffers.UpdateBuffers(); if (!this.vessel.packed && !_warpToReal) { storedThrotle = vessel.ctrlState.mainThrottle; } maxEffectivePower = MaxEffectivePower; currentPropellantEfficiency = CurrentPropellantEfficiency; var sumOfAllEffectivePower = vessel.FindPartModulesImplementing <ElectricEngineControllerFX>().Where(ee => ee.IsOperational).Sum(ee => ee.MaxEffectivePower); _electrical_share_f = sumOfAllEffectivePower > 0 ? maxEffectivePower / sumOfAllEffectivePower : 1; modifiedThrotte = ModifiedThrotte; modifiedMaxThrottlePower = maxEffectivePower * modifiedThrotte; availablePower = getAvailablePrioritisedStableSupply(ResourceManager.FNRESOURCE_MEGAJOULES); maxThrustFromPower = EvaluateMaxThrust(availablePower * _electrical_share_f); var megaJoulesBarRatio = getResourceBarRatio(ResourceManager.FNRESOURCE_MEGAJOULES); effectiveResourceThrotling = megaJoulesBarRatio > 0.1 ? 1 : megaJoulesBarRatio * 10; availablePowerForEngine = availablePower * effectiveResourceThrotling * _electrical_share_f; currentPowerForEngine = availablePowerForEngine * modifiedThrotte; power_request = CheatOptions.InfiniteElectricity ? modifiedMaxThrottlePower : currentPropellantEfficiency <= 0 ? 0 : Math.Min(currentPowerForEngine, modifiedMaxThrottlePower); actualPowerReceived = CheatOptions.InfiniteElectricity ? power_request : consumeFNResourcePerSecond(power_request, ResourceManager.FNRESOURCE_MEGAJOULES); simulatedPowerReceived = Math.Min(availablePowerForEngine, maxEffectivePower); // produce waste heat var heatToProduce = actualPowerReceived * (1 - currentPropellantEfficiency) * Current_propellant.WasteHeatMultiplier; _heat_production_f = CheatOptions.IgnoreMaxTemperature ? heatToProduce : supplyFNResourcePerSecond(heatToProduce, ResourceManager.FNRESOURCE_WASTEHEAT); // update GUI Values _electrical_consumption_f = actualPowerReceived; _effectiveIsp = _modifiedEngineBaseIsp * _modifiedCurrentPropellantIspMultiplier * ThrottleModifiedIsp(); _maxIsp = _effectiveIsp * CurrentPropellantThrustMultiplier; var throtteModifier = ispGears == 1 ? 1 : ModifiedThrotte; effectivePowerThrustModifier = timeDilation * currentPropellantEfficiency * CurrentPropellantThrustMultiplier * GetPowerThrustModifier(); effectiveRecievedPower = effectivePowerThrustModifier * actualPowerReceived * throtteModifier; effectiveSimulatedPower = effectivePowerThrustModifier * simulatedPowerReceived; currentThrustInSpace = _effectiveIsp <= 0 ? 0 : effectiveRecievedPower / _effectiveIsp / GameConstants.STANDARD_GRAVITY; simulatedThrustInSpace = _effectiveIsp <= 0 ? 0 : effectiveSimulatedPower / _effectiveIsp / GameConstants.STANDARD_GRAVITY; _attachedEngine.maxThrust = (float)Math.Max(simulatedThrustInSpace, 0.001); _currentSpaceFuelFlowRate = _maxIsp <= 0 ? 0 : currentThrustInSpace / _maxIsp / GameConstants.STANDARD_GRAVITY; _simulatedSpaceFuelFlowRate = _maxIsp <= 0 ? 0 : simulatedThrustInSpace / _maxIsp / GameConstants.STANDARD_GRAVITY; var maxThrustWithCurrentThrottle = currentThrustInSpace * throtteModifier; calculated_thrust = Current_propellant.SupportedEngines == 8 ? maxThrustWithCurrentThrottle : Math.Max(maxThrustWithCurrentThrottle - (exitArea * vessel.staticPressurekPa), 0); simulated_max_thrust = Current_propellant.SupportedEngines == 8 ? simulatedThrustInSpace : Math.Max(simulatedThrustInSpace - (exitArea * vessel.staticPressurekPa), 0); var throttle = _attachedEngine.currentThrottle > 0 ? Math.Max((double)(decimal)_attachedEngine.currentThrottle, 0.01) : 0; if (throttle > 0) { if (IsValidPositiveNumber(calculated_thrust) && IsValidPositiveNumber(maxThrustWithCurrentThrottle)) { _atmosphereThrustEfficiency = Math.Min(1, calculated_thrust / maxThrustWithCurrentThrottle); _atmosphereThrustEfficiencyPercentage = _atmosphereThrustEfficiency * 100; UpdateIsp(_atmosphereThrustEfficiency); _fuelFlowModifier = ispGears == 1 ? 1 / throttle : ModifiedThrotte / throttle; _maxFuelFlowRate = (float)Math.Max(_atmosphereThrustEfficiency * _currentSpaceFuelFlowRate * _fuelFlowModifier, 1e-11); _attachedEngine.maxFuelFlow = _maxFuelFlowRate; } else { UpdateIsp(1); _atmosphereThrustEfficiency = 0; _maxFuelFlowRate = 1e-11f; _attachedEngine.maxFuelFlow = _maxFuelFlowRate; } if (!this.vessel.packed) { // allow throtle to be used up to Geeforce treshold TimeWarp.GThreshold = GThreshold; _isFullyStarted = true; _ispPersistent = (double)(decimal)_attachedEngine.realIsp; thrust_d = (double)(decimal)_attachedEngine.requestedMassFlow * GameConstants.STANDARD_GRAVITY * _ispPersistent; } else if (this.vessel.packed && _attachedEngine.enabled && FlightGlobals.ActiveVessel == vessel && _initializationCountdown == 0) { _warpToReal = true; // Set to true for transition to realtime thrust_d = calculated_thrust; if (PersistHeading()) { PersistantThrust((double)(decimal)TimeWarp.fixedDeltaTime, Planetarium.GetUniversalTime(), this.part.transform.up, this.vessel.totalMass, thrust_d, _ispPersistent); } } else { IdleEngine(); } } else { IdleEngine(); } if (_attachedEngine is ModuleEnginesFX && particleEffectMult > 0) { var engineFuelFlow = (double)(decimal)_attachedEngine.maxFuelFlow * (double)(decimal)_attachedEngine.currentThrottle; var max_fuel_flow_rate = (double)(decimal)_attachedEngine.maxThrust / (double)(decimal)_attachedEngine.realIsp / GameConstants.STANDARD_GRAVITY; effectPower = Math.Min(1, particleEffectMult * (engineFuelFlow / max_fuel_flow_rate)); if (String.IsNullOrEmpty(EffectName)) { _particleFXName = Current_propellant.ParticleFXName; } else { _particleFXName = EffectName; } this.part.Effect(_particleFXName, (float)effectPower, -1); } var vacuumPlasmaResource = part.Resources[InterstellarResourcesConfiguration.Instance.VacuumPlasma]; if (isupgraded && vacuumPlasmaResource != null) { var calculatedConsumptionInTon = this.vessel.packed ? 0 : currentThrustInSpace / engineIsp / GameConstants.STANDARD_GRAVITY; vacuumPlasmaResource.maxAmount = Math.Max(0.0000001, calculatedConsumptionInTon * 200 * (double)(decimal)TimeWarp.fixedDeltaTime); part.RequestResource(InterstellarResourcesConfiguration.Instance.VacuumPlasma, -vacuumPlasmaResource.maxAmount); } }
public override void OnFixedUpdate() { temperatureStr = part.temperature.ToString("0.00") + "K / " + part.maxTemp.ToString("0.00") + "K"; MinIsp = BaseFloatCurve.Evaluate((float)Altitude); resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, this.part.mass); resourceBuffers.UpdateBuffers(); if (curEngineT == null || !curEngineT.isEnabled) { return; } throttle = curEngineT.currentThrottle > MinThrottleRatio ? curEngineT.currentThrottle : 0; if (throttle > 0) { if (maxAtmosphereDensity >= 0 && vessel.atmDensity > maxAtmosphereDensity) { ShutDown("Inertial Fusion cannot operate in atmosphere!"); } if (radhazard && rad_safety_features) { ShutDown("Engines throttled down as they presently pose a radiation hazard"); } if (SelectedIsp <= 10) { ShutDown("Engine Stall"); } } KillKerbalsWithRadiation(throttle); hasIspThrottling = HasIspThrottling(); if (throttle > 0) { // Calculate Fusion Ratio enginePowerRequirement = CurrentPowerRequirement; var requestedPowerPerSecond = enginePowerRequirement; var availablePower = getAvailableResourceSupply(ResourceManager.FNRESOURCE_MEGAJOULES); var resourceBarRatio = getResourceBarRatio(ResourceManager.FNRESOURCE_MEGAJOULES); var effectivePowerThrotling = resourceBarRatio > ResourceManager.ONE_THIRD ? 1 : resourceBarRatio * 3; var requestedPower = Math.Min(requestedPowerPerSecond, availablePower * effectivePowerThrotling); var recievedPowerPerSecond = CheatOptions.InfiniteElectricity || requestedPower <= 0 ? requestedPowerPerSecond : consumeFNResourcePerSecond(requestedPower, ResourceManager.FNRESOURCE_MEGAJOULES); var plasmaRatio = requestedPowerPerSecond > 0 ? recievedPowerPerSecond / requestedPowerPerSecond : 1; fusionRatio = plasmaRatio; laserWasteheat = recievedPowerPerSecond * (1 - LaserEfficiency); // Lasers produce Wasteheat if (!CheatOptions.IgnoreMaxTemperature) { supplyFNResourcePerSecond(laserWasteheat, ResourceManager.FNRESOURCE_WASTEHEAT); } // The Aborbed wasteheat from Fusion var rateMultplier = hasIspThrottling ? MinIsp / SelectedIsp : 1; neutronbsorbionBonus = hasIspThrottling ? 1 - NeutronAbsorptionFractionAtMinIsp * (1 - ((SelectedIsp - MinIsp) / (MaxIsp - MinIsp))) : 0.5; absorbedWasteheat = FusionWasteHeat * wasteHeatMultiplier * fusionRatio * throttle * neutronbsorbionBonus; supplyFNResourcePerSecond(absorbedWasteheat, ResourceManager.FNRESOURCE_WASTEHEAT); // change ratio propellants Hydrogen/Fusion SetRatio(InterstellarResourcesConfiguration.Instance.LqdDeuterium, (float)(standard_deuterium_rate / rateMultplier)); SetRatio(InterstellarResourcesConfiguration.Instance.LqdTritium, (float)(standard_tritium_rate / rateMultplier)); currentIsp = hasIspThrottling ? SelectedIsp : MinIsp; UpdateAtmosphereCurve(currentIsp); maximumThrust = hasIspThrottling ? MaximumThrust : FullTrustMaximum; // Update FuelFlow var maxFuelFlow = fusionRatio * maximumThrust / currentIsp / GameConstants.STANDARD_GRAVITY; curEngineT.maxFuelFlow = (float)maxFuelFlow; curEngineT.maxThrust = (float)maximumThrust; if (!curEngineT.getFlameoutState && plasmaRatio < 0.75 && recievedPowerPerSecond > 0) { curEngineT.status = "Insufficient Electricity"; } } else { enginePowerRequirement = 0; absorbedWasteheat = 0; laserWasteheat = 0; fusionRatio = 0; currentIsp = hasIspThrottling ? SelectedIsp : MinIsp; maximumThrust = hasIspThrottling ? MaximumThrust : FullTrustMaximum; UpdateAtmosphereCurve(currentIsp); curEngineT.maxThrust = (float)maximumThrust; var rateMultplier = hasIspThrottling ? MinIsp / SelectedIsp : 1; var maxFuelFlow = maximumThrust / currentIsp / GameConstants.STANDARD_GRAVITY; curEngineT.maxFuelFlow = (float)maxFuelFlow; SetRatio(InterstellarResourcesConfiguration.Instance.LqdDeuterium, (float)(standard_deuterium_rate / rateMultplier)); SetRatio(InterstellarResourcesConfiguration.Instance.LqdTritium, (float)(standard_tritium_rate / rateMultplier)); } coldBathTemp = FNRadiator.getAverageRadiatorTemperatureForVessel(vessel); maxTempatureRadiators = FNRadiator.getAverageMaximumRadiatorTemperatureForVessel(vessel); radiatorPerformance = Math.Max(1 - (coldBathTemp / maxTempatureRadiators), 0.000001); partEmissiveConstant = part.emissiveConstant; base.OnFixedUpdate(); }
public void FixedUpdate() // FixedUpdate is also called when not activated { try { if (!HighLogic.LoadedSceneIsFlight) { return; } if (!active) { base.OnFixedUpdate(); } resourceBuffers.UpdateBuffers(); effectiveRadiatorArea = EffectiveRadiatorArea; var external_temperature = FlightGlobals.getExternalTemperature(part.transform.position); wasteheatManager = getManagerForVessel(ResourceManager.FNRESOURCE_WASTEHEAT); // get resource bar ratio at start of frame wasteheatRatio = wasteheatManager.ResourceBarRatioBegin; if (Double.IsNaN(wasteheatRatio)) { Debug.LogError("FNRadiator: FixedUpdate Single.IsNaN detected in wasteheatRatio"); return; } var normalized_atmosphere = Math.Min(vessel.atmDensity, 1); maxCurrentTemperature = maxAtmosphereTemperature * Math.Max(normalized_atmosphere, 0) + maxVacuumTemperature * Math.Max(Math.Min(1 - vessel.atmDensity, 1), 0); radiator_temperature_temp_val = external_temperature + Math.Min((maxRadiatorTemperature - external_temperature) * Math.Sqrt(wasteheatRatio), maxCurrentTemperature - external_temperature); var efficiency = 1 - Math.Pow(1 - wasteheatRatio, 400); var delta_temp = Math.Max(radiator_temperature_temp_val - Math.Max(external_temperature * normalized_atmosphere, 2.7), 0); if (radiatorIsEnabled) { if (!CheatOptions.IgnoreMaxTemperature && wasteheatRatio >= 1 && CurrentRadiatorTemperature >= maxRadiatorTemperature) { explode_counter++; if (explode_counter > 25) { part.explode(); } } else { explode_counter = 0; } var thermal_power_dissip_per_second = efficiency * Math.Pow(delta_temp, 4) * GameConstants.stefan_const * effectiveRadiatorArea / 1e6; if (Double.IsNaN(thermal_power_dissip_per_second)) { Debug.LogWarning("FNRadiator: FixedUpdate Single.IsNaN detected in fixed_thermal_power_dissip"); } radiatedThermalPower = canRadiateHeat ? consumeWasteHeatPerSecond(thermal_power_dissip_per_second) : 0; if (Double.IsNaN(radiatedThermalPower)) { Debug.LogError("FNRadiator: FixedUpdate Single.IsNaN detected in radiatedThermalPower after call consumeWasteHeat (" + thermal_power_dissip_per_second + ")"); } instantaneous_rad_temp = Math.Max(radiator_temperature_temp_val, Math.Max(FlightGlobals.getExternalTemperature(vessel.altitude, vessel.mainBody), 2.7)); if (Double.IsNaN(instantaneous_rad_temp)) { Debug.LogError("FNRadiator: FixedUpdate Single.IsNaN detected in instantaneous_rad_temp after reading external temperature"); } CurrentRadiatorTemperature = instantaneous_rad_temp; if (_moduleDeployableRadiator) { _moduleDeployableRadiator.hasPivot = pivotEnabled; } } else { double thermal_power_dissip_per_second = efficiency * Math.Pow(Math.Max(delta_temp - external_temperature, 0), 4) * GameConstants.stefan_const * effectiveRadiatorArea / 0.5e7; radiatedThermalPower = canRadiateHeat ? consumeWasteHeatPerSecond(thermal_power_dissip_per_second) : 0; instantaneous_rad_temp = Math.Max(radiator_temperature_temp_val, Math.Max(FlightGlobals.getExternalTemperature(vessel.altitude, vessel.mainBody), 2.7)); CurrentRadiatorTemperature = instantaneous_rad_temp; } if (vessel.atmDensity > 0) { var pressure = vessel.atmDensity; dynamic_pressure = 0.60205 * pressure * vessel.srf_velocity.sqrMagnitude / 101325; pressure += dynamic_pressure; var splashBonus = Math.Max(part.submergedPortion * 10, 1); var convection_delta_temp = Math.Max(0, CurrentRadiatorTemperature - external_temperature); var conv_power_dissip = efficiency * pressure * convection_delta_temp * effectiveRadiatorArea * 0.001 * convectiveBonus * splashBonus; if (!radiatorIsEnabled) { conv_power_dissip = conv_power_dissip / 2; } convectedThermalPower = canRadiateHeat ? consumeWasteHeatPerSecond(conv_power_dissip) : 0; if (update_count == DEPLOYMENT_DELAY) { DeployMentControl(dynamic_pressure); } } else { convectedThermalPower = 0; if (!radiatorIsEnabled && isAutomated && canRadiateHeat && showControls && update_count == DEPLOYMENT_DELAY) { Debug.Log("[KSPI] - FixedUpdate Automated Deplotment "); Deploy(); } } } catch (Exception e) { Debug.LogError("[KSPI] - Exception on " + part.name + " durring FNRadiator.FixedUpdate with message " + e.Message); } }