// 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 / PluginHelper.GravityConstant; var calculatedConsumptionInTon = max_engine_thrust_at_max_isp / maximum_isp / PluginHelper.GravityConstant; // 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 / PluginHelper.GravityConstant; 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 / PluginHelper.GravityConstant; 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 / PluginHelper.GravityConstant / (_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; } }
public override void OnStart(PartModule.StartState state) { try { Debug.Log("[KSPI]: Start ElectricEngineControllerFX"); if (state != StartState.Editor) { if (vessel.FindPartModulesImplementing <FNGenerator>().Any(m => m.isHighPower) == false) { if (powerThrustMultiplier == 1 && powerThrustMultiplierWithoutReactors > 0) { powerThrustMultiplier = powerThrustMultiplierWithoutReactors; } if (powerReqMult == 1 && powerReqMultWithoutReactor > 0) { powerReqMult = powerReqMultWithoutReactor; } } } ScaleParameters(); // initialise resources this.resources_to_supply = new[] { ResourceManager.FNRESOURCE_WASTEHEAT }; base.OnStart(state); AttachToEngine(); DetermineTechLevel(); powerCapacityModifier = PowerCapacityModifier; _initializationCountdown = 10; _ispFloatCurve = new FloatCurve(); _ispFloatCurve.Add(0, (float)baseISP); _speedOfLight = GameConstants.speedOfLight * PluginHelper.SpeedOfLightMult; _hasGearTechnology = String.IsNullOrEmpty(gearsTechReq) || PluginHelper.UpgradeAvailable(gearsTechReq); _modifiedEngineBaseIsp = baseISP * PluginHelper.ElectricEngineIspMult; _hasrequiredupgrade = this.HasTechsRequiredToUpgrade(); if (_hasrequiredupgrade && (isupgraded || state == StartState.Editor)) { upgradePartModule(); } UpdateEngineTypeString(); _resourceBuffers = new ResourceBuffers(); _resourceBuffers.AddConfiguration(new ResourceBuffers.TimeBasedConfig(ResourceManager.FNRESOURCE_WASTEHEAT, wasteHeatMultiplier, 2.0e+4, true)); _resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, (double)(decimal)this.part.mass); _resourceBuffers.Init(this.part); InitializePropellantMode(); SetupPropellants(true); _attachedEngine.maxThrust = (float)maximumThrustFromPower; } catch (Exception e) { Debug.LogError("[KSPI]: Error OnStart ElectricEngineControllerFX " + e.Message); } Debug.Log("[KSPI]: End Initializing ElectricEngineControllerFX"); }
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() // OnFixedUpdate is only called when (force) activated { _resourceBuffers.UpdateVariable(ResourceSettings.Config.WasteHeatInMegawatt, part.mass); _resourceBuffers.UpdateBuffers(); }
public override void OnStart(StartState state) { try { if (state.ToString().Contains(StartState.PreLaunch.ToString())) { Debug.Log("[KSPI]: PreLaunch uses InitialGearRatio:" + InitialGearRatio); SelectedIsp = ((MaxIsp - MinIsp) * Math.Max(0, Math.Min(1, InitialGearRatio))) + MinIsp; } Fields["selectedFuel"].guiName = fuelSwitchName; Fields["currentMaximumPowerRequirement"].guiActive = powerRequirement > 0; Fields["laserWasteheat"].guiActive = powerRequirement > 0 && fusionWasteHeat > 0; Fields["absorbedWasteheat"].guiActive = powerRequirement > 0 && fusionWasteHeat > 0; Fields["fusionRatio"].guiActive = powerRequirement > 0; Fields["powerRequirement"].guiActiveEditor = powerRequirement > 0; Fields["powerRequirementUpgraded1"].guiActiveEditor = powerRequirementUpgraded1 > 0; Fields["powerRequirementUpgraded2"].guiActiveEditor = powerRequirementUpgraded2 > 0; Fields["powerRequirementUpgraded3"].guiActiveEditor = powerRequirementUpgraded3 > 0; Fields["powerRequirementUpgraded4"].guiActiveEditor = powerRequirementUpgraded4 > 0; Fields["fusionWasteHeat"].guiActiveEditor = fusionWasteHeat > 0; Fields["fusionWasteHeatUpgraded1"].guiActiveEditor = !String.IsNullOrEmpty(upgradeTechReq1); Fields["fusionWasteHeatUpgraded2"].guiActiveEditor = !String.IsNullOrEmpty(upgradeTechReq2); Fields["fusionWasteHeatUpgraded3"].guiActiveEditor = !String.IsNullOrEmpty(upgradeTechReq3); Fields["fusionWasteHeatUpgraded4"].guiActiveEditor = !String.IsNullOrEmpty(upgradeTechReq4); part.maxTemp = maxTemp; part.thermalMass = 1; part.thermalMassModifier = 1; curEngineT = this.part.FindModuleImplementing <ModuleEngines>(); if (curEngineT == null) { Debug.LogError("[KSPI]: FusionEngine OnStart Engine not found"); return; } BaseFloatCurve = curEngineT.atmosphereCurve; curveMaxISP = GetMaxKey(BaseFloatCurve); if (hasMultipleConfigurations) { FcSetup(); } InitializeKerbalismEmitter(); DetermineTechLevel(); resourceBuffers = new ResourceBuffers(); resourceBuffers.AddConfiguration(new ResourceBuffers.TimeBasedConfig(ResourceManager.FNRESOURCE_WASTEHEAT, wasteHeatMultiplier, 1.0e+4, true)); resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, this.part.mass); resourceBuffers.Init(this.part); if (state != StartState.Editor) { part.emissiveConstant = maxTempatureRadiators > 0 ? 1 - coldBathTemp / maxTempatureRadiators : 0.01; } base.OnStart(state); Fields["localIsp"].guiActive = selectableIsp; Fields["localIsp"].guiActiveEditor = selectableIsp; } catch (Exception e) { Debug.LogError("[KSPI]: FusionEngine OnStart eception: " + e.Message); } }
public override void OnStart(PartModule.StartState state) { if (state == StartState.Editor) { return; } megaJouleSolarPowerSupplyField = Fields["megaJouleSolarPowerSupply"]; solarMaxSupplyField = Fields["solarMaxSupply"]; if (part.Modules.Contains("SolarPanelFixer")) { solarPanelFixer = part.Modules["SolarPanelFixer"]; _field_kerbalism_nominalRate = solarPanelFixer.Fields["nominalRate"]; _field_kerbalism_panelStatus = solarPanelFixer.Fields["panelStatus"]; } // calculate Astronomical unit on homeworld semiMajorAxis when missing if (astronomicalUnit == 0) { astronomicalUnit = FlightGlobals.GetHomeBody().orbit.semiMajorAxis; } _microwavePowerReceiver = part.FindModuleImplementing <BeamedPowerReceiver>(); _solarPanel = (ModuleDeployableSolarPanel)this.part.FindModuleImplementing <ModuleDeployableSolarPanel>(); if (_solarPanel == null) { return; } if (this.part.FindModuleImplementing <ModuleJettison>() == null) { UnityEngine.Debug.Log("[KSPI]: FNSolarPanelWasteHeatModule Force Activated " + part.name); part.force_activate(); } String[] resources_to_supply = { ResourceManager.FNRESOURCE_MEGAJOULES }; this.resources_to_supply = resources_to_supply; base.OnStart(state); outputResource = _solarPanel.resHandler.outputResources.FirstOrDefault(); resourceName = _solarPanel.resourceName; if (resourceName == ResourceManager.FNRESOURCE_MEGAJOULES) { _outputType = ResourceType.megajoule; } else if (resourceName == ResourceManager.STOCK_RESOURCE_ELECTRICCHARGE) { _outputType = ResourceType.electricCharge; } else { _outputType = ResourceType.other; } // only manage power buffer when microwave receiver is not available if (_outputType != ResourceType.other && _microwavePowerReceiver == null) { _resourceBuffers = new ResourceBuffers(); _resourceBuffers.AddConfiguration(new ResourceBuffers.TimeBasedConfig(ResourceManager.FNRESOURCE_MEGAJOULES)); _resourceBuffers.AddConfiguration(new ResourceBuffers.TimeBasedConfig(ResourceManager.STOCK_RESOURCE_ELECTRICCHARGE)); _resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_MEGAJOULES, _outputType == ResourceType.electricCharge ? _solarPanel.chargeRate * 0.001f : _solarPanel.chargeRate); _resourceBuffers.UpdateVariable(ResourceManager.STOCK_RESOURCE_ELECTRICCHARGE, _outputType == ResourceType.electricCharge ? _solarPanel.chargeRate : _solarPanel.chargeRate * 1000); _resourceBuffers.Init(part); } _stars = KopernicusHelper.Stars; }
// 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; } // 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; //var availablePower = Math.Max(getStableResourceSupply(ResourceManager.FNRESOURCE_MEGAJOULES) - getCurrentHighPriorityResourceDemand(ResourceManager.FNRESOURCE_MEGAJOULES), 0); var availablePower = getAvailableResourceSupply(ResourceManager.FNRESOURCE_MEGAJOULES); maxThrustInSpace = EvaluateMaxThrust(availablePower * _electrical_share_f); _attachedEngine.maxThrust = (float)Math.Max(maxThrustInSpace, 0.001); if (CheatOptions.InfiniteElectricity) { power_request = maxThrottlePower; } else { var megaJoulesBarRatio = getResourceBarRatio(ResourceManager.FNRESOURCE_MEGAJOULES); var effectiveResourceThrotling = megaJoulesBarRatio > OneThird ? 1 : megaJoulesBarRatio * 3; var powerPerEngine = effectiveResourceThrotling * ModifiedThrotte * maxThrustInSpace * CurrentIspMultiplier * _modifiedEngineBaseIsp / GetPowerThrustModifier() * GameConstants.STANDARD_GRAVITY; 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; _heat_production_f = CheatOptions.IgnoreMaxTemperature ? heatToProduce : supplyFNResourcePerSecond(heatToProduce, ResourceManager.FNRESOURCE_WASTEHEAT); // update GUI Values _electrical_consumption_f = powerReceived; var effectiveIsp = _modifiedCurrentPropellantIspMultiplier * _modifiedEngineBaseIsp * ThrottleModifiedIsp(); var throtteModifier = ispGears == 1 ? 1 : ModifiedThrotte; var effectivePower = timeDilation * currentPropellantEfficiency * CurrentPropellantThrustMultiplier * throtteModifier * GetPowerThrustModifier() * powerReceived; curThrustInSpace = effectivePower / effectiveIsp / GameConstants.STANDARD_GRAVITY; _maxIsp = _modifiedEngineBaseIsp * _modifiedCurrentPropellantIspMultiplier * CurrentPropellantThrustMultiplier * ThrottleModifiedIsp(); _spaceFuelFlowRate = _maxIsp <= 0 ? 0 : curThrustInSpace / _maxIsp / GameConstants.STANDARD_GRAVITY; var maxThrustWithCurrentThrottle = curThrustInSpace * throtteModifier; calculated_thrust = Current_propellant.SupportedEngines == 8 ? maxThrustWithCurrentThrottle : Math.Max(maxThrustWithCurrentThrottle - (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 = _atmosphereThrustEfficiency * _spaceFuelFlowRate * _fuelFlowModifier; _attachedEngine.maxFuelFlow = (float)Math.Max(_maxFuelFlowRate, 0.00000000001); } else { UpdateIsp(1); _atmosphereThrustEfficiency = 0; _attachedEngine.maxFuelFlow = 0.00000000001f; } 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 : curThrustInSpace / 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 OnFixedUpdateResourceSuppliable(double fixedDeltaTime) { temperatureStr = part.temperature.ToString("F0") + "K / " + part.maxTemp.ToString("F0") + "K"; MinIsp = BaseFloatCurve.Evaluate((float)altitude); resourceBuffers.UpdateVariable(ResourceSettings.Config.WasteHeatInMegawatt, part.mass); resourceBuffers.UpdateBuffers(); if (curEngineT == null || !curEngineT.isEnabled) { return; } if (curEngineT.requestedThrottle > 0) { if (radHazard && rad_safety_features) { ShutDown(Localizer.Format("#LOC_KSPIE_FusionECU2_PostMsg2"));//"Engines throttled down as they presently pose a radiation hazard" } } KillKerbalsWithRadiation(fusionRatio); hasIspThrottling = HasIspThrottling(); ShowIspThrottle = hasIspThrottling; availablePower = Math.Max(GetResourceAvailability(ResourceSettings.Config.ElectricPowerInMegawatt), GetAvailablePrioritizedStableSupply(ResourceSettings.Config.ElectricPowerInMegawatt)); 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, ResourceSettings.Config.ElectricPowerInMegawatt); 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, ResourceSettings.Config.ElectricPowerInMegawatt); } // Lasers produce Wasteheat if (!CheatOptions.IgnoreMaxTemperature && laserWasteheat > 0) { SupplyFnResourcePerSecondWithMax(laserWasteheat, currentMaximumPowerRequirement * inefficiency, ResourceSettings.Config.WasteHeatInMegawatt); } // The Absorbed wasteheat from Fusion rateMultplier = hasIspThrottling ? Math.Pow(SelectedIsp / MinIsp, 2) : 1; neutronbsorbionBonus = hasIspThrottling ? 1 - NeutronAbsorptionFractionAtMinIsp * (1 - ((SelectedIsp - MinIsp) / (MaxIsp - MinIsp))) : 0.5; absorbedWasteheat = FusionWasteHeat * fusionRatio * curEngineT.currentThrottle * neutronbsorbionBonus; SupplyFnResourcePerSecond(absorbedWasteheat, ResourceSettings.Config.WasteHeatInMegawatt); SetRatios(); currentIsp = hasIspThrottling ? SelectedIsp : MinIsp; UpdateAtmosphereCurve(currentIsp); maximumThrust = hasIspThrottling ? MaximumThrust : FullTrustMaximum; // Update FuelFlow maxFuelFlow = fusionRatio * maximumThrust / currentIsp / PhysicsGlobals.GravitationalAcceleration; 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 / PhysicsGlobals.GravitationalAcceleration; 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; }
public override void OnStart(StartState state) { String[] resourcesToSupply = { ResourceManager.FNRESOURCE_WASTEHEAT }; this.resources_to_supply = resourcesToSupply; base.OnStart(state); radiatedThermalPower = 0; convectedThermalPower = 0; CurrentRadiatorTemperature = 0; update_count = 0; radiator_deploy_delay = 0; explode_counter = 0; DetermineGenerationType(); maxRadiatorTemperature = (float)MaxRadiatorTemperature; if (hasSurfaceAreaUpgradeTechReq) { part.emissiveConstant = 1.6; } radiatorType = RadiatorType; effectiveRadiatorArea = EffectiveRadiatorArea; deployRadiatorEvent = Events["DeployRadiator"]; retractRadiatorEvent = Events["RetractRadiator"]; thermalPowerConvStrField = Fields["thermalPowerConvStr"]; radiatorIsEnabledField = Fields["radiatorIsEnabled"]; isAutomatedField = Fields["isAutomated"]; pivotEnabledField = Fields["pivotEnabled"]; var preventDeplyField = Fields["preventShieldedDeploy"]; preventDeplyField.guiActive = isDeployable; preventDeplyField.guiActiveEditor = isDeployable; Actions["DeployRadiatorAction"].guiName = Events["DeployRadiator"].guiName = "Deploy Radiator"; Actions["ToggleRadiatorAction"].guiName = String.Format("Toggle Radiator"); Actions["RetractRadiatorAction"].guiName = "Retract Radiator"; Events["RetractRadiator"].guiName = "Retract Radiator"; var myAttachedEngine = part.FindModuleImplementing <ModuleEngines>(); if (myAttachedEngine == null) { partMass = part.mass; Fields["partMass"].guiActiveEditor = true; Fields["partMass"].guiActive = true; Fields["convectiveBonus"].guiActiveEditor = true; } if (!String.IsNullOrEmpty(thermalAnim)) { heatStates = PluginHelper.SetUpAnimation(thermalAnim, this.part); if (heatStates != null) { SetHeatAnimationRatio(0); } } deployAnimation = part.FindModelAnimators(animName).FirstOrDefault(); if (deployAnimation != null) { deployAnimation[animName].layer = 1; deployAnimation[animName].speed = 0; deployAnimation[animName].normalizedTime = radiatorIsEnabled ? 1 : 0; } _moduleActiveRadiator = part.FindModuleImplementing <ModuleActiveRadiator>(); if (_moduleActiveRadiator != null) { _moduleActiveRadiator.Events["Activate"].guiActive = false; _moduleActiveRadiator.Events["Shutdown"].guiActive = false; } _moduleDeployableRadiator = part.FindModuleImplementing <ModuleDeployableRadiator>(); if (_moduleDeployableRadiator != null) { radiatorState = _moduleDeployableRadiator.deployState; } var radiatorfield = Fields["radiatorIsEnabled"]; radiatorfield.guiActive = showControls; radiatorfield.guiActiveEditor = showControls; radiatorfield.OnValueModified += radiatorIsEnabled_OnValueModified; var automatedfield = Fields["isAutomated"]; automatedfield.guiActive = showControls; automatedfield.guiActiveEditor = showControls; var pivotfield = Fields["pivotEnabled"]; pivotfield.guiActive = showControls; pivotfield.guiActiveEditor = showControls; if (_moduleActiveRadiator != null) { _maxEnergyTransfer = radiatorArea * 1000 * Math.Pow(1 + ((int)CurrentGenerationType), 2); _moduleActiveRadiator.maxEnergyTransfer = _maxEnergyTransfer; _moduleActiveRadiator.overcoolFactor = 0.20 + ((int)CurrentGenerationType * 0.025); } if (state == StartState.Editor) { return; } var depth = 0; star = FlightGlobals.currentMainBody; while (depth < 10 && star != null && star.GetTemperature(0) < 2000) { star = star.referenceBody; depth++; } if (star == null) { star = FlightGlobals.Bodies[0]; } if (ResearchAndDevelopment.Instance != null) { upgradeCostStr = ResearchAndDevelopment.Instance.Science + "/" + upgradeCost.ToString("0") + " Science"; } renderArray = part.FindModelComponents <Renderer>().ToArray(); if (radiatorInit == false) { radiatorInit = true; } part.maxTemp = maxRadiatorTemperature; radiatorTempStr = maxRadiatorTemperature + "K"; maxVacuumTemperature = String.IsNullOrEmpty(surfaceAreaUpgradeTechReq) ? Math.Min((float)PluginHelper.RadiatorTemperatureMk3, maxRadiatorTemperature) : Math.Min(maxVacuumTemperature, maxRadiatorTemperature); maxAtmosphereTemperature = String.IsNullOrEmpty(surfaceAreaUpgradeTechReq) ? Math.Min((float)PluginHelper.RadiatorTemperatureMk3, maxRadiatorTemperature) : Math.Min(maxAtmosphereTemperature, maxRadiatorTemperature); resourceBuffers = new ResourceBuffers(); resourceBuffers.AddConfiguration(new ResourceBuffers.TimeBasedConfig(ResourceManager.FNRESOURCE_WASTEHEAT, wasteHeatMultiplier, 2.0e+6)); resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, this.part.mass); resourceBuffers.Init(this.part); }
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); 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 * Math.Pow(deltaTemp, 4) * 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 * Math.Pow(Math.Max(deltaTemp - external_temperature, 0), 4) * 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 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 / PluginHelper.GravityConstant; 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 / PluginHelper.GravityConstant; 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; }
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 OnStart(PartModule.StartState state) { String[] resources_to_supply = { ResourceManager.FNRESOURCE_MEGAJOULES, ResourceManager.FNRESOURCE_WASTEHEAT, ResourceManager.FNRESOURCE_THERMALPOWER, ResourceManager.FNRESOURCE_CHARGED_PARTICLES }; this.resources_to_supply = resources_to_supply; resourceBuffers = new ResourceBuffers(); resourceBuffers.AddConfiguration(new ResourceBuffers.TimeBasedConfig(ResourceManager.FNRESOURCE_WASTEHEAT, wasteHeatMultiplier, 2.0e+5, true)); resourceBuffers.AddConfiguration(new ResourceBuffers.TimeBasedConfig(ResourceManager.FNRESOURCE_MEGAJOULES)); resourceBuffers.AddConfiguration(new ResourceBuffers.TimeBasedConfig(ResourceManager.STOCK_RESOURCE_ELECTRICCHARGE, 1000 / powerOutputMultiplier)); resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, this.part.mass); resourceBuffers.Init(this.part); base.OnStart(state); targetMass = part.prefabMass * storedMassMultiplier; initialMass = part.prefabMass * storedMassMultiplier; if (initialMass == 0) { initialMass = part.prefabMass; } if (targetMass == 0) { targetMass = part.prefabMass; } InitializeEfficiency(); Fields["powerCapacity"].guiActiveEditor = !isLimitedByMinThrotle; Fields["partMass"].guiActive = Fields["partMass"].guiActiveEditor = calculatedMass; Fields["powerPercentage"].guiActive = Fields["powerPercentage"].guiActiveEditor = showSpecialisedUI; Fields["radius"].guiActiveEditor = showSpecialisedUI; if (state == StartState.Editor) { if (this.HasTechsRequiredToUpgrade()) { isupgraded = true; hasrequiredupgrade = true; upgradePartModule(); } part.OnEditorAttach += OnEditorAttach; part.OnEditorDetach += OnEditorDetach; part.OnEditorDestroy += OnEditorDetach; part.OnJustAboutToBeDestroyed += OnDestroyed; part.OnJustAboutToDie += OnDestroyed; FindAndAttachToPowerSource(); return; } if (this.HasTechsRequiredToUpgrade()) { hasrequiredupgrade = true; } // only force activate if no certain partmodules are not present and not limited by minimum throtle if (!isLimitedByMinThrotle && part.FindModuleImplementing <MicrowavePowerReceiver>() == null) { Debug.Log("[KSPI] - Generator on " + part.name + " was Force Activated"); part.force_activate(); } anim = part.FindModelAnimators(animName).FirstOrDefault(); if (anim != null) { anim[animName].layer = 1; if (!IsEnabled) { anim[animName].normalizedTime = 1; anim[animName].speed = -1; } else { anim[animName].normalizedTime = 0; anim[animName].speed = 1; } anim.Play(); } if (generatorInit == false) { IsEnabled = true; } if (isupgraded) { upgradePartModule(); } FindAndAttachToPowerSource(); UpdateHeatExchangedThrustDivisor(); }
// ReSharper disable once UnusedMember.Global public override void OnFixedUpdateResourceSuppliable(double fixedDeltaTime) { if (_attachedEngine == null || !HighLogic.LoadedSceneIsFlight) { return; } if (_initializationCountdown > 0) { _initializationCountdown--; } if (_vesselChangedSIOCountdown > 0) { _vesselChangedSIOCountdown--; } CalculateTimeDialation(); if (_attachedEngine is ModuleEnginesFX) { GetAllPropellants().ForEach(prop => part.Effect(prop.ParticleFXName, 0, -1)); // set all FX to zero } if (CurrentPropellant == null) { return; } _resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, (double)(decimal)part.mass); _resourceBuffers.UpdateBuffers(); if (!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; totalPowerSupplied = getTotalPowerSupplied(ResourceManager.FNRESOURCE_MEGAJOULES); megaJoulesBarRatio = getResourceBarRatio(ResourceManager.FNRESOURCE_MEGAJOULES); effectiveResourceThrotling = megaJoulesBarRatio > 0.1 ? 1 : megaJoulesBarRatio * 10; availableMaximumPower = getAvailablePrioritisedStableSupply(ResourceManager.FNRESOURCE_MEGAJOULES); availableCurrentPower = getAvailablePrioritisedCurrentSupply(ResourceManager.FNRESOURCE_MEGAJOULES); maximumAvailablePowerForEngine = availableMaximumPower * _electrical_share_f; currentAvailablePowerForEngine = availableCurrentPower * _electrical_share_f; maximumThrustFromPower = EvaluateMaxThrust(maximumAvailablePowerForEngine); currentThrustFromPower = EvaluateMaxThrust(currentAvailablePowerForEngine); effectiveMaximumAvailablePowerForEngine = maximumAvailablePowerForEngine * effectiveResourceThrotling; effectiveCurrentAvailablePowerForEngine = currentAvailablePowerForEngine * effectiveResourceThrotling; modifiedMaximumPowerForEngine = effectiveMaximumAvailablePowerForEngine * modifiedThrotte; modifiedCurrentPowerForEngine = effectiveCurrentAvailablePowerForEngine * modifiedThrotte; maximum_power_request = CheatOptions.InfiniteElectricity ? modifiedMaximumPowerForEngine : currentPropellantEfficiency <= 0 ? 0 : Math.Min(modifiedMaximumPowerForEngine, modifiedMaxThrottlePower); current_power_request = CheatOptions.InfiniteElectricity ? modifiedCurrentPowerForEngine : currentPropellantEfficiency <= 0 ? 0 : Math.Min(modifiedCurrentPowerForEngine, modifiedMaxThrottlePower); // request electric power actualPowerReceived = CheatOptions.InfiniteElectricity ? current_power_request : consumeFNResourcePerSecond(current_power_request, maximum_power_request, ResourceManager.FNRESOURCE_MEGAJOULES); simulatedPowerReceived = Math.Min(effectiveMaximumAvailablePowerForEngine, maxEffectivePower); // produce waste heat var heatModifier = (1 - currentPropellantEfficiency) * CurrentPropellant.WasteHeatMultiplier; var heatToProduce = actualPowerReceived * heatModifier; var maxHeatToProduce = maximumAvailablePowerForEngine * heatModifier; _heat_production_f = CheatOptions.IgnoreMaxTemperature ? heatToProduce : supplyFNResourcePerSecondWithMax(heatToProduce, maxHeatToProduce, 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 = CurrentPropellant.SupportedEngines == 8 ? maxThrustWithCurrentThrottle : Math.Max(maxThrustWithCurrentThrottle - (exitArea * vessel.staticPressurekPa), 0); simulated_max_thrust = CurrentPropellant.SupportedEngines == 8 ? simulatedThrustInSpace : Math.Max(simulatedThrustInSpace - (exitArea * vessel.staticPressurekPa), 0); var throttle = _attachedEngine.getIgnitionState && _attachedEngine.currentThrottle > 0 ? Math.Max(_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 = _attachedEngine.realIsp; thrust_d = _attachedEngine.requestedMassFlow * GameConstants.STANDARD_GRAVITY * _ispPersistent; ratioHeadingVersusRequest = 0; } else if (this.vessel.packed && _attachedEngine.isEnabled && FlightGlobals.ActiveVessel == vessel && _initializationCountdown == 0) { _warpToReal = true; // Set to true for transition to realtime thrust_d = calculated_thrust; ratioHeadingVersusRequest = _attachedEngine.PersistHeading(_vesselChangedSIOCountdown > 0, ratioHeadingVersusRequest == 1); if (ratioHeadingVersusRequest == 1) { 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 = _attachedEngine.maxFuelFlow * _attachedEngine.currentThrottle; var maxFuelFlowRate = _attachedEngine.maxThrust / _attachedEngine.realIsp / GameConstants.STANDARD_GRAVITY; effectPower = Math.Min(1, particleEffectMult * (engineFuelFlow / maxFuelFlowRate)); _particleFXName = String.IsNullOrEmpty(EffectName) ? CurrentPropellant.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); } }
// 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.GetTotalMass()); } 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 : throtle_max_thrust / engineIsp / PluginHelper.GravityConstant; vacuumPlasmaResource.maxAmount = Math.Max(0.0000001, calculatedConsumptionInTon * 200 * TimeWarp.fixedDeltaTime); part.RequestResource(InterstellarResourcesConfiguration.Instance.VacuumPlasma, -vacuumPlasmaResource.maxAmount); } }
public override void OnStart(StartState state) { if (state.ToString().Contains(StartState.PreLaunch.ToString())) { Debug.Log("[KSPI]: PreLaunch uses InitialGearRatio:" + InitialGearRatio); SelectedIsp = ((MaxIsp - MinIsp) * Math.Max(0, Math.Min(1, InitialGearRatio))) + MinIsp; } Fields[nameof(selectedFuel)].guiName = fuelSwitchName; Fields[nameof(currentMaximumPowerRequirement)].guiActive = powerRequirement > 0; Fields[nameof(laserWasteheat)].guiActive = powerRequirement > 0 && fusionWasteHeat > 0; Fields[nameof(absorbedWasteheat)].guiActive = powerRequirement > 0 && fusionWasteHeat > 0; Fields[nameof(fusionRatio)].guiActive = powerRequirement > 0; Fields[nameof(powerRequirementMax)].guiActiveEditor = powerRequirement > 0; Fields[nameof(fusionWasteHeatMax)].guiActiveEditor = fusionWasteHeat > 0; part.maxTemp = maxTemp; part.thermalMass = 1; part.thermalMassModifier = 1; curEngineT = part.FindModuleImplementing <ModuleEngines>(); if (curEngineT == null) { Debug.LogError("[KSPI]: FusionEngine OnStart Engine not found"); return; } BaseFloatCurve = curEngineT.atmosphereCurve; curveMaxISP = GetMaxKey(BaseFloatCurve); if (hasMultipleConfigurations) { FcSetup(); } InitializeKerbalismEmitter(); DetermineTechLevel(); powerRequirementMax = PowerRequirementMaximum; fusionWasteHeatMax = FusionWasteHeat; resourceBuffers = new ResourceBuffers(); resourceBuffers.AddConfiguration(new WasteHeatBufferConfig(wasteHeatMultiplier, 1.0e+4, true)); resourceBuffers.UpdateVariable(ResourceSettings.Config.WasteHeatInMegawatt, part.mass); resourceBuffers.Init(this.part); if (state != StartState.Editor) { part.emissiveConstant = maxTempatureRadiators > 0 ? 1 - coldBathTemp / maxTempatureRadiators : 0.01; } base.OnStart(state); var localIspField = Fields[nameof(VistaECU2.localIsp)]; if (localIspField != null) { localIspField.guiActive = selectableIsp; localIspField.guiActiveEditor = selectableIsp; } }
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 / PluginHelper.GravityConstant; 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 / PluginHelper.GravityConstant; 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 OnFixedUpdate() { temperatureStr = part.temperature.ToString("0.00") + "K / " + part.maxTemp.ToString("0.00") + "K"; MinIsp = OrigFloatCurve.Evaluate((float)Altitude); // part.ona if (curEngineT == null) { return; } throttle = curEngineT.currentThrottle > MinThrottleRatio ? curEngineT.currentThrottle : 0; if (throttle > 0) { if (vessel.atmDensity > maxAtmosphereDensity) { ShutDown(Localizer.Format("#LOC_KSPIE_VistaEngineControllerAdv_PostMsg1"));//"Inertial Fusion cannot operate in atmosphere!" } if (radhazard && rad_safety_features) { ShutDown(Localizer.Format("#LOC_KSPIE_VistaEngineControllerAdv_PostMsg2"));//"Engines throttled down as they presently pose a radiation hazard" } if (SelectedIsp <= 10) { ShutDown(Localizer.Format("#LOC_KSPIE_VistaEngineControllerAdv_PostMsg4"));//"Engine Stall" } } KillKerbalsWithRadiation(throttle); resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, this.part.mass); resourceBuffers.UpdateBuffers(); if (throttle > 0) { // Calculate Fusion Ratio enginePowerRequirement = CurrentPowerRequirement; var recievedPowerFixed = CheatOptions.InfiniteElectricity ? enginePowerRequirement : consumeFNResourcePerSecond(enginePowerRequirement, ResourceManager.FNRESOURCE_MEGAJOULES); var plasma_ratio = recievedPowerFixed / enginePowerRequirement; fusionRatio = plasma_ratio >= 1 ? 1 : plasma_ratio > 0.75f ? Mathf.Pow((float)plasma_ratio, 6) : 0; laserWasteheat = recievedPowerFixed * (1 - LaserEfficiency); // Lasers produce Wasteheat if (!CheatOptions.IgnoreMaxTemperature) { supplyFNResourcePerSecond(enginePowerRequirement, ResourceManager.FNRESOURCE_WASTEHEAT); } // The Absorbed wasteheat from Fusion var rateMultplier = MinIsp / SelectedIsp; var neutronbsorbionBonus = 1 - NeutronAbsorptionFractionAtMinIsp * (1 - ((SelectedIsp - MinIsp) / (MaxIsp - MinIsp))); absorbedWasteheat = FusionWasteHeat * wasteHeatMultiplier * fusionRatio * throttle * neutronbsorbionBonus; 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; UpdateISP(); // Update FuelFlow var maxFuelFlow = fusionRatio * MaximumThrust / currentIsp / GameConstants.STANDARD_GRAVITY; maximumThrust = (float)MaximumThrust; curEngineT.maxFuelFlow = (float)maxFuelFlow; curEngineT.maxThrust = maximumThrust; if (!curEngineT.getFlameoutState && plasma_ratio < 0.75 && recievedPowerFixed > 0) { curEngineT.status = Localizer.Format("#LOC_KSPIE_VistaEngineControllerAdv_statu");//"Insufficient Electricity" } } else { enginePowerRequirement = 0; absorbedWasteheat = 0; laserWasteheat = 0; fusionRatio = 0; var currentIsp = SelectedIsp; UpdateISP(); curEngineT.maxThrust = (float)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 = (float)FNRadiator.getAverageRadiatorTemperatureForVessel(vessel); maxTempatureRadiators = (float)FNRadiator.getAverageMaximumRadiatorTemperatureForVessel(vessel); radiatorPerformance = Mathf.Max(1 - (coldBathTemp / maxTempatureRadiators), 0.000001f); partEmissiveConstant = (float)part.emissiveConstant; }
public override void OnStart(PartModule.StartState state) { if (state == StartState.Editor) { return; } _mjSolarSupplyField = Fields[nameof(mjSolarSupply)]; _mjMaxSupplyField = Fields[nameof(mjMaxSupply)]; if (part.Modules.Contains("SolarPanelFixer")) { _solarPanelFixer = part.Modules["SolarPanelFixer"]; _fieldKerbalismNominalRate = _solarPanelFixer.Fields["nominalRate"]; _fieldKerbalismPanelStatus = _solarPanelFixer.Fields["panelStatus"]; } // calculate Astronomical unit on homeworld semiMajorAxis when missing if (astronomicalUnit <= 0) { astronomicalUnit = FlightGlobals.GetHomeBody().orbit.semiMajorAxis; } _microwavePowerReceiver = part.FindModuleImplementing <BeamedPowerReceiver>(); _solarPanel = part.FindModuleImplementing <ModuleDeployableSolarPanel>(); if (_solarPanel == null || _solarPanel.chargeRate <= 0) { return; } if (part.FindModuleImplementing <ModuleJettison>() == null) { Debug.Log("[KSPI]: FNSolarPanelWasteHeatModule Force Activated " + part.name); part.force_activate(); } string[] resourcesToSupply = { ResourceSettings.Config.ElectricPowerInMegawatt }; this.resourcesToSupply = resourcesToSupply; base.OnStart(state); _outputResource = _solarPanel.resHandler.outputResources.FirstOrDefault(); resourceName = _solarPanel.resourceName; if (resourceName == ResourceSettings.Config.ElectricPowerInMegawatt) { _outputType = ResourceType.megajoule; } else if (resourceName == ResourceSettings.Config.ElectricPowerInKilowatt) { _outputType = ResourceType.electricCharge; } else { _outputType = ResourceType.other; } // only manage power buffer when microwave receiver is not available if (_outputType != ResourceType.other && _microwavePowerReceiver == null) { _resourceBuffers = new ResourceBuffers(); _resourceBuffers.AddConfiguration(new ResourceBuffers.TimeBasedConfig(ResourceSettings.Config.ElectricPowerInMegawatt)); _resourceBuffers.UpdateVariable(ResourceSettings.Config.ElectricPowerInMegawatt, _outputType == ResourceType.electricCharge ? _solarPanel.chargeRate / GameConstants.ecPerMJ : _solarPanel.chargeRate); if (!Kerbalism.IsLoaded) { _resourceBuffers.AddConfiguration(new ResourceBuffers.TimeBasedConfig(ResourceSettings.Config.ElectricPowerInKilowatt)); _resourceBuffers.UpdateVariable(ResourceSettings.Config.ElectricPowerInKilowatt, _outputType == ResourceType.electricCharge ? _solarPanel.chargeRate : _solarPanel.chargeRate * GameConstants.ecPerMJ); } _resourceBuffers.Init(part); } _stars = KopernicusHelper.Stars; }
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; } if (curEngineT.currentThrottle > 0) { if (maxAtmosphereDensity >= 0 && vessel.atmDensity > 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 (SelectedIsp <= 10) { 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)); if (curEngineT.currentThrottle > 0) { requiredPowerPerSecond = curEngineT.currentThrottle * CurrentMaximumPowerRequirement; 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; 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 * 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; curEngineT.maxFuelFlow = (float)maxFuelFlow; curEngineT.maxThrust = (float)maximumThrust; 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; requiredPowerPerSecond = CurrentMaximumPowerRequirement; 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; curEngineT.maxFuelFlow = (float)maxFuelFlow; curEngineT.maxThrust = (float)maximumThrust; SetRatios(); } coldBathTemp = FNRadiator.getAverageRadiatorTemperatureForVessel(vessel); maxTempatureRadiators = FNRadiator.getAverageMaximumRadiatorTemperatureForVessel(vessel); radiatorPerformance = Math.Max(1 - (coldBathTemp / maxTempatureRadiators), 0.000001); partEmissiveConstant = part.emissiveConstant; base.OnFixedUpdate(); }
private void UpdateElectricChargeBuffer(double currentPowerUsage) { resourceBuffers.UpdateVariable(InterstellarResourcesConfiguration.Instance.ElectricCharge, currentPowerUsage); resourceBuffers.UpdateBuffers(); }
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; if (throttle > 0) { // Calculate Fusion Ratio enginePowerRequirement = CurrentPowerRequirement; var requestedPowerPerSecond = enginePowerRequirement; var availablePower = getAvailableStableSupply(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); fusionRatio = requestedPowerPerSecond > 0 ? recievedPowerPerSecond / requestedPowerPerSecond : 1; laserWasteheat = recievedPowerPerSecond * (1 - LaserEfficiency); // Lasers produce Wasteheat if (!CheatOptions.IgnoreMaxTemperature) { 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 var maxFuelFlow = fusionRatio * maximumThrust / currentIsp / GameConstants.STANDARD_GRAVITY; curEngineT.maxFuelFlow = (float)maxFuelFlow; curEngineT.maxThrust = (float)maximumThrust; if (!curEngineT.getFlameoutState && fusionRatio < 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; rateMultplier = hasIspThrottling ? Math.Pow(SelectedIsp / MinIsp, 2) : 1; var maxFuelFlow = 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(); }
public override void OnStart(StartState state) { String[] resourcesToSupply = { ResourceManager.FNRESOURCE_WASTEHEAT }; this.resources_to_supply = resourcesToSupply; base.OnStart(state); radiatedThermalPower = 0; convectedThermalPower = 0; CurrentRadiatorTemperature = 0; radiator_deploy_delay = 0; DetermineGenerationType(); isGraphene = !String.IsNullOrEmpty(surfaceAreaUpgradeTechReq); maximumRadiatorTempInSpace = (float)RadiatorProperties.RadiatorTemperatureMk6; maxSpaceTempBonus = maximumRadiatorTempInSpace - maximumRadiatorTempAtOneAtmosphere; temperatureRange = maximumRadiatorTempInSpace - drapperPoint; kspShader = Shader.Find(kspShaderLocation); maxRadiatorTemperature = (float)MaxRadiatorTemperature; part.heatConvectiveConstant = convectiveBonus; if (hasSurfaceAreaUpgradeTechReq) { part.emissiveConstant = 1.6; } radiatorType = RadiatorType; effectiveRadiatorArea = EffectiveRadiatorArea; stefanArea = PhysicsGlobals.StefanBoltzmanConstant * effectiveRadiatorArea * 1e-6; startWithCircradiator = part.name.StartsWith("circradiator"); startWithRadialRadiator = part.name.StartsWith("RadialRadiator"); startWithLargeFlatRadiator = part.name.StartsWith("LargeFlatRadiator"); deployRadiatorEvent = Events["DeployRadiator"]; retractRadiatorEvent = Events["RetractRadiator"]; thermalPowerConvStrField = Fields["thermalPowerConvStr"]; radiatorIsEnabledField = Fields["radiatorIsEnabled"]; isAutomatedField = Fields["isAutomated"]; pivotEnabledField = Fields["pivotEnabled"]; var preventDeplyField = Fields["preventShieldedDeploy"]; preventDeplyField.guiActive = isDeployable; preventDeplyField.guiActiveEditor = isDeployable; Actions["DeployRadiatorAction"].guiName = Events["DeployRadiator"].guiName = "Deploy Radiator"; Actions["ToggleRadiatorAction"].guiName = String.Format("Toggle Radiator"); Actions["RetractRadiatorAction"].guiName = "Retract Radiator"; Events["RetractRadiator"].guiName = "Retract Radiator"; var myAttachedEngine = part.FindModuleImplementing <ModuleEngines>(); if (myAttachedEngine == null) { partMass = part.mass; Fields["partMass"].guiActiveEditor = true; Fields["partMass"].guiActive = true; Fields["convectiveBonus"].guiActiveEditor = true; } if (!String.IsNullOrEmpty(thermalAnim)) { heatStates = PluginHelper.SetUpAnimation(thermalAnim, this.part); if (heatStates != null) { SetHeatAnimationRatio(0); } } deployAnimation = part.FindModelAnimators(animName).FirstOrDefault(); if (deployAnimation != null) { deployAnimation[animName].layer = 1; deployAnimation[animName].speed = 0; deployAnimation[animName].normalizedTime = radiatorIsEnabled ? 1 : 0; } _moduleActiveRadiator = part.FindModuleImplementing <ModuleActiveRadiator>(); if (_moduleActiveRadiator != null) { _moduleActiveRadiator.Events["Activate"].guiActive = false; _moduleActiveRadiator.Events["Shutdown"].guiActive = false; } _moduleDeployableRadiator = part.FindModuleImplementing <ModuleDeployableRadiator>(); if (_moduleDeployableRadiator != null) { radiatorState = _moduleDeployableRadiator.deployState; } var radiatorfield = Fields["radiatorIsEnabled"]; radiatorfield.guiActive = showControls; radiatorfield.guiActiveEditor = showControls; radiatorfield.OnValueModified += radiatorIsEnabled_OnValueModified; var automatedfield = Fields["isAutomated"]; automatedfield.guiActive = showControls; automatedfield.guiActiveEditor = showControls; var pivotfield = Fields["pivotEnabled"]; pivotfield.guiActive = showControls; pivotfield.guiActiveEditor = showControls; if (_moduleActiveRadiator != null) { _maxEnergyTransfer = radiatorArea * PhysicsGlobals.StefanBoltzmanConstant * Math.Pow(MaxRadiatorTemperature, 4) * 0.001; _moduleActiveRadiator.maxEnergyTransfer = _maxEnergyTransfer; _moduleActiveRadiator.overcoolFactor = 0.20 + ((int)CurrentGenerationType * 0.025); if (radiatorIsEnabled) { _moduleActiveRadiator.Activate(); } else { _moduleActiveRadiator.Shutdown(); } } if (state == StartState.Editor) { return; } if (isAutomated && !isDeployable) { ActivateRadiator(); } for (var i = 0; i < 20; i++) { radTempQueue.Enqueue(currentRadTemp); } InitializeTemperatureColorChannels(); ApplyColorHeat(); if (ResearchAndDevelopment.Instance != null) { upgradeCostStr = ResearchAndDevelopment.Instance.Science + "/" + upgradeCost.ToString("0") + " Science"; } renderArray = part.FindModelComponents <Renderer>().ToArray(); if (radiatorInit == false) { radiatorInit = true; } radiatorTempStr = maxRadiatorTemperature + "K"; maxVacuumTemperature = isGraphene ? Math.Min(maxVacuumTemperature, maxRadiatorTemperature) : Math.Min(RadiatorProperties.RadiatorTemperatureMk4, maxRadiatorTemperature); maxAtmosphereTemperature = isGraphene ? Math.Min(maxAtmosphereTemperature, maxRadiatorTemperature) : Math.Min(RadiatorProperties.RadiatorTemperatureMk3, maxRadiatorTemperature); UpdateMaxCurrentTemperature(); if (keepMaxPartTempEqualToMaxRadiatorTemp) { var partSkinTemperature = Math.Min(part.skinTemperature, maxCurrentRadiatorTemperature * 0.99); if (double.IsNaN(partSkinTemperature) == false) { part.skinTemperature = partSkinTemperature; } var partTemperature = Math.Min(part.temperature, maxCurrentRadiatorTemperature * 0.99); if (double.IsNaN(partTemperature) == false) { part.temperature = partTemperature; } if (double.IsNaN(maxCurrentRadiatorTemperature) == false) { part.skinMaxTemp = maxCurrentRadiatorTemperature; part.maxTemp = maxCurrentRadiatorTemperature; } } if (maintainResourceBuffers) { resourceBuffers = new ResourceBuffers(); resourceBuffers.AddConfiguration(new ResourceBuffers.TimeBasedConfig(ResourceManager.FNRESOURCE_WASTEHEAT, wasteHeatMultiplier, 2.0e+6)); resourceBuffers.UpdateVariable(ResourceManager.FNRESOURCE_WASTEHEAT, this.part.mass); resourceBuffers.Init(this.part); } }