void FixPressure(FloatCurve curve, double topLayer) { List<double[]> list = ReadCurve(curve); /* Avoid Bad Curves ==> */ if (list.Count < 2) { UnityEngine.Debug.Log("SigmaLog: This pressure curve has " + (list.Count == 0 ? "no keys" : "just one key") + ". I don't know what you expect me to do with that."); return; } double maxAltitude = list.Last()[0]; bool smoothEnd = list.Last()[1] == 0 && list.Count > 2; double smoothRange = list.Last()[0] - list[list.Count - 2][0]; if (smoothEnd) list.RemoveAt(list.Count - 1); if (topLayer > maxAltitude) { Extend(list, topLayer); maxAltitude = list.Last()[0]; } if (topLayer < maxAltitude) { Trim(list, topLayer); } if (smoothEnd) { Smooth(list, smoothRange); } curve.Load(WriteCurve(list)); }
public static Vector3 DoAeroForces(MissileLauncher ml, Vector3 targetPosition, float liftArea, float steerMult, Vector3 previousTorque, float maxTorque, float maxAoA) { if(DefaultLiftCurve == null) { DefaultLiftCurve = new FloatCurve(); DefaultLiftCurve.Add(0, .1f); DefaultLiftCurve.Add(8, .45f); DefaultLiftCurve.Add(19, 1); DefaultLiftCurve.Add(23, .9f); DefaultLiftCurve.Add(29, 0.85f); DefaultLiftCurve.Add(35, 0.65f); DefaultLiftCurve.Add(65, .6f); DefaultLiftCurve.Add(90, .7f); } if(DefaultDragCurve == null) { DefaultDragCurve = new FloatCurve(); DefaultDragCurve.Add(0, 0.00225f); DefaultDragCurve.Add(5, .0035f); DefaultDragCurve.Add(15, .015f); DefaultDragCurve.Add(29, .025f); DefaultDragCurve.Add(55, .3f); DefaultDragCurve.Add(90, .5f); } FloatCurve liftCurve = DefaultLiftCurve; FloatCurve dragCurve = DefaultDragCurve; return DoAeroForces(ml, targetPosition, liftArea, steerMult, previousTorque, maxTorque, maxAoA, liftCurve, dragCurve); }
public FloatCurve ProcessNodeAsFloatCurve(ConfigNode node) { FloatCurve resultCurve = new FloatCurve(); ConfigNode[] moduleNodeArray = node.GetNodes(nodeName); debugMessage("ProcessNodeAsFloatCurve: moduleNodeArray.length " + moduleNodeArray.Length); for (int k = 0; k < moduleNodeArray.Length; k++) { debugMessage("found node"); string[] valueArray = moduleNodeArray[k].GetValues(valueName); debugMessage("found " + valueArray.Length + " values"); for (int l = 0; l < valueArray.Length; l++) { string[] splitString = valueArray[l].Split(' '); try { Vector2 v2 = new Vector2(float.Parse(splitString[0]), float.Parse(splitString[1])); resultCurve.Add(v2.x, v2.y, 0, 0); } catch { Debug.Log("Error parsing vector2"); } } } return resultCurve; }
public HeatShieldType(ConfigNode node) { name = node.GetStringValue("name"); heatCurve = node.GetFloatCurve("heatCurve"); resourceMult = node.GetFloatValue("resourceMult", resourceMult); ablationMult = node.GetFloatValue("ablationMult", ablationMult); massMult = node.GetFloatValue("massMult", massMult); }
public SSTUSolarPanelStatic() { //the default stock temperatureEfficiencyCurve this.temperatureEfficCurve = new FloatCurve (); this.temperatureEfficCurve.Add (4f, 1.2f, 0f, -0.0005725837f); this.temperatureEfficCurve.Add (300f, 1f, -0.0008277721f, -0.0008277721f); this.temperatureEfficCurve.Add (1200f, 0.1f, -0.0003626566f, -0.0003626566f); this.temperatureEfficCurve.Add (2500f, 0.01f, 0f, 0f); }
public void Load(ConfigNode node) { if (node.HasValue("scope")) scope = node.GetValue("scope").ToLower(); if (node.HasNode("reliabilityCurve")) { reliabilityCurve = new FloatCurve(); reliabilityCurve.Load(node.GetNode("reliabilityCurve")); } }
public override void OnLoad(ConfigNode node) { base.OnLoad(node); if (node.HasNode("cycle")) { cycle = new FloatCurve(); cycle.Load(node.GetNode("cycle")); } else cycle = null; }
public override void OnStart(StartState state) { base.OnStart(state); intake = FindIntake(); if (machCurve == null) { Debug.LogError("ERROR: ModuleB9AnimateIntake on part " + part.name + ": machCurve is null!"); machCurve = new FloatCurve(); machCurve.Add(0f, 0f); } }
internal void add(float time, Vector2 xy) { if (curveX == null) { curveX = new FloatCurve(); } curveX.Add(time, xy.x); if (curveY == null) { curveY = new FloatCurve(); } curveY.Add(time, xy.y); }
public float EvaluateTempDiffCurve(float vel) { if(protoTempCurve != null) { tempAdditionFromVelocity = new FloatCurve(); foreach(CurveData data in protoTempCurve) { tempAdditionFromVelocity.Add(data.x, data.y, data.dy_dx, data.dy_dx); } protoTempCurve = null; } return tempAdditionFromVelocity.Evaluate(vel); }
public override void OnStart(StartState state) { base.OnStart(state); Part prefab = this.part.partInfo.partPrefab; foreach (PartModule pm in prefab.Modules) { TestFlightReliability_EngineCycle modulePrefab = pm as TestFlightReliability_EngineCycle; if (modulePrefab != null && modulePrefab.Configuration == configuration) { cycle = modulePrefab.cycle; } } }
public float EvaluateVelCpCurve(float vel) { if (protoVelCpCurve != null) { velCpCurve = new FloatCurve(); foreach (CurveData data in protoVelCpCurve) { velCpCurve.Add(data.x, data.y, data.dy_dx, data.dy_dx); } protoTempCurve = null; } return velCpCurve.Evaluate(vel); }
public override void CreateEngine() { rfSolver = new SolverRF(); if(!useAtmCurve) atmCurve = null; if(!useVelCurve) velCurve = null; if (!useThrustCurve) thrustCurve = null; // FIXME quick temp hax if (useAtmCurve) { if (maxEngineTemp == 0d) maxEngineTemp = 2000d; if (chamberNominalTemp == 0d) chamberNominalTemp = 950d; } else { if (maxEngineTemp == 0d) maxEngineTemp = 3600d; if (chamberNominalTemp == 0d) chamberNominalTemp = 3400d; if (tempGaugeMin == 0.8d) tempGaugeMin = 0.95d; } double thrustVariation = varyThrust * RFSettings.Instance.varyThrust; chamberNominalTemp *= (1d - thrustVariation); rfSolver.InitializeOverallEngineData( minFuelFlow, maxFuelFlow, atmosphereCurve, atmCurve, velCurve, throttleResponseRate, chamberNominalTemp, machLimit, machHeatMult, flowMultMin, flowMultCap, flowMultCapSharpness, multFlow, thrustVariation, (float)part.name.GetHashCode()); rfSolver.SetScale(scale); engineSolver = rfSolver; }
public override void OnAwake() { base.OnAwake(); if (thrustModifier == null) { thrustModifier = new FloatCurve(); thrustModifier.Add(0f, 1f); } if (cycle == null) { cycle = new FloatCurve(); cycle.Add(0f, 1f); } }
public void FixedUpdate() { if (HighLogic.LoadedSceneIsFlight && _attached_engine != null && _attached_reactor != null && _attached_engine.isOperational) { double max_power = _attached_reactor.MaximumChargedPower; if (_attached_reactor is InterstellarFusionReactor) max_power *= 0.9; double dilution_factor = 15000.0; double joules_per_amu = _attached_reactor.CurrentMeVPerChargedProduct * 1e6 * GameConstants.ELECTRON_CHARGE / dilution_factor; double isp = Math.Sqrt(joules_per_amu * 2.0 / GameConstants.ATOMIC_MASS_UNIT) / GameConstants.STANDARD_GRAVITY; FloatCurve new_isp = new FloatCurve(); new_isp.Add(0, (float)isp, 0, 0); _attached_engine.atmosphereCurve = new_isp; double charged_power_received = consumeFNResource(max_power * TimeWarp.fixedDeltaTime * _attached_engine.currentThrottle, FNResourceManager.FNRESOURCE_CHARGED_PARTICLES) / TimeWarp.fixedDeltaTime; consumeFNResource(charged_power_received * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_WASTEHEAT); double megajoules_received = consumeFNResource(charged_power_received * TimeWarp.fixedDeltaTime * 0.01, FNResourceManager.FNRESOURCE_MEGAJOULES)/TimeWarp.fixedDeltaTime; double megajoules_ratio = megajoules_received / charged_power_received / 0.01; megajoules_ratio = (double.IsNaN(megajoules_ratio) || double.IsInfinity(megajoules_ratio)) ? 0 : megajoules_ratio; double atmo_thrust_factor = Math.Min(1.0,Math.Max(1.0 - Math.Pow(vessel.atmDensity,0.2),0)); double exchanger_thrust_divisor = 1; if (radius > _attached_reactor.getRadius()) { exchanger_thrust_divisor = _attached_reactor.getRadius() * _attached_reactor.getRadius() / radius / radius; } else { exchanger_thrust_divisor = radius * radius / _attached_reactor.getRadius() / _attached_reactor.getRadius(); } double engineMaxThrust = 0.000000001; float power_ratio; if (max_power > 0) { power_ratio = (float)(charged_power_received / max_power); engineMaxThrust = Math.Max(2000.0 * charged_power_received*megajoules_ratio*atmo_thrust_factor*exchanger_thrust_divisor / isp / GameConstants.STANDARD_GRAVITY / _attached_engine.currentThrottle, 0.000000001); } if (!double.IsInfinity(engineMaxThrust) && !double.IsNaN(engineMaxThrust)) { _attached_engine.maxThrust = (float)engineMaxThrust; } else { _attached_engine.maxThrust = 0.000000001f; } } else if (_attached_engine != null) { _attached_engine.maxThrust = 0.000000001f; } }
// CONSTRUCTORS public TechLevel() { atmosphereCurve = new FloatCurve(); velocityCurve = new FloatCurve(); TWR = -1; thrustMultiplier = -1; massMultiplier = -1; minThrottleMultiplier = -1; gimbalRange = -1f; techRequired = ""; costMult = 1f; LoadGlobals(); }
public TechLevel(TechLevel t) { atmosphereCurve = t.atmosphereCurve; velocityCurve = t.velocityCurve; TWR = t.TWR; thrustMultiplier = t.thrustMultiplier; massMultiplier = t.massMultiplier; gimbalRange = t.gimbalRange; techRequired = t.techRequired; minThrottleMultiplier = t.minThrottleMultiplier; costMult = t.costMult; LoadGlobals(); }
public float EvaluateTempDiffCurve(float vel) { if(protoTempCurve != null) { tempAdditionFromVelocity = new FloatCurve(); Debug.Log("Building Temperature Curve Object..."); foreach(CurveData data in protoTempCurve) { tempAdditionFromVelocity.Add(data.x, data.y, data.dy_dx, data.dy_dx); } protoTempCurve = null; } return tempAdditionFromVelocity.Evaluate(vel); }
public override void OnAwake() { base.OnAwake(); if (heatCurve == null) { heatCurve = new FloatCurve(); heatCurve.Add(0, 0.00002f);//very minimal initial ablation factor heatCurve.Add(50, 0.00005f);//ramp it up fairly quickly though heatCurve.Add(150, 0.00015f); heatCurve.Add(500, 0.00050f); heatCurve.Add(750, 0.00075f); heatCurve.Add(1000, 0.00100f); heatCurve.Add(2000, 0.00400f); heatCurve.Add(3000, 0.00800f);//generally, things will explode before this point heatCurve.Add(10000, 0.05000f);//but just in case, continue the curve up to insane levels } }
public void FixedUpdate() { if (HighLogic.LoadedSceneIsFlight) { if (!active) { base.OnFixedUpdate(); } if (solarPanel != null) { double inv_square_mult = Math.Pow(Vector3d.Distance(FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBIN].transform.position, FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBOL].transform.position), 2) / Math.Pow(Vector3d.Distance(vessel.transform.position, FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBOL].transform.position), 2); FloatCurve satcurve = new FloatCurve(); satcurve.Add(0.0f, (float)inv_square_mult); solarPanel.powerCurve = satcurve; float solar_rate = solarPanel.flowRate * TimeWarp.fixedDeltaTime; float clamper = PluginHelper.IsSolarPanelHeatingClamped ? (float)Math.Min(Math.Max((Math.Sqrt(inv_square_mult) - 1.5), 0.0), 1.0) : 1.0f; float heat_rate = clamper * solar_rate * 0.5f / 1000.0f; if (getResourceBarRatio(FNResourceManager.FNRESOURCE_WASTEHEAT) >= 0.98 && solarPanel.panelState == ModuleDeployableSolarPanel.panelStates.EXTENDED && solarPanel.sunTracking) { solarPanel.Retract(); if (FlightGlobals.ActiveVessel == vessel) ScreenMessages.PostScreenMessage("Warning Dangerous Overheating Detected: Solar Panel retraction occuring NOW!", 5.0f, ScreenMessageStyle.UPPER_CENTER); return; } List<PartResource> prl = part.GetConnectedResources("ElectricCharge").ToList(); double current_charge = prl.Sum(pr => pr.amount); double max_charge = prl.Sum(pr => pr.maxAmount); var solar_supply = current_charge >= max_charge ? solar_rate / 1000.0f : 0; var solar_maxSupply = solar_rate / 1000.0f; supplyFNResourceFixedMax(solar_supply, solar_maxSupply, FNResourceManager.FNRESOURCE_MEGAJOULES); wasteheat_production_f = supplyFNResource(heat_rate, FNResourceManager.FNRESOURCE_WASTEHEAT) / TimeWarp.fixedDeltaTime * 1000.0f; } } }
public static float GetFlowModifier(bool atmChangeFlow, FloatCurve atmCurve, double atmDensity, FloatCurve velCurve, float machNumber, ref float maxMach) { float flowModifier = 1.0f; if (atmChangeFlow) { flowModifier = (float)(atmDensity / 1.225); if (atmCurve != null) { flowModifier = atmCurve.Evaluate(flowModifier); } } if (velCurve != null) { flowModifier = flowModifier * velCurve.Evaluate(machNumber); maxMach = velCurve.maxTime; } if (flowModifier < float.Epsilon) { flowModifier = float.Epsilon; } return flowModifier; }
public override void OnFixedUpdate() { base.OnFixedUpdate (); if (solarPanel != null) { float solar_rate = solarPanel.flowRate*TimeWarp.fixedDeltaTime; float heat_rate = solar_rate * 0.5f/1000.0f; double inv_square_mult = Math.Pow(Vector3d.Distance(FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBIN].transform.position, FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBOL].transform.position), 2) / Math.Pow(Vector3d.Distance(vessel.transform.position, FlightGlobals.Bodies[PluginHelper.REF_BODY_KERBOL].transform.position), 2); FloatCurve satcurve = new FloatCurve(); satcurve.Add(0.0f, (float)inv_square_mult); solarPanel.powerCurve = satcurve; if (getResourceBarRatio (FNResourceManager.FNRESOURCE_WASTEHEAT) >= 0.98 && solarPanel.panelState == ModuleDeployableSolarPanel.panelStates.EXTENDED && solarPanel.sunTracking) { solarPanel.Retract (); if (FlightGlobals.ActiveVessel == vessel) { ScreenMessages.PostScreenMessage ("Warning Dangerous Overheating Detected: Solar Panel retraction occuring NOW!", 5.0f, ScreenMessageStyle.UPPER_CENTER); } return; } wasteheat_production_f = supplyFNResource(heat_rate,FNResourceManager.FNRESOURCE_WASTEHEAT)/TimeWarp.fixedDeltaTime*1000.0f; } }
public override void OnStart(PartModule.StartState state) { base.OnStart(state); engine = part.GetComponent<ModuleEnginesFX>(); Propellant fuelPropellant = new Propellant(); foreach (Propellant prop in engine.propellants) { if (prop.name != "ElectricCharge") fuelPropellant = prop; } ThrustCurve = new FloatCurve(); ThrustCurve.Add(0f, engine.maxThrust); ThrustCurve.Add(minPressure, minThrust); AtmoCurve = new FloatCurve(); AtmoCurve.Add(0f, engine.atmosphereCurve.Evaluate(0f)); float rate = FindFlowRate (engine.maxThrust,engine.atmosphereCurve.Evaluate(0f),fuelPropellant); AtmoCurve.Add(1f,FindIsp(minThrust,rate,fuelPropellant)); }
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"); }
protected void UpdateFloatCurve(FloatCurve curve) { floatMod.curve = curve; UpdateModifierPanel(); }
public static EngineSim New(PartSim theEngine, ModuleEngines engineMod, double atmosphere, float machNumber, bool vectoredThrust, bool fullThrust, LogMsg log) { float maxFuelFlow = engineMod.maxFuelFlow; float minFuelFlow = engineMod.minFuelFlow; float thrustPercentage = engineMod.thrustPercentage; List <Transform> thrustTransforms = engineMod.thrustTransforms; List <float> thrustTransformMultipliers = engineMod.thrustTransformMultipliers; Vector3 vecThrust = CalculateThrustVector(vectoredThrust ? thrustTransforms : null, vectoredThrust ? thrustTransformMultipliers : null, log); FloatCurve atmosphereCurve = engineMod.atmosphereCurve; bool atmChangeFlow = engineMod.atmChangeFlow; FloatCurve atmCurve = engineMod.useAtmCurve ? engineMod.atmCurve : null; FloatCurve velCurve = engineMod.useVelCurve ? engineMod.velCurve : null; FloatCurve thrustCurve = engineMod.useThrustCurve ? engineMod.thrustCurve : null; float currentThrottle = engineMod.currentThrottle; float IspG = engineMod.g; bool throttleLocked = engineMod.throttleLocked || fullThrust; List <Propellant> propellants = engineMod.propellants; float thrustCurveRatio = engineMod.thrustCurveRatio; bool active = engineMod.isOperational; float resultingThrust = engineMod.resultingThrust; bool isFlamedOut = engineMod.flameout; EngineSim engineSim = pool.Borrow(); engineSim.isp = 0.0; engineSim.maxMach = 0.0f; engineSim.actualThrust = 0.0; engineSim.partSim = theEngine; engineSim.isActive = active; engineSim.thrustVec = vecThrust; engineSim.isFlamedOut = isFlamedOut; engineSim.resourceConsumptions.Reset(); engineSim.resourceFlowModes.Reset(); engineSim.appliedForces.Clear(); double flowRate = 0.0; if (engineSim.partSim.hasVessel) { if (log != null) { log.AppendLine("hasVessel is true"); } float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, engineSim.partSim.part.atmDensity, velCurve, machNumber, thrustCurve, thrustCurveRatio, ref engineSim.maxMach); engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere); engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp); engineSim.actualThrust = engineSim.isActive ? resultingThrust : 0.0; if (log != null) { log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier); log.buf.AppendFormat("isp = {0:g6}\n", engineSim.isp); log.buf.AppendFormat("thrust = {0:g6}\n", engineSim.thrust); log.buf.AppendFormat("actual = {0:g6}\n", engineSim.actualThrust); } if (throttleLocked) { if (log != null) { log.AppendLine("throttleLocked is true, using thrust for flowRate"); } flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); } else { if (currentThrottle > 0.0f && engineSim.partSim.isLanded == false) { // TODO: This bit doesn't work for RF engines if (log != null) { log.AppendLine("throttled up and not landed, using actualThrust for flowRate"); } flowRate = GetFlowRate(engineSim.actualThrust, engineSim.isp); } else { if (log != null) { log.AppendLine("throttled down or landed, using thrust for flowRate"); } flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); } } } else { if (log != null) { log.buf.AppendLine("hasVessel is false"); } float flowModifier = GetFlowModifier(atmChangeFlow, atmCurve, CelestialBodies.SelectedBody.GetDensity(BuildAdvanced.Altitude), velCurve, machNumber, thrustCurve, thrustCurveRatio, ref engineSim.maxMach); engineSim.isp = atmosphereCurve.Evaluate((float)atmosphere); engineSim.thrust = GetThrust(Mathf.Lerp(minFuelFlow, maxFuelFlow, GetThrustPercent(thrustPercentage)) * flowModifier, engineSim.isp); engineSim.actualThrust = 0d; if (log != null) { log.buf.AppendFormat("flowMod = {0:g6}\n", flowModifier); log.buf.AppendFormat("isp = {0:g6}\n", engineSim.isp); log.buf.AppendFormat("thrust = {0:g6}\n", engineSim.thrust); log.buf.AppendFormat("actual = {0:g6}\n", engineSim.actualThrust); log.AppendLine("no vessel, using thrust for flowRate"); } flowRate = GetFlowRate(engineSim.thrust, engineSim.isp); } if (log != null) { log.buf.AppendFormat("flowRate = {0:g6}\n", flowRate); } float flowMass = 0f; for (int i = 0; i < propellants.Count; ++i) { Propellant propellant = propellants[i]; if (!propellant.ignoreForIsp) { flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id); } } if (log != null) { log.buf.AppendFormat("flowMass = {0:g6}\n", flowMass); } for (int i = 0; i < propellants.Count; ++i) { Propellant propellant = propellants[i]; if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir") { continue; } double consumptionRate = propellant.ratio * flowRate / flowMass; if (log != null) { log.buf.AppendFormat( "Add consumption({0}, {1}:{2:d}) = {3:g6}\n", ResourceContainer.GetResourceName(propellant.id), theEngine.name, theEngine.partId, consumptionRate); } engineSim.resourceConsumptions.Add(propellant.id, consumptionRate); engineSim.resourceFlowModes.Add(propellant.id, (double)propellant.GetFlowMode()); } for (int i = 0; i < thrustTransforms.Count; i++) { Transform thrustTransform = thrustTransforms[i]; Vector3d direction = thrustTransform.forward.normalized; Vector3d position = thrustTransform.position; AppliedForce appliedForce = AppliedForce.New(direction * engineSim.thrust * thrustTransformMultipliers[i], position); engineSim.appliedForces.Add(appliedForce); } return(engineSim); }
// Default constructor public FloatCurveParser() { this.curve = null; }
internal NumericInput(ConfigNode node, InternalProp internalProp) { if (!node.HasValue("switchTransform")) { throw new Exception("USERINPUTSET missing switchTransform"); } // XNOR! if (!(node.HasValue("increment") ^ node.HasNode("incrementCurve"))) { throw new Exception("USERINPUTSET missing increment or incrementCurve, or it has both"); } if (node.HasValue("increment") && !float.TryParse(node.GetValue("increment"), out increment)) { throw new Exception("USERINPUTSET bad increment"); } else if (node.HasNode("incrementCurve")) { ConfigNode incNode = node.GetNode("incrementCurve"); string[] keys = incNode.GetValues("key"); incrementCurve = new FloatCurve(); for (int i = 0; i < keys.Length; ++i) { string[] values = keys[i].Split(' '); if (values.Length == 2) { incrementCurve.Add(float.Parse(values[0]), float.Parse(values[1])); } else if (values.Length == 4) { incrementCurve.Add(float.Parse(values[0]), float.Parse(values[1]), float.Parse(values[2]), float.Parse(values[3])); } else { JUtil.LogErrorMessage(this, "Found a curve key with {0} entries?!?", values.Length); } } pressAndHold = true; } if (node.HasValue("reverse")) { bool.TryParse(node.GetValue("reverse"), out reverse); } if (node.HasValue("animationName")) { animationName = node.GetValue("animationName").Trim(); } float switchSoundVolume = 0.5f; if (node.HasValue("switchSoundVolume") && !float.TryParse("switchSoundVolume", out switchSoundVolume)) { switchSoundVolume = 0.5f; } if (node.HasValue("switchSound")) { audioOutput = JUtil.SetupIVASound(internalProp, node.GetValue("switchSound").Trim(), switchSoundVolume, false); } if (node.HasValue("customSpeed") && !float.TryParse("customSpeed", out customSpeed)) { customSpeed = 1.0f; } if (!string.IsNullOrEmpty(animationName)) { // Set up the animation Animation[] animators = internalProp.FindModelAnimators(animationName); if (animators.Length > 0) { anim = animators[0]; } else { JUtil.LogErrorMessage(this, "Could not find animation \"{0}\" on prop \"{1}\"", animationName, internalProp.name); return; } anim[animationName].wrapMode = WrapMode.Once; if (reverse) { anim[animationName].speed = float.MaxValue; anim[animationName].normalizedTime = 0.0f; } else { anim[animationName].speed = float.MinValue; anim[animationName].normalizedTime = 1.0f; } anim.Play(animationName); } string switchTransform = node.GetValue("switchTransform"); if (incrementCurve != null) { SmarterButton.CreateButton(internalProp, switchTransform, TimedClick, TimedRelease); } else { SmarterButton.CreateButton(internalProp, switchTransform, Click, TimedRelease); } }
private void updateMeshEmissives(float progress, bool useLoop) { float p = progress / (useLoop ? animationLoopTime : animationOnTime); FloatCurve rCurve = useLoop?emissiveOnRedCurve : emissiveLoopRedCurve, bCurve = useLoop?emissiveOnBlueCurve:emissiveLoopBlueCurve, gCurve = useLoop?emissiveOnGreenCurve:emissiveOnBlueCurve; color.r = rCurve.Evaluate(p); color.b = bCurve.Evaluate(p); color.g = gCurve.Evaluate(p); int len = emissiveRenderers.Count; for (int i = 0; i < len; i++) { if (emissiveRenderers[i] != null) { emissiveRenderers[i].GetPropertyBlock(matProps); matProps.SetColor(shaderEmissiveID, color); emissiveRenderers[i].SetPropertyBlock(matProps); } } }
public PartStats(Part part) { this.mass = part.mass; if (part.partInfo.variant != null) { kRnDVariants = KRnD.getVariants(part); currentVariant = part.partInfo.variant.Name; currentVariantMass = part.partInfo.variant.Mass; variantBaseMass = part.baseVariant.Mass; } if (kRnDVariants != null) { hasVariants = true; } else { currentVariantMass = 0; variantBaseMass = 0; hasVariants = false; } this.skinMaxTemp = part.skinMaxTemp; this.intMaxTemp = part.maxTemp; // There should only be one or the other, engines or RCS: List <ModuleEngines> engineModules = KRnD.getEngineModules(part); ModuleRCS rcsModule = KRnD.getRcsModule(part); if (engineModules != null) { this.maxFuelFlows = new List <float>(); this.atmosphereCurves = new List <FloatCurve>(); for (int i = 0; i < engineModules.Count; i++) { ModuleEngines engineModule = engineModules[i]; this.maxFuelFlows.Add(engineModule.maxFuelFlow); FloatCurve atmosphereCurve = new FloatCurve(); for (int i5 = 0; i5 < engineModule.atmosphereCurve.Curve.length; i5++) { Keyframe frame = engineModule.atmosphereCurve.Curve[i5]; atmosphereCurve.Add(frame.time, frame.value); } this.atmosphereCurves.Add(atmosphereCurve); } } else if (rcsModule) { this.maxFuelFlows = new List <float>(); this.atmosphereCurves = new List <FloatCurve>(); this.maxFuelFlows.Add(rcsModule.thrusterPower); FloatCurve atmosphereCurve = new FloatCurve(); for (int i = 0; i < rcsModule.atmosphereCurve.Curve.length; i++) { Keyframe frame = rcsModule.atmosphereCurve.Curve[i]; atmosphereCurve.Add(frame.time, frame.value); } this.atmosphereCurves.Add(atmosphereCurve); } ModuleReactionWheel reactionWheel = KRnD.getReactionWheelModule(part); if (reactionWheel) { this.torque = reactionWheel.RollTorque; // There is also pitch- and yaw-torque, but they should all be the same } // WIP //ModuleDataTransmitter dataTransmitter = KRnD.getDataTransmitterModule(part); //if (dataTransmitter) //{ // this.antPower = dataTransmitter.antennaPower; //} ModuleResourceHarvester resourceHarvester = KRnD.getResourceHarvesterModule(part); if (resourceHarvester) { this.harvester = resourceHarvester.Efficiency; } ModuleActiveRadiator activeRadiator = KRnD.getActiveRadiatorModule(part); if (activeRadiator) { this.radiatorEfficiency = activeRadiator.maxEnergyTransfer; } ModuleDeployableSolarPanel solarPanel = KRnD.getSolarPanelModule(part); if (solarPanel) { this.chargeRate = solarPanel.chargeRate; } ModuleWheelBase landingLeg = KRnD.getLandingLegModule(part); if (landingLeg) { this.crashTolerance = part.crashTolerance; // Every part has a crash tolerance, but we only want to improve landing legs. } PartResource electricCharge = KRnD.getChargeResource(part); if (electricCharge != null) { this.batteryCharge = electricCharge.maxAmount; } ModuleGenerator generator = KRnD.getGeneratorModule(part); if (generator != null) { generatorEfficiency = new Dictionary <String, double>(); for (int i = 0; i < generator.resHandler.outputResources.Count; i++) { ModuleResource outputResource = generator.resHandler.outputResources[i]; generatorEfficiency.Add(outputResource.name, outputResource.rate); } } PartModule fissionGenerator = KRnD.getFissionGeneratorModule(part); if (fissionGenerator != null) { fissionPowerGeneration = KRnD.getGenericModuleValue(fissionGenerator, "PowerGeneration"); } // There might be different converter-modules in the same part with different names (eg for Fuel, Monopropellant, etc): List <ModuleResourceConverter> converterList = KRnD.getConverterModules(part); if (converterList != null) { converterEfficiency = new Dictionary <String, Dictionary <String, double> >(); for (int i = 0; i < converterList.Count; i++) { ModuleResourceConverter converter = converterList[i]; Dictionary <String, double> thisConverterEfficiency = new Dictionary <String, double>(); for (int i2 = 0; i2 < converter.outputList.Count; i2++) { ResourceRatio resourceRatio = converter.outputList[i2]; thisConverterEfficiency.Add(resourceRatio.ResourceName, resourceRatio.Ratio); } converterEfficiency.Add(converter.ConverterName, thisConverterEfficiency); } } ModuleParachute parachute = KRnD.getParachuteModule(part); if (parachute) { this.chuteMaxTemp = parachute.chuteMaxTemp; } ModuleProceduralFairing fairing = KRnD.getFairingModule(part); if (fairing) { this.fairingAreaMass = fairing.UnitAreaMass; } List <PartResource> fuelResources = KRnD.getFuelResources(part); if (fuelResources != null) { fuelCapacities = new Dictionary <string, double>(); fuelCapacitiesSum = 0; for (int i = 0; i < fuelResources.Count; i++) { PartResource fuelResource = fuelResources[i]; fuelCapacities.Add(fuelResource.resourceName, fuelResource.maxAmount); fuelCapacitiesSum += fuelResource.maxAmount; } } }
public void BuildNewDragModel(double newS, FloatCurve newCd, FloatCurve newClPotential, FloatCurve newClViscous, FloatCurve newCm, Vector3 newCoD, double newMajorMinorAxisRatio, double newCosCutoffAngle, double newTaperCrossSectionArea, double newYmaxForce, double newXZmaxForce) { S = newS; CdCurve = newCd; ClPotentialCurve = newClPotential; ClViscousCurve = newClViscous; CmCurve = newCm; CenterOfDrag = newCoD; majorMinorAxisRatio = newMajorMinorAxisRatio; cosAngleCutoff = newCosCutoffAngle; taperCrossSectionAreaRatio = newTaperCrossSectionArea / S; SPlusAttachArea = S; YmaxForce = newYmaxForce; XZmaxForce = newXZmaxForce; UpdateUpVector(true); }
public override void OnLoad(ConfigNode node) { base.OnLoad(node); if (node.HasNode("baseIgnitionChance")) { Log("IgnitionFail: Loading baseIgnitionChance curve"); baseIgnitionChance = new FloatCurve(); baseIgnitionChance.Load(node.GetNode("baseIgnitionChance")); } else baseIgnitionChance = null; if (node.HasNode("pressureCurve")) { Log("IgnitionFail: Loading pressure curve"); pressureCurve = new FloatCurve(); pressureCurve.Load(node.GetNode("pressureCurve")); } else pressureCurve = null; }
public static void UpdateCurrentActiveBody(int index, CelestialBody body) { if (index != prevBodyIndex) { prevBodyIndex = index; currentBodyVisc = bodyAtmosphereConfiguration[prevBodyIndex]; currentBody = body; prandtlMeyerMach = null; prandtlMeyerAngle = null; } }
public override void OnFixedUpdate() { ModuleEngines curEngineT = (ModuleEngines)this.part.Modules ["ModuleEngines"]; float throttle = curEngineT.currentThrottle; if (radhazard && throttle > 0 && rad_safety_features) { curEngineT.Events ["Shutdown"].Invoke (); curEngineT.currentThrottle = 0; curEngineT.requestedThrottle = 0; ScreenMessages.PostScreenMessage("Engines throttled down as they presently pose a radiation hazard!", 5.0f, ScreenMessageStyle.UPPER_CENTER); foreach (FXGroup fx_group in part.fxGroups) { fx_group.setActive (false); } } System.Random rand = new System.Random (new System.DateTime().Millisecond); List<Vessel> vessels = FlightGlobals.Vessels; List<Vessel> vessels_to_remove = new List<Vessel> (); List<ProtoCrewMember> crew_to_remove = new List<ProtoCrewMember> (); double death_prob = 1.0 - 1.0 * TimeWarp.fixedDeltaTime; if (radhazard && throttle > 0 && !rad_safety_features) { foreach (Vessel vess in vessels) { float distance = (float)Vector3d.Distance (vessel.transform.position, vess.transform.position); if (distance < 2000 && vess != this.vessel && vess.GetCrewCount() > 0) { float inv_sq_dist = distance / 50.0f; float inv_sq_mult = 1.0f / inv_sq_dist / inv_sq_dist; List<ProtoCrewMember> vessel_crew = vess.GetVesselCrew (); foreach (ProtoCrewMember crew_member in vessel_crew) { if (UnityEngine.Random.value >= death_prob*inv_sq_mult) { if(!vess.isEVA) { //Part part = vess.Parts.Find(p => p.protoModuleCrew.Contains(crew_member)); //part.RemoveCrewmember (crew_member); //crew_member.Die (); ScreenMessages.PostScreenMessage(crew_member.name + " was killed by Neutron Radiation!", 5.0f, ScreenMessageStyle.UPPER_CENTER); crew_to_remove.Add (crew_member); }else{ //vess.rootPart.Die(); ScreenMessages.PostScreenMessage(crew_member.name + " was killed by Neutron Radiation!", 5.0f, ScreenMessageStyle.UPPER_CENTER); vessels_to_remove.Add (vess); } } } } } foreach (Vessel vess in vessels_to_remove) { vess.rootPart.Die (); } foreach (ProtoCrewMember crew_member in crew_to_remove) { Vessel vess = FlightGlobals.Vessels.Find (p => p.GetVesselCrew ().Contains (crew_member)); Part part = vess.Parts.Find(p => p.protoModuleCrew.Contains(crew_member)); part.RemoveCrewmember (crew_member); crew_member.Die (); } } if (throttle > 0) { curEngineT.propellants [1].ratio = (float) (standard_megajoule_rate / throttle / throttle); curEngineT.propellants [2].ratio = (float) (standard_deut_rate / throttle / throttle); curEngineT.propellants [3].ratio = (float) (standard_lith_rate / throttle / throttle); FloatCurve newISP = new FloatCurve(); newISP.Add (0, (float)(minISP / throttle)); curEngineT.atmosphereCurve = newISP; } }
protected void UpdateRedCurve(FloatCurve curve) { colorMod.rCurve = curve; UpdateModifierPanel(); }
public override void UpdateCurves(FloatCurve newCurve, string tag) { base.UpdateCurves(newCurve, tag); }
// Default constructor public FloatCurveParser(FloatCurve curve) { this.curve = curve; }
public override void OnLoad(ConfigNode node) { base.OnLoad(node); // Manually reload ignitions if not in editor if (!HighLogic.LoadedSceneIsEditor) { node.TryGetValue("ignited", ref ignited); } int pCount = propellants.Count; // thrust curve useThrustCurve = false; if (node.HasNode("thrustCurve") && node.HasValue("curveResource")) { if (node.GetValue("curveResource") != curveResource) { Debug.LogError("*RFE* ERROR: curveResource doesn't match node's!"); curveResource = node.GetValue("curveResource"); } if (thrustCurve == null) { Debug.LogError("*RFE* ERROR: have curve node but thrustCurve is null!"); thrustCurve = new FloatCurve(); thrustCurve.Load(node.GetNode("thrustCurve")); } if (curveResource != string.Empty) { for (int i = 0; i < pCount; ++i) { if (propellants[i].name.Equals(curveResource)) { curveProp = i; break; } } if (curveProp != -1) { useThrustCurve = true; } } Fields["thrustPercentage"].guiActive = Fields["thrustPercentage"].guiActiveEditor = (minFuelFlow != maxFuelFlow); } // Set from propellants bool instantThrottle = false; for (int i = 0; i < pCount; ++i) { if (RFSettings.Instance.instantThrottleProps.Contains(propellants[i].name)) { instantThrottle = true; } // any other stuff } // FIXME calculating throttle change rate if (!instantThrottle) { if (throttleResponseRate <= 0f) { throttleResponseRate = (float)(RFSettings.Instance.throttlingRate / Math.Log(Math.Max(RFSettings.Instance.throttlingClamp, Math.Sqrt(part.mass * maxThrust * maxThrust)))); } } else { throttleResponseRate = 1000000f; } minThrottle = minFuelFlow / maxFuelFlow; // set fields Fields["thrustCurveDisplay"].guiActive = useThrustCurve; CreateEngine(); if (ullageSet == null) { ullageSet = new Ullage.UllageSet(this); } // Get thrust axis (only on create prefabs) if (part.partInfo == null || part.partInfo.partPrefab == null) { thrustAxis = Vector3.zero; foreach (Transform t in part.FindModelTransforms(thrustVectorTransformName)) { thrustAxis -= t.forward; } thrustAxis = thrustAxis.normalized; } ullageSet.SetThrustAxis(thrustAxis); // ullage if (node.HasNode("Ullage")) { ullageSet.Load(node.GetNode("Ullage")); } if (node.HasValue("pressureFed")) { bool.TryParse(node.GetValue("pressureFed"), out pressureFed); Debug.Log(this.name + ".pressureFed = " + this.pressureFed); } ullageSet.SetUllageEnabled(ullage); // load ignition resources if (node.HasNode("IGNITOR_RESOURCE")) { ignitionResources.Clear(); } foreach (ConfigNode n in node.GetNodes("IGNITOR_RESOURCE")) { ModuleResource res = new ModuleResource(); res.Load(n); ignitionResources.Add(res); } }
public void OverriddenStart() { var range = (UI_FloatRange)this.Fields["CurrentSafetyOverride"].uiControlEditor; range.minValue = 0f; range.maxValue = MaximumTemperature; range = (UI_FloatRange)this.Fields["CurrentSafetyOverride"].uiControlFlight; range.minValue = 0f; range.maxValue = MaximumTemperature; throttleCurve = new FloatCurve(); throttleCurve.Add(0, 0, 0, 0); throttleCurve.Add(50, 20, 0, 0); throttleCurve.Add(100, 100, 0, 0); Actions["TogglePanelAction"].guiName = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Action_TogglePanelAction"); Events["ShowReactorControl"].guiName = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Event_ShowReactorControl"); Events["RepairReactor"].guiName = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Event_RepairReactor"); Fields["CurrentSafetyOverride"].guiName = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Field_CurrentSafetyOverride"); Fields["CurrentPowerPercent"].guiName = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Field_CurrentPowerPercent"); Fields["ReactorOutput"].guiName = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Field_ReactorOutput"); Fields["ThermalTransfer"].guiName = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Field_ThermalTransfer"); Fields["CoreTemp"].guiName = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Field_CoreTemp"); Fields["CoreStatus"].guiName = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Field_CoreStatus"); Fields["FuelStatus"].guiName = Localizer.Format("#LOC_NFElectrical_ModuleFissionReactor_Field_FuelStatus"); if (base.ModuleIsActive()) { activeFlag = true; } else { activeFlag = false; } if (FirstLoad) { this.CurrentSafetyOverride = this.CriticalTemperature; FirstLoad = false; } if (HighLogic.LoadedScene != GameScenes.EDITOR) { core = this.GetComponent <ModuleCoreHeatNoCatchup>(); SetupCore(); SetupResourceRatios(); if (OverheatAnimation != "") { overheatStates = Utils.SetUpAnimation(OverheatAnimation, this.part); } if (FollowThrottle) { reactorEngine = this.GetComponent <FissionEngine>(); } } else { //this.CurrentSafetyOverride = this.NominalTemperature; } }
public void estimateEditorPerformance() { bool attached_reactor_upgraded = false; FloatCurve atmospherecurve = new FloatCurve(); float thrust = 0; if (myAttachedReactor != null) { if (myAttachedReactor is IUpgradeableModule) { IUpgradeableModule upmod = myAttachedReactor as IUpgradeableModule; if (upmod.HasTechsRequiredToUpgrade()) { attached_reactor_upgraded = true; } } maxISP = (float)(Math.Sqrt((double)myAttachedReactor.CoreTemperature) * isp_temp_rat * ispMultiplier); minISP = maxISP * 0.4f; atmospherecurve.Add(0, maxISP, 0, 0); atmospherecurve.Add(1, minISP, 0, 0); thrust = (float)(2 * myAttachedReactor.MaximumPower * 1000 / g0 / maxISP); myAttachedEngine.maxThrust = thrust; myAttachedEngine.atmosphereCurve = atmospherecurve; } else { atmospherecurve.Add(0, 0.00001f, 0, 0); myAttachedEngine.maxThrust = thrust; myAttachedEngine.atmosphereCurve = atmospherecurve; } }
private void InitializeParticlesHydrogenCubeM() { if (ParticlesHydrogenCubePerMeter != null) { return; } ParticlesHydrogenCubePerMeter = new FloatCurve(); ParticlesHydrogenCubePerMeter.Add(0, 0); ParticlesHydrogenCubePerMeter.Add(72.5f, 1.747e+9f); ParticlesHydrogenCubePerMeter.Add(73.0f, 2.872e+9f); ParticlesHydrogenCubePerMeter.Add(73.5f, 5.154e+9f); ParticlesHydrogenCubePerMeter.Add(74.0f, 1.009e+10f); ParticlesHydrogenCubePerMeter.Add(74.5f, 2.138e+10f); ParticlesHydrogenCubePerMeter.Add(75.0f, 4.836e+10f); ParticlesHydrogenCubePerMeter.Add(75.5f, 1.144e+11f); ParticlesHydrogenCubePerMeter.Add(76.0f, 2.760e+11f); ParticlesHydrogenCubePerMeter.Add(76.5f, 6.612e+11f); ParticlesHydrogenCubePerMeter.Add(77.0f, 1.531e+12f); ParticlesHydrogenCubePerMeter.Add(77.5f, 3.351e+12f); ParticlesHydrogenCubePerMeter.Add(78.0f, 6.813e+12f); ParticlesHydrogenCubePerMeter.Add(78.5f, 1.274e+13f); ParticlesHydrogenCubePerMeter.Add(79.0f, 2.180e+13f); ParticlesHydrogenCubePerMeter.Add(79.5f, 3.420e+13f); ParticlesHydrogenCubePerMeter.Add(80.0f, 4.945e+13f); ParticlesHydrogenCubePerMeter.Add(80.5f, 6.637e+13f); ParticlesHydrogenCubePerMeter.Add(81.0f, 8.346e+13f); ParticlesHydrogenCubePerMeter.Add(81.5f, 9.920e+13f); ParticlesHydrogenCubePerMeter.Add(82.0f, 1.124e+14f); ParticlesHydrogenCubePerMeter.Add(82.5f, 1.225e+14f); ParticlesHydrogenCubePerMeter.Add(83.0f, 1.292e+14f); ParticlesHydrogenCubePerMeter.Add(83.5f, 1.328e+14f); ParticlesHydrogenCubePerMeter.Add(84.0f, 1.335e+14f); ParticlesHydrogenCubePerMeter.Add(84.5f, 1.320e+14f); ParticlesHydrogenCubePerMeter.Add(85.0f, 1.287e+14f); ParticlesHydrogenCubePerMeter.Add(85.5f, 1.241e+14f); ParticlesHydrogenCubePerMeter.Add(86.0f, 1.187e+14f); ParticlesHydrogenCubePerMeter.Add(87, 1.066e+13f); ParticlesHydrogenCubePerMeter.Add(88, 9.426e+13f); ParticlesHydrogenCubePerMeter.Add(89, 8.257e+13f); ParticlesHydrogenCubePerMeter.Add(90, 7.203e+13f); ParticlesHydrogenCubePerMeter.Add(91, 6.276e+13f); ParticlesHydrogenCubePerMeter.Add(92, 5.474e+13f); ParticlesHydrogenCubePerMeter.Add(93, 4.786e+13f); ParticlesHydrogenCubePerMeter.Add(94, 4.198e+13f); ParticlesHydrogenCubePerMeter.Add(95, 3.698e+13f); ParticlesHydrogenCubePerMeter.Add(96, 3.272e+13f); ParticlesHydrogenCubePerMeter.Add(97, 2.909e+13f); ParticlesHydrogenCubePerMeter.Add(98, 2.598e+13f); ParticlesHydrogenCubePerMeter.Add(99, 2.332e+13f); ParticlesHydrogenCubePerMeter.Add(100, 2.101e+13f); ParticlesHydrogenCubePerMeter.Add(101, 1.901e+13f); ParticlesHydrogenCubePerMeter.Add(102, 1.726e+13f); ParticlesHydrogenCubePerMeter.Add(103, 1.572e+13f); ParticlesHydrogenCubePerMeter.Add(104, 1.435e+13f); ParticlesHydrogenCubePerMeter.Add(105, 1.313e+13f); ParticlesHydrogenCubePerMeter.Add(106, 1.203e+13f); ParticlesHydrogenCubePerMeter.Add(107, 1.104e+13f); ParticlesHydrogenCubePerMeter.Add(108, 1.013e+13f); ParticlesHydrogenCubePerMeter.Add(109, 9.299e+13f); ParticlesHydrogenCubePerMeter.Add(110, 8.534e+12f); ParticlesHydrogenCubePerMeter.Add(111, 7.827e+12f); ParticlesHydrogenCubePerMeter.Add(112, 7.173e+12f); ParticlesHydrogenCubePerMeter.Add(113, 6.569e+12f); ParticlesHydrogenCubePerMeter.Add(114, 6.012e+12f); ParticlesHydrogenCubePerMeter.Add(115, 5.500e+12f); ParticlesHydrogenCubePerMeter.Add(120, 3.551e+12f); ParticlesHydrogenCubePerMeter.Add(125, 2.477e+12f); ParticlesHydrogenCubePerMeter.Add(130, 1.805e+12f); ParticlesHydrogenCubePerMeter.Add(140, 1.029e+12f); ParticlesHydrogenCubePerMeter.Add(150, 6.468e+11f); ParticlesHydrogenCubePerMeter.Add(160, 4.485e+11f); ParticlesHydrogenCubePerMeter.Add(170, 3.400e+11f); ParticlesHydrogenCubePerMeter.Add(180, 2.774e+11f); ParticlesHydrogenCubePerMeter.Add(190, 2.394e+11f); ParticlesHydrogenCubePerMeter.Add(200, 2.154e+11f); ParticlesHydrogenCubePerMeter.Add(210, 1.995e+11f); ParticlesHydrogenCubePerMeter.Add(220, 1.887e+11f); ParticlesHydrogenCubePerMeter.Add(230, 1.809e+11f); ParticlesHydrogenCubePerMeter.Add(240, 1.752e+11f); ParticlesHydrogenCubePerMeter.Add(250, 1.707e+11f); ParticlesHydrogenCubePerMeter.Add(300, 1.569e+11f); ParticlesHydrogenCubePerMeter.Add(350, 1.477e+11f); ParticlesHydrogenCubePerMeter.Add(400, 1.399e+11f); ParticlesHydrogenCubePerMeter.Add(450, 1.327e+11f); ParticlesHydrogenCubePerMeter.Add(500, 1.260e+11f); ParticlesHydrogenCubePerMeter.Add(550, 1.198e+11f); ParticlesHydrogenCubePerMeter.Add(600, 1.139e+11f); ParticlesHydrogenCubePerMeter.Add(650, 1.085e+11f); ParticlesHydrogenCubePerMeter.Add(700, 1.033e+11f); ParticlesHydrogenCubePerMeter.Add(750, 9.848e+10f); ParticlesHydrogenCubePerMeter.Add(800, 9.393e+10f); ParticlesHydrogenCubePerMeter.Add(850, 8.965e+10f); ParticlesHydrogenCubePerMeter.Add(900, 8.562e+10f); ParticlesHydrogenCubePerMeter.Add(950, 8.182e+10f); ParticlesHydrogenCubePerMeter.Add(1000, 7.824e+10f); }
public SolarPanel(ConfigNode node, InterestedVessel vessel, ProtoPartModuleSnapshot modulesnapshot, ProtoPartSnapshot partsnapshot) { if (node == null) { Debug.Log("[UnloadedResources]: SolarPanel - Call to constructor failed. node is null."); return; } if (vessel == null) { Debug.Log("[UnloadedResources]: SolarPanel - Call to constructor failed. vessel is null."); return; } if (modulesnapshot == null) { Debug.Log("[UnloadedResources]: SolarPanel - Call to constructor failed. modulesnapshot is null."); return; } if (partsnapshot == null) { Debug.Log("[UnloadedResources]: SolarPanel - Call to constructor failed. partsnapshot is null."); return; } this.vessel = vessel; this.PartModule = modulesnapshot; if (node.HasValue("type")) { panelType = (ModuleDeployableSolarPanel.PanelType)System.Enum.Parse(typeof(ModuleDeployableSolarPanel.PanelType), node.GetValue("type")); } node.TryGetValue("chargeRate", ref chargeRate); node.TryGetValue("sunAOA", ref this.sunAOA); node.TryGetValue("flowRate", ref this.flowRate); node.TryGetValue("flowMult", ref this.flowMult); node.TryGetValue("efficiencyMult", ref this.efficiencyMult); if (node.HasValue("deployState")) { deployState = (ModuleDeployablePart.DeployState)System.Enum.Parse(typeof(ModuleDeployablePart.DeployState), node.GetValue("deployState")); } if (deployState != ModuleDeployablePart.DeployState.EXTENDED) { sunAOA = 0f; flowRate = 0f; } AvailablePart avPart = PartLoader.getPartInfoByName(partsnapshot.partName); Part part = null; if (avPart != null) { part = avPart.partPrefab; } if (part == null) { Debug.Log("[UnloadedResources]: SolarPanel - Unable to Find Part: " + partsnapshot.partName); return; } if (part.Modules == null) { Debug.Log("[UnloadedResources]: SolarPanel -No defined Modules Part: " + partsnapshot.partName); return; } for (int i = 0; i < part.Modules.Count; ++i) { if (part.Modules[i] == null) { continue; } if (part.Modules[i].moduleName == "ModuleDeployableSolarPanel" || part.Modules[i].moduleName == "KopernicusSolarPanel") { ModuleDeployableSolarPanel panelModule = (ModuleDeployableSolarPanel)part.Modules[i]; solarNormal = panelModule.part.FindModelTransform(panelModule.secondaryTransformName).forward; pivotAxis = panelModule.part.FindModelTransform(panelModule.pivotName).up; sunTracking = panelModule.isTracking && panelModule.trackingMode == ModuleDeployablePart.TrackingMode.SUN; usesCurve = panelModule.useCurve; tempCurve = panelModule.temperatureEfficCurve; temperature = (float)partsnapshot.temperature; powerCurve = panelModule.powerCurve; position = partsnapshot.position; orientation = partsnapshot.rotation; break; } } this.moduleType = UnloadedResources.ModuleType.Producer; }
public static Vector3 DoAeroForces(MissileLauncher ml, Vector3 targetPosition, float liftArea, float steerMult, Vector3 previousTorque, float maxTorque, float maxAoA, FloatCurve liftCurve, FloatCurve dragCurve) { Rigidbody rb = ml.part.rb; double airDensity = ml.vessel.atmDensity; double airSpeed = ml.vessel.srfSpeed; Vector3d velocity = ml.vessel.srf_velocity; //temp values Vector3 CoL = new Vector3(0, 0, -1f); float liftMultiplier = BDArmorySettings.GLOBAL_LIFT_MULTIPLIER; float dragMultiplier = BDArmorySettings.GLOBAL_DRAG_MULTIPLIER; //lift float AoA = Mathf.Clamp(Vector3.Angle(ml.transform.forward, velocity.normalized), 0, 90); if (AoA > 0) { double liftForce = 0.5 * airDensity * Math.Pow(airSpeed, 2) * liftArea * liftMultiplier * liftCurve.Evaluate(AoA); Vector3 forceDirection = Vector3.ProjectOnPlane(-velocity, ml.transform.forward).normalized; rb.AddForceAtPosition((float)liftForce * forceDirection, ml.transform.TransformPoint(ml.part.CoMOffset + CoL)); } //drag if (airSpeed > 0) { double dragForce = 0.5 * airDensity * Math.Pow(airSpeed, 2) * liftArea * dragMultiplier * dragCurve.Evaluate(AoA); rb.AddForceAtPosition((float)dragForce * -velocity.normalized, ml.transform.TransformPoint(ml.part.CoMOffset + CoL)); } //guidance if (airSpeed > 1) { Vector3 targetDirection; float targetAngle; if (AoA < maxAoA) { targetDirection = (targetPosition - ml.transform.position); targetAngle = Vector3.Angle(velocity.normalized, targetDirection) * 4; } else { targetDirection = velocity.normalized; targetAngle = AoA; } Vector3 torqueDirection = -Vector3.Cross(targetDirection, velocity.normalized).normalized; torqueDirection = ml.transform.InverseTransformDirection(torqueDirection); float torque = Mathf.Clamp(targetAngle * steerMult, 0, maxTorque); Vector3 finalTorque = Vector3.ProjectOnPlane(Vector3.Lerp(previousTorque, torqueDirection * torque, 1), Vector3.forward); rb.AddRelativeTorque(finalTorque); return(finalTorque); } else { Vector3 finalTorque = Vector3.ProjectOnPlane(Vector3.Lerp(previousTorque, Vector3.zero, 0.25f), Vector3.forward); rb.AddRelativeTorque(finalTorque); return(finalTorque); } }
private void ExportGenericData(YAMLMappingNode node, IReadOnlyDictionary <uint, string> tos) { StreamedClip streamedClip = MuscleClip.Clip.StreamedClip; DenseClip denseClip = MuscleClip.Clip.DenseClip; ConstantClip constantClip = MuscleClip.Clip.ConstantClip; IReadOnlyList <StreamedFrame> frames = streamedClip.GenerateFrames(); Dictionary <uint, Vector3Curve> translations = new Dictionary <uint, Vector3Curve>(); Dictionary <uint, QuaternionCurve> rotations = new Dictionary <uint, QuaternionCurve>(); Dictionary <uint, Vector3Curve> scales = new Dictionary <uint, Vector3Curve>(); Dictionary <uint, Vector3Curve> eulers = new Dictionary <uint, Vector3Curve>(); Dictionary <uint, FloatCurve> floats = new Dictionary <uint, FloatCurve>(); int frameCount = Math.Max(denseClip.FrameCount - 1, frames.Count - 2); float[] frameCurvesValue = new float[streamedClip.CurveCount]; for (int frame = 0, streamFrame = 1; frame < frameCount; frame++, streamFrame++) { bool isAdd = true; float time; StreamedFrame streamedFrame = null; if (streamFrame < frames.Count) { streamedFrame = frames[streamFrame]; time = streamedFrame.Time; } else { time = (float)frame / SampleRate; } // number of stream curves which has key in current frame int streamFrameCurveCount = streamFrame < frames.Count ? streamedFrame.Curves.Count : 0; // total amount of curves which has key in current frame int frameCurveCount = streamFrameCurveCount + (int)denseClip.CurveCount + constantClip.Constants.Count; int streamOffset = (int)streamedClip.CurveCount - streamFrameCurveCount; for (int curve = 0; curve < frameCurveCount;) { int curveIndex; IReadOnlyList <float> curvesValue; int offset; if (streamFrame < frames.Count && curve < streamedFrame.Curves.Count) { #warning TODO: read TCB and convert to in/out slope #warning TODO: write only few values for (int key = 0; key < streamedFrame.Curves.Count; key++) { frameCurvesValue[key] = streamedFrame.Curves[key].Value; } curveIndex = streamedFrame.Curves[curve].Index; curvesValue = frameCurvesValue; offset = 0; } else if (curve < streamFrameCurveCount + denseClip.CurveCount) { curveIndex = curve + streamOffset; curvesValue = denseClip.SampleArray; offset = streamFrameCurveCount - frame * (int)denseClip.CurveCount; } else { curveIndex = curve + streamOffset; curvesValue = constantClip.Constants; offset = streamFrameCurveCount + (int)denseClip.CurveCount; isAdd = frame == 0 || frame == frameCount - 1; } GenericBinding binding = ClipBindingConstant.FindBinding(curveIndex); uint pathHash = binding.Path; string path; if (pathHash == 0) { curve++; continue; } if (!tos.TryGetValue(pathHash, out path)) { path = "dummy" + pathHash; //Logger.Log(LogType.Debug, LogCategory.Export, $"Can't find path '{binding.Path}' in TOS for {ToLogString()}"); } switch (binding.BindingType) { case BindingType.Translation: float x = curvesValue[curve++ - offset]; float y = curvesValue[curve++ - offset]; float z = curvesValue[curve++ - offset]; float w = 0; if (isAdd) { Vector3f trans = new Vector3f(x, y, z); Vector3Curve transCurve; if (!translations.TryGetValue(pathHash, out transCurve)) { transCurve = new Vector3Curve(AssetsFile, path); translations[pathHash] = transCurve; } KeyframeTpl <Vector3f> transKey = new KeyframeTpl <Vector3f>(AssetsFile, time, trans); transCurve.Curve.Curve.Add(transKey); } break; case BindingType.Rotation: x = curvesValue[curve++ - offset]; y = curvesValue[curve++ - offset]; z = curvesValue[curve++ - offset]; w = curvesValue[curve++ - offset]; if (isAdd) { Quaternionf rot = new Quaternionf(x, y, z, w); QuaternionCurve rotCurve; if (!rotations.TryGetValue(pathHash, out rotCurve)) { rotCurve = new QuaternionCurve(AssetsFile, path); rotations[pathHash] = rotCurve; } KeyframeTpl <Quaternionf> rotKey = new KeyframeTpl <Quaternionf>(AssetsFile, time, rot); rotCurve.Curve.Curve.Add(rotKey); } break; case BindingType.Scaling: x = curvesValue[curve++ - offset]; y = curvesValue[curve++ - offset]; z = curvesValue[curve++ - offset]; if (isAdd) { Vector3f scale = new Vector3f(x, y, z); Vector3Curve scaleCurve; if (!scales.TryGetValue(pathHash, out scaleCurve)) { scaleCurve = new Vector3Curve(AssetsFile, path); scales[pathHash] = scaleCurve; } KeyframeTpl <Vector3f> scaleKey = new KeyframeTpl <Vector3f>(AssetsFile, time, scale); scaleCurve.Curve.Curve.Add(scaleKey); } break; case BindingType.EulerRotation: x = curvesValue[curve++ - offset]; y = curvesValue[curve++ - offset]; z = curvesValue[curve++ - offset]; if (isAdd) { Vector3f euler = new Vector3f(x, y, z); Vector3Curve eulerCurve; if (!eulers.TryGetValue(pathHash, out eulerCurve)) { eulerCurve = new Vector3Curve(AssetsFile, path); eulers[pathHash] = eulerCurve; } KeyframeTpl <Vector3f> eulerKey = new KeyframeTpl <Vector3f>(AssetsFile, time, euler); eulerCurve.Curve.Curve.Add(eulerKey); } break; case BindingType.Floats: float value = curvesValue[curve++ - offset]; if (isAdd) { Float @float = new Float(value); FloatCurve floatCurve; if (!floats.TryGetValue(pathHash, out floatCurve)) { floatCurve = new FloatCurve(AssetsFile, path); floats[pathHash] = floatCurve; } KeyframeTpl <Float> floatKey = new KeyframeTpl <Float>(AssetsFile, time, @float); floatCurve.Curve.Curve.Add(floatKey); } break; default: #warning TODO: ??? curve++; //throw new NotImplementedException(binding.BindingType.ToString()); break; } } } node.Add("m_RotationCurves", rotations.Values.ExportYAML()); node.Add("m_CompressedRotationCurves", YAMLMappingNode.Empty); node.Add("m_EulerCurves", eulers.Values.ExportYAML()); node.Add("m_PositionCurves", translations.Values.ExportYAML()); node.Add("m_ScaleCurves", scales.Values.ExportYAML()); node.Add("m_FloatCurves", floats.Values.ExportYAML()); }
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); 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 ? Math.Pow(plasma_ratio, 6) : 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; }
// Build the curve from the data found in the node void IParserEventSubscriber.Apply(ConfigNode node) { curve = new FloatCurve(); curve.Load(node); }
public EngineBaseData(ModuleEnginesFX fx, FloatCurve isp, float thrust) { engineFX = fx; maxThrust = thrust; ispCurve = isp; }
public void UpdateCurve(FloatCurve curve) { // update the curve currentModWinForCurve.UpdateCurves(curve, currentCurveTag); }
public static float GetFlowModifier(bool atmChangeFlow, FloatCurve atmCurve, double atmDensity, FloatCurve velCurve, float machNumber, FloatCurve thrustCurve, float thrustCurveRatio, ref float maxMach) { float flowModifier = 1.0f; if (atmChangeFlow) { flowModifier = (float)(atmDensity / 1.225); if (atmCurve != null) { flowModifier = atmCurve.Evaluate(flowModifier); } } if (velCurve != null) { flowModifier = flowModifier * velCurve.Evaluate(machNumber); maxMach = velCurve.maxTime; } if (thrustCurve != null) { flowModifier = flowModifier * thrustCurve.Evaluate(thrustCurveRatio); } if (flowModifier < float.Epsilon) { flowModifier = float.Epsilon; } return(flowModifier); }
public string partName; //for debugging public FuelNode(Part part, bool dVLinearThrust) { bool physicallySignificant = (part.physicalSignificance != Part.PhysicalSignificance.NONE); if (part.HasModule <ModuleLandingGear>() || part.HasModule <LaunchClamp>()) { //Landing gear set physicalSignificance = NONE when they enter the flight scene //Launch clamp mass should be ignored. physicallySignificant = false; } if (physicallySignificant) { dryMass = part.mass; } inverseStage = part.inverseStage; isFuelLine = (part is FuelLine); isSepratron = part.IsSepratron(); partName = part.partInfo.name; //note which resources this part has stored foreach (PartResource r in part.Resources) { if (r.info.density > 0 && r.name != "IntakeAir") { resources[r.info.id] = (float)r.amount; } resourcesUnobtainableFromParent.Add(r.info.id); } //record relevant engine stats ModuleEngines engine = part.Modules.OfType <ModuleEngines>().FirstOrDefault(); if (engine != null) { //Only count engines that either are ignited or will ignite in the future: if (HighLogic.LoadedSceneIsEditor || inverseStage < Staging.CurrentStage || engine.getIgnitionState) { //if an engine has been activated early, pretend it is in the current stage: if (engine.getIgnitionState && inverseStage < Staging.CurrentStage) { inverseStage = Staging.CurrentStage; } isEngine = true; // If we take into account the engine rotation if (dVLinearThrust) { Vector3 thrust = Vector3d.zero; foreach (var t in engine.thrustTransforms) { thrust -= t.forward / engine.thrustTransforms.Count; } Vector3 fwd = HighLogic.LoadedScene == GameScenes.EDITOR ? Vector3d.up : (HighLogic.LoadedScene == GameScenes.SPH ? Vector3d.forward : (Vector3d)engine.part.vessel.GetTransform().up); fwdThrustRatio = Vector3.Dot(fwd, thrust); } maxThrust = engine.thrustPercentage / 100f * engine.maxThrust; if (part.Modules.Contains("ModuleEngineConfigs") || part.Modules.Contains("ModuleHybridEngine") || part.Modules.Contains("ModuleHybridEngines")) { correctThrust = true; if (HighLogic.LoadedSceneIsFlight && engine.realIsp > 0.0f) { maxThrust = maxThrust * engine.atmosphereCurve.Evaluate(0) / engine.realIsp; //engine.atmosphereCurve.Evaluate((float)FlightGlobals.ActiveVessel.atmDensity); } } else { correctThrust = false; } ispCurve = engine.atmosphereCurve; propellantSumRatioTimesDensity = engine.propellants.Sum(prop => prop.ratio * MuUtils.ResourceDensity(prop.id)); propellantRatios = engine.propellants.Where(prop => PartResourceLibrary.Instance.GetDefinition(prop.id).density > 0 && prop.name != "IntakeAir").ToDictionary(prop => prop.id, prop => prop.ratio); } } // And do the same for ModuleEnginesFX :( ModuleEnginesFX enginefx = part.Modules.OfType <ModuleEnginesFX>().Where(e => e.isEnabled).FirstOrDefault(); if (enginefx != null) { //Only count engines that either are ignited or will ignite in the future: if (HighLogic.LoadedSceneIsEditor || inverseStage < Staging.CurrentStage || enginefx.getIgnitionState) { //if an engine has been activated early, pretend it is in the current stage: if (enginefx.getIgnitionState && inverseStage < Staging.CurrentStage) { inverseStage = Staging.CurrentStage; } isEngine = true; // If we take into account the engine rotation if (dVLinearThrust) { Vector3 thrust = Vector3d.zero; foreach (var t in enginefx.thrustTransforms) { thrust -= t.forward / enginefx.thrustTransforms.Count; } Vector3 fwd = HighLogic.LoadedScene == GameScenes.EDITOR ? Vector3d.up : (HighLogic.LoadedScene == GameScenes.SPH ? Vector3d.forward : (Vector3d)enginefx.part.vessel.GetTransform().up); fwdThrustRatio = Vector3.Dot(fwd, thrust); } maxThrust = enginefx.thrustPercentage / 100f * enginefx.maxThrust; if (part.Modules.Contains("ModuleEngineConfigs") || part.Modules.Contains("ModuleHybridEngine") || part.Modules.Contains("ModuleHybridEngines")) { correctThrust = true; if (HighLogic.LoadedSceneIsFlight && enginefx.realIsp > 0.0f) { maxThrust = maxThrust * enginefx.atmosphereCurve.Evaluate(0) / enginefx.realIsp; //engine.atmosphereCurve.Evaluate((float)FlightGlobals.ActiveVessel.atmDensity); } } else { correctThrust = false; } ispCurve = enginefx.atmosphereCurve; propellantSumRatioTimesDensity = enginefx.propellants.Sum(prop => prop.ratio * MuUtils.ResourceDensity(prop.id)); propellantRatios = enginefx.propellants.Where(prop => PartResourceLibrary.Instance.GetDefinition(prop.id).density > 0 && prop.name != "IntakeAir").ToDictionary(prop => prop.id, prop => prop.ratio); } } //figure out when this part gets decoupled. We do this by looking through this part and all this part's ancestors //and noting which one gets decoupled earliest (i.e., has the highest inverseStage). Some parts never get decoupled //and these are assigned decoupledInStage = -1. decoupledInStage = -1; Part p = part; while (true) { if (p.IsDecoupler() || p.IsLaunchClamp()) { if (p.inverseStage > decoupledInStage) { decoupledInStage = p.inverseStage; } } if (p.parent == null) { break; } else { p = p.parent; } } }
public static float GetAirSpeed(Vessel vessel) { FloatCurve windCurve = GetPlanetWindCurve(vessel.mainBody); return(windCurve.Evaluate((float)vessel.altitude) + (float)vessel.srf_velocity.magnitude); }
private void UpdateThrustDependentCalcs() { PartResource solidFuel = part.Resources["SolidFuel"]; double solidFuelMassG; if (solidFuel == null) { solidFuelMassG = UsingME ? 7.454 : 30.75; } else { solidFuelMassG = solidFuel.amount * solidFuel.info.density * Engine.g; } FloatCurve atmosphereCurve = Engine.atmosphereCurve; if (!UsingME) { //float burnTime0 = burnTimeME = (float)(atmosphereCurve.Evaluate(0) * solidFuelMassG / thrust); //float burnTime1 = (float)(atmosphereCurve.Evaluate(1) * solidFuelMassG / thrust); fuelRate = thrust / (atmosphereCurve.Evaluate(0f) * Engine.g); if (solidFuel != null) { UpdateBurnTime(); thrustASL = string.Format("{0:F1}", fuelRate * atmosphereCurve.Evaluate(1f) * Engine.g); } //burnTime = string.Format("{0:F1}s ({1:F1}s Vac)", burnTime1, burnTime0); //fuelRate = solidFuelMassG / burnTime0; } else { thrust = (float)(atmosphereCurve.Evaluate(0) * solidFuelMassG / burnTimeME); if (thrust > maxThrust) { burnTimeME = (float)Math.Ceiling(atmosphereCurve.Evaluate(0) * solidFuelMassG / maxThrust); thrust = (float)(atmosphereCurve.Evaluate(0) * solidFuelMassG / burnTimeME); } float thrust0 = Engine.maxThrust = thrust; float thrust1 = (float)(atmosphereCurve.Evaluate(1) * solidFuelMassG / burnTimeME); thrustME = thrust0.ToStringSI(unit: "N", exponent: 3) + " Vac / " + thrust1.ToStringSI(unit: "N", exponent: 3) + " ASL"; srbISP = string.Format("{1:F0}s Vac / {0:F0}s ASL", atmosphereCurve.Evaluate(1), atmosphereCurve.Evaluate(0)); fuelRate = (float)solidFuelMassG / (burnTimeME * Engine.g); } // This equation is much easier. From StretchySRBs if (useOldHeatEquation) { heatProduction = (float)Math.Round((200f + 5200f / Math.Pow((burnTimeME + 20f), 0.75f)) * 0.5f); } // My equation. else { heatProduction = heatPerThrust * Mathf.Sqrt(thrust) / (1 + part.mass); } // ReSharper disable once InconsistentNaming // Rescale the bell. float bellScale1m = selectedBell.chokeEndRatio / selectedBell.bellChokeDiameter; bellScale = bellScale1m * Mathf.Sqrt(thrust / thrust1m); UpdateEngineAndBellScale(); }
protected void UpdateBlueCurve(FloatCurve curve) { colorMod.bCurve = curve; UpdateModifierPanel(); }
private void updateLights(float progress, bool useLoop) { float p = progress / (useLoop ? animationLoopTime : animationOnTime); if (float.IsNaN(p)) { p = 0; } FloatCurve rCurve = useLoop ? lightLoopRedCurve : lightOnRedCurve, bCurve = useLoop ? lightLoopBlueCurve : lightOnBlueCurve, gCurve = useLoop ? lightLoopGreenCurve : lightOnGreenCurve; color.r = rCurve.Evaluate(p); color.b = bCurve.Evaluate(p); color.g = gCurve.Evaluate(p); foreach (LightData tr in lightTransforms) { tr.setColor(color); } }
public override void OnFixedUpdate() { temperatureStr = part.temperature.ToString("0.00") + "K / " + part.maxTemp.ToString("0.00") + "K"; if (curEngineT == null) return; float throttle = curEngineT.currentThrottle; //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 = consumeFNResource(powerRequirement * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_MEGAJOULES); var plasma_ratio = recievedPower / (powerRequirement * TimeWarp.fixedDeltaTime); var fusionRatio = plasma_ratio >= 1 ? 1 : plasma_ratio > 0.75 ? Mathf.Pow((float)plasma_ratio, 6.0f) : 0; // Lasers produce Wasteheat supplyFNResource(recievedPower * (1 - efficiency), FNResourceManager.FNRESOURCE_WASTEHEAT); // The Aborbed wasteheat from Fusion supplyFNResource(FusionWasteHeat * wasteHeatMultiplier * fusionRatio * TimeWarp.fixedDeltaTime, FNResourceManager.FNRESOURCE_WASTEHEAT); // change ratio propellants Hydrogen/Fusion curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.Deuterium).ratio = (float)(standard_deuterium_rate / throttle / throttle); curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.Tritium).ratio = (float)(standard_tritium_rate / throttle / throttle); // Update ISP FloatCurve 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 = (float)maxFuelFlow; if (!curEngineT.getFlameoutState) { if (plasma_ratio < 0.75 && recievedPower > 0) curEngineT.status = "Insufficient Electricity"; } } else { FloatCurve newISP = new FloatCurve(); newISP.Add(0, (float)minISP); curEngineT.atmosphereCurve = newISP; var maxFuelFlow = MaximumThrust / minISP / PluginHelper.GravityConstant; curEngineT.maxFuelFlow = (float)maxFuelFlow; } radiatorPerformance = (float)Math.Max(1 - (float)(coldBathTemp / maxTempatureRadiators), 0.000001); partEmissiveConstant = (float)part.emissiveConstant; }
protected void UpdateGreenCurve(FloatCurve curve) { colorMod.gCurve = curve; UpdateModifierPanel(); }
public override void Startup() { base.Startup(); // We don't want this getting triggered as a random failure core.DisableFailure("TestFlightFailure_IgnitionFail"); Part prefab = this.part.partInfo.partPrefab; foreach (PartModule pm in prefab.Modules) { TestFlightFailure_IgnitionFail modulePrefab = pm as TestFlightFailure_IgnitionFail; if (modulePrefab != null && modulePrefab.Configuration == configuration) { if ((object)modulePrefab.baseIgnitionChance != null) { Log("IgnitionFail: Loading baseIgnitionChance from prefab"); baseIgnitionChance = modulePrefab.baseIgnitionChance; } if ((object)modulePrefab.pressureCurve != null) { Log("IgnitionFail: Loading pressureCurve from prefab"); pressureCurve = modulePrefab.pressureCurve; } } } }
protected void UpdateAlphaCurve(FloatCurve curve) { colorMod.aCurve = curve; UpdateModifierPanel(); }
public FuelNode(Part part) { bool physicallySignificant = (part.physicalSignificance != Part.PhysicalSignificance.NONE); if (part.HasModule<ModuleLandingGear>() || part.HasModule<LaunchClamp>()) { //Landing gear set physicalSignificance = NONE when they enter the flight scene //Launch clamp mass should be ignored. physicallySignificant = false; } if (physicallySignificant) dryMass = part.mass; inverseStage = part.inverseStage; isFuelLine = (part is FuelLine); isSepratron = part.IsSepratron(); partName = part.partInfo.name; //note which resources this part has stored foreach (PartResource r in part.Resources) { if (r.info.name != "ElectricCharge") resources[r.info.id] = (float)r.amount; resourcesUnobtainableFromParent.Add(r.info.id); } //record relevant engine stats ModuleEngines engine = part.Modules.OfType<ModuleEngines>().FirstOrDefault(); if (engine != null) { //Only count engines that either are ignited or will ignite in the future: if (HighLogic.LoadedSceneIsEditor || inverseStage < Staging.CurrentStage || engine.getIgnitionState) { //if an engine has been activated early, pretend it is in the current stage: if (engine.getIgnitionState && inverseStage < Staging.CurrentStage) inverseStage = Staging.CurrentStage; isEngine = true; maxThrust = engine.maxThrust; ispCurve = engine.atmosphereCurve; propellantSumRatioTimesDensity = engine.propellants.Sum(prop => prop.ratio * MuUtils.ResourceDensity(prop.id)); propellantRatios = engine.propellants.Where(prop => prop.name != "ElectricCharge").ToDictionary(prop => prop.id, prop => prop.ratio); } } //figure out when this part gets decoupled. We do this by looking through this part and all this part's ancestors //and noting which one gets decoupled earliest (i.e., has the highest inverseStage). Some parts never get decoupled //and these are assigned decoupledInStage = -1. decoupledInStage = -1; Part p = part; while (true) { if (p.IsDecoupler()) { if (p.inverseStage > decoupledInStage) decoupledInStage = p.inverseStage; } if (p.parent == null) break; else p = p.parent; } }
// 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; } }