예제 #1
0
    public override void OnStart(PartModule.StartState state)
    {
        base.OnStart(state);
        if (!HighLogic.LoadedSceneIsFlight)
            return;

        modeList.Add(new mode(primaryModeRange.x, primaryModeRange.y));

        engine = part.Modules.OfType<ModuleEngines>().FirstOrDefault();
        if (engine != null)
        {

        }
        else
        {
            Debug.Log("FSanimateThrottle: no engine module found");
        }

        anim = part.FindModelAnimators(animationName).FirstOrDefault();
        if (anim != null)
        {
            animTime = 0f;
            anim[animationName].layer = animationLayer;
            anim[animationName].speed = 0f;
            anim[animationName].normalizedTime = 0f;
            anim[animationName].wrapMode = WrapMode.ClampForever;
        }
        else
        {
            Debug.Log("FSanimateThrottle: no animation found called " + animationName);
        }
    }
예제 #2
0
 public override void OnStart(PartModule.StartState state)
 {
     base.OnStart(state);
     engine = part.Modules.OfType<ModuleEngines>().FirstOrDefault();
     intake = part.Modules.OfType<ModuleResourceIntake>().FirstOrDefault();
     toggleMenuItems(false);
 }
예제 #3
0
 public EngineWrapper(IEngineStatus engine_status)
 {
     engineS  = engine_status;
     engine   = engineS as ModuleEngines;
     engineFX = engineS as ModuleEnginesFX;
     eFX = engineFX != null;
 }
예제 #4
0
 public EngineWrapper(Part part)
 {
     engine = (ModuleEngines)part.Modules["ModuleEngines"];
     if (engine != null)
     {
         type = EngineType.ModuleEngine;
     }
     else
     {
         engineFX = (ModuleEnginesFX)part.Modules["ModuleEnginesFX"];
         if (engineFX != null)
         {
             type = EngineType.ModuleEngineFX;
         }
         else
         {
      //                   fsengine = (Firespitter.engine.FSengine)part.Modules["FSengine"];
      //                   if (fsengine != null)
             {
      //                       type = EngineType.FSengine;
             }
         }
     }
     Debug.Log("EngineWrapper: engine type is " + type.ToString());
 }
예제 #5
0
        public override void OnStart(StartState state)
        {
            // parent OnStart
            base.OnStart(state);

            module = Utils.getModuleByType<ModuleEngines>(base.part);
        }
예제 #6
0
 public override void OnStart(PartModule.StartState state)
 {
     base.OnStart(state);
         engine = part.Modules.OfType<ModuleEngines>().FirstOrDefault();
        partTransform = part.FindModelTransform(thrustTransform);
         //maxThrust = engine.maxThrust;
 }
        public void Start()
        {
            engineStates = SetUpAnimation(EngineAnimationName, this.part);

            if(HighLogic.LoadedSceneIsFlight)
            {
                foreach (var me in this.part.FindModulesImplementing<ModuleEngines>())
                {
                    engineIsOn = me.EngineIgnited;
                    modEng = me;
                    engineIsFX = false;
                }

                foreach (var me in this.part.FindModulesImplementing<ModuleEnginesFX>())
                {
                    engineIsOn = me.EngineIgnited;
                    modEngFX = me;
                    engineIsFX = true;
                }
            }

            foreach(var anim in engineStates)
            {
                if (engineIsOn)
                {
                        anim.normalizedTime = 1;
                }
                else
                {
                        anim.normalizedTime = 0;
                }
            }
        }
 public override void OnStart(PartModule.StartState state) {
     if (state == StartState.Editor) { return; }
     List<ModuleEnginesFX> mefxs = part.FindModulesImplementing<ModuleEnginesFX>().Where(e => e.engineID == "AirBreathing").ToList();
     List<ModuleEngines> mes = part.FindModulesImplementing<ModuleEngines>().ToList();
     rapier_engine = mefxs.FirstOrDefault();
     rapier_engine2 = mes.FirstOrDefault();
 }
예제 #9
0
        public override void OnStart(StartState state)
        {
            base.OnStart(state);

            if (HighLogic.LoadedSceneIsEditor == false && HighLogic.LoadedSceneIsFlight == false)
                return;

            //Set landing gear action
            ModuleAnimateGeneric kickstandAnim = this.part.FindModuleImplementing<ModuleAnimateGeneric>();
            kickstandAnim.Actions[0].actionGroup = KSPActionGroup.Gear;

            //Setup the GUI
            setupGUI();

            //Get the primary and secondary engine
            List<ModuleEngines> engineList = this.part.FindModulesImplementing<ModuleEngines>();
            foreach (ModuleEngines engine in engineList)
            {
                if (engine.engineID == multiModeEngine.primaryEngineID)
                    primaryEngine = engine;
                else if (engine.engineID == multiModeEngine.secondaryEngineID)
                    secondaryEngine = engine;
            }

            //Setup the engine mode
            setupEngineMode();
        }
예제 #10
0
 public FSengineWrapper(Part part)
 {
     engine = part.Modules.OfType<ModuleEngines>().FirstOrDefault();
     if (engine != null)
     {
         type = EngineType.ModuleEngine;
     }
     else
     {
         engineFX = part.Modules.OfType<ModuleEnginesFX>().FirstOrDefault();
         if (engineFX != null)
         {
             type = EngineType.ModuleEngineFX;
         }
         else
         {
             fsengine = part.Modules.OfType<FSengine>().FirstOrDefault();
             if (fsengine != null)
             {
                 type = EngineType.FSengine;
             }
         }
     }
     //Debug.Log("FSengineWrapper: engine type is " + type.ToString());
 }
예제 #11
0
        public override void OnStart(PartModule.StartState state)
        {
            base.OnStart (state);

            /*MonoBehaviour.print("Configured with " + engines.Count + " switchable engines:");
            foreach (Engine engine in engines)
                MonoBehaviour.print(engine.ToString());*/

            //FlightInputHandler.OnFlyByWire += new FlightInputHandler.FlightInputCallback(autopilotDelegate);

            // let's find us the other two part modules, throw errors if we can't
            try {
                jet = this.part.Modules.OfType<ModuleEngines> ().Where (m => m.propellants.Any (p => p.name == "IntakeAir")).First ();
                rocket = this.part.Modules.OfType<ModuleEngines> ().Where (m => m.propellants.Any (p => p.name == "Oxidizer")).First ();
            } catch (InvalidOperationException e) {
                MonoBehaviour.print ("HybridRocketModule error: jet or rocket engine partmodules not found, check part configuration");
            }

            MonoBehaviour.print("HybridRocketModule initialized");

            // hide all GUI events for this, except our own Toggle event
            Deactivate();

            switch (this.status) {
            case JET:
                ActivateJet();
                break;
            case ROCKET:
                ActivateRocket();
                break;
            }
        }
예제 #12
0
    public EngineModuleWrapper(Part part, string engineID)
    {
        ModuleEngines _engine = null;
        foreach (PartModule pm in part.Modules)
        {
            _engine = pm as ModuleEngines;
            if (_engine != null && _engine.engineID.ToLowerInvariant() == engineID.ToLowerInvariant())
                break;
        }
        if (_engine != null)
        {
            engine = _engine;
            if (part.Modules.Contains("ModuleEnginesRF"))
                engineType = EngineModuleType.REALENGINE;
            else if (part.Modules.Contains("ModuleEngines"))
                engineType = EngineModuleType.ENGINE;
            else if (part.Modules.Contains("ModuleEnginesFX"))
                engineType = EngineModuleType.ENGINEFX;
            else
                engineType = EngineModuleType.UNKNOWN;

            _minFuelFlow = engine.minFuelFlow;
            _maxFuelFlow = engine.maxFuelFlow;
        }
        else
        {
            engineType = EngineModuleType.UNKNOWN;
        }
    }
        public override void OnStart(PartModule.StartState state)
        {
            animStates = Utils.SetUpAnimation(ThrustAnimationName, this.part);

            foreach(ModuleEngines me in this.part.FindModulesImplementing<ModuleEngines>())
            {
                modEng = me;
                isEngineFX = false;
                break;
            }

            foreach(ModuleEnginesFX me in this.part.FindModulesImplementing<ModuleEnginesFX>())
            {
                modEngFX = me;
                isEngineFX = true;
                break;
            }
            HideGimbalButtons();
            part.OnEditorAttach += new Callback(HideGimbalButtons);
            if(disableGimbalToggle)
            {
                Actions["AGToggleGimbal"].active = true;
                Events["GuiToggleGimbal"].guiActive = true;
                Events["GuiToggleGimbal"].guiActiveEditor = true;

                foreach(ModuleGimbal mgg in this.part.FindModulesImplementing<ModuleGimbal>())
                {
                    gimbalStatus = !mgg.gimbalLock;
                }
            }
            else
            {
                Actions["AGToggleGimbal"].active = false;
            }
        }
        public AirbreathingEngineCrossSectonAdjuster(ModuleEngines engine, Matrix4x4 worldToVesselMatrix)
        {
            vehicleBasisForwardVector = Vector3.forward;
            //for (int i = 0; i < engine.thrustTransforms.Count; i++)
            //    vehicleBasisForwardVector += engine.thrustTransforms[i].forward;

            thisToVesselMatrix = worldToVesselMatrix * engine.thrustTransforms[0].localToWorldMatrix;

            vehicleBasisForwardVector = thisToVesselMatrix.MultiplyVector(vehicleBasisForwardVector);

            vehicleBasisForwardVector.Normalize();
            vehicleBasisForwardVector *= -1f;


            this.engine = engine;
            this.part = engine.part;

            Bounds partBounds = part.GetPartColliderBoundsInBasis(Matrix4x4.identity);
            exitArea = partBounds.extents.x + partBounds.extents.z;
            exitArea *= 0.5;
            exitArea *= exitArea;
            exitArea *= Math.PI;

            exitArea *= -1;     //make this negative to note that it is a removal of area 
        }
        public override void OnStart(PartModule.StartState state)
        {
            deployStates = Utils.SetUpAnimation(animationName, part);
            engine = part.FindModuleImplementing<ModuleEngines>();
            vtolEngines = new List<BDVTOLAnimator>();

            engine.Actions["ActivateAction"].active = false;
            engine.Actions["ShutdownAction"].active = false;
        }
예제 #16
0
 public override void OnStart(PartModule.StartState state)
 {
     base.OnStart(state);
     engine = part.GetComponent<ModuleEngines>();
     engine.Events["Activate"].guiActiveUnfocused = true;
     engine.Events["Activate"].unfocusedRange = 5f;
     engine.Events["Shutdown"].guiActiveUnfocused = true;
     engine.Events["Shutdown"].unfocusedRange = 5f;
 }
예제 #17
0
 public static void updateEngineThrust(ModuleEngines engine, float minThrust, float maxThrust)
 {
     engine.minThrust = minThrust;
     engine.maxThrust = maxThrust;
     ConfigNode updateNode = new ConfigNode("MODULE");
     updateNode.AddValue("maxThrust", engine.maxThrust);
     updateNode.AddValue("minThrust", engine.minThrust);
     engine.Load(updateNode);
 }
예제 #18
0
 public EngineWrapper(Part part)
 {
     if ((mEFX = part.transform.GetComponent<ModuleEnginesFX>()) != null)
         type = ModuleType.MODULEENGINESFX;
     else if ((mE = part.transform.GetComponent<ModuleEngines>()) != null)
         type = ModuleType.MODULEENGINES;
     else
         throw new ArgumentException("Unable to find engine-like module");
 }
예제 #19
0
 internal static Engine Normalise(ModuleEngines engine)
 {
     return Engine.CreateEngineWithName(Part.FromGO(engine.gameObject).partInfo.title)
         .WithMode(x =>
         {
             x.SeaLevelISP = engine.atmosphereCurve.Evaluate(1.0f);
             x.VacuumISP = engine.atmosphereCurve.Evaluate(0.0f);
         });
 }
        protected override void OnEnabled()
        {
            base.ToleranceScaling = 8.0f;
            base.Malleability = 2.0f;

            _engine = (ModuleEngines)part.GetComponent(typeof(ModuleEngines));
            _originalHeatProduction = _engine.heatProduction;

            DamageReceived += ModuleKerbalKrashEngine_DamageReceived;
            DamageRepaired += ModuleKerbalKrashEngine_DamageReceived;
        }
        public void DustController(ModuleEngines pm, List<Transform> lt)
        {
            float thrustPer = pm.finalThrust / lt.Count;

            for (int i = 0; i < lt.Count; i++)
            {
                var layerMask = 1 << 15;

                Ray r = new Ray(lt[i].position, lt[i].forward);

                RaycastHit ht;
                Physics.Raycast(r, out ht, 100, layerMask);

                float pwr = 0;

                pwr = Mathf.Clamp01((pm.finalThrust / lt.Count) / 200); //if the engine produces 200 kN of thrust, then the effect is a "full power". obviously this can be changed
                pwr = Mathf.Clamp01((ht.distance / 100 - 1f) * (ht.distance / 100 - 1f)) * pwr; //this is intended to make the effect larger as the distance is reduced. this can of course also be changed.

                groundInterfaceTransform.position = ht.point;
                groundInterfaceTransform.forward = ht.normal;

                foreach (ParticleEmitter fx in dustEffect.fxEmitters)
                {
                    fx.transform.position = ht.point;
                    fx.transform.forward = ht.normal;
                }

                dustEffect.Power = pwr;

                if (pwr > .01)
                {
                    dustEffect.setActive(true);

                    foreach (ParticleEmitter fx in dustEffect.fxEmitters)
                    {
                        fx.gameObject.SetActive(true);
                    }
                }

                else
                {
                    dustEffect.setActive(false);

                    foreach (ParticleEmitter fx in dustEffect.fxEmitters)
                    {
                        fx.gameObject.SetActive(false);
                    }
                }

            }
        }
 public EngineWrapper(ModuleEngines engine)
 {
     //init
     thrustController.setMaster(ThrustPI);
     zeroIsp = engine.atmosphereCurve.Evaluate(0f);
     name = Utils.ParseCamelCase(engine.part.Title());
     if(engine.engineID.Length > 0 && engine.engineID != "Engine")
         name += " (" + engine.engineID + ")";
     //generate engine ID
     this.engine = engine;
     ID = new EngineID(this);
     //get info
     info = engine.part.Modules.GetModule<TCAEngineInfo>();
     //find gimbal
     gimbal = engine.part.Modules.GetModule<ModuleGimbal>();
 }
    //private bool showMenu = false;
    //private Rect windowRect = new Rect(500f, 250f, 250f, 50f);
    //private FSGUIPopup popup;
    public override void OnStart(PartModule.StartState state)
    {
        engine = part.Modules.OfType<ModuleEngines>().FirstOrDefault();
            if (engine != null)
            {
                //Debug.Log("FSswitchEngineThrustTransform: Engine module found");
                thrustTransform = part.FindModelTransform(defaultTTName);
                defaultTT = new GameObject().transform;
                defaultTT.localPosition = thrustTransform.localPosition;
                defaultTT.localRotation = thrustTransform.localRotation;
                //defaultTT = part.FindModelTransform(defaultTTName);
                if (useNamedAlternate == 1)
                {
                    alternateTT = part.FindModelTransform(alternateTTName);
                }
                else
                {
                    alternateTT = new GameObject().transform;
                    alternateTT.localPosition = defaultTT.localPosition;
                    alternateTT.localRotation = defaultTT.localRotation;
                    alternateTT.Rotate(alternateTT.right, 180f);
                }
                if (defaultTT == null || alternateTT == null) valid = false;

                if (isReversed)
                {
                    setTTReverseState(true);
                }
                else
                {
                    setTTReverseState(false);
                }
            }
            else
            {
                valid = false;
                Debug.Log("FSswitchEngineThrustTransform: no engine module found");
            }

            animateThrottle = part.Modules.OfType<FSanimateThrottle>().FirstOrDefault();
            if (animateThrottle != null)
            {
                animateThrottle.modeList.Add(new mode(animateThrottleRange.x, animateThrottleRange.y));
                animateThrottleMode = animateThrottle.modeList.Count - 1;
            }
    }
예제 #24
0
        // for a single EngineModule, determine its flowMultiplier, subject to atmDensity + machNumber
        public static double FlowMultiplierAtConditions(this ModuleEngines e, double atmDensity, double machNumber)
        {
            double flowMultiplier = 1;

            if (e.atmChangeFlow)
            {
                if (e.useAtmCurve)
                {
                    flowMultiplier = e.atmCurve.Evaluate((float)atmDensity * 40 / 49);
                }
                else
                {
                    flowMultiplier = atmDensity * 40 / 49;
                }
            }

            double ratio = 1.0f;  // FIXME: should be sum of propellant.totalAmount / sum of propellant.totalCapacity?

            // (but the FuelFlowSimulation that uses this takes very large timesteps anyway)
            if (e.useThrustCurve)
            {
                flowMultiplier *= e.thrustCurve.Evaluate((float)ratio);
            }

            if (e.useVelCurve)
            {
                flowMultiplier *= e.velCurve.Evaluate((float)machNumber);
            }

            if (flowMultiplier > e.flowMultCap)
            {
                double excess = flowMultiplier - e.flowMultCap;
                flowMultiplier = e.flowMultCap + excess / (e.flowMultCapSharpness + excess / e.flowMultCap);
            }

            // some engines have e.CLAMP set to float.MaxValue so we have to have the e.CLAMP < 1 sanity check here
            if (flowMultiplier < e.CLAMP && e.CLAMP < 1)
            {
                flowMultiplier = e.CLAMP;
            }

            return(flowMultiplier);
        }
예제 #25
0
        // for a single EngineModule, evaluate its ISP, subject to all the different possible curves
        public static double ISPAtConditions(this ModuleEngines e, double throttle, double atmPressure, double atmDensity, double machNumber)
        {
            double isp = 0;

            isp = e.atmosphereCurve.Evaluate((float)atmPressure);
            if (e.useThrottleIspCurve)
            {
                isp *= Mathf.Lerp(1f, e.throttleIspCurve.Evaluate((float)throttle), e.throttleIspCurveAtmStrength.Evaluate((float)atmPressure));
            }
            if (e.useAtmCurveIsp)
            {
                isp *= e.atmCurveIsp.Evaluate((float)atmDensity * 40 / 49);
            }
            if (e.useVelCurveIsp)
            {
                isp *= e.velCurveIsp.Evaluate((float)machNumber);
            }
            return(isp);
        }
예제 #26
0
        public void Start()
        {
            // Reconfigure the prompts from the generic values
            BaseField baseField = Fields["partId"];

            baseField.guiName = "#MAS_GroupId_PartId";
            Utility.LogMessage(this, "partId updated");

            BaseEvent baseEvent = Events["IdPlus"];

            baseEvent.guiName = "#MAS_GroupId_Next_PartId";
            Utility.LogMessage(this, "IdPlus updated");

            baseEvent         = Events["IdMinus"];
            baseEvent.guiName = "#MAS_GroupId_Prev_PartId";
            Utility.LogMessage(this, "IdMinus updated");

            engine = part.FindModuleImplementing <ModuleEngines>();
        }
예제 #27
0
		// Restore engines control without reactivating them
		private void ActivateEngines()
		{
			foreach (Part p in FlightGlobals.ActiveVessel.Parts)
			{
				foreach (PartModule pm in p.Modules)
				{
					if (!(pm is ModuleEngines)) continue;
					ModuleEngines eng = (ModuleEngines) pm;
					if (eng.engineType == EngineType.LiquidFuel | eng.engineType == EngineType.Nuclear)
					{
						eng.Events["Activate"].guiActive = true;
					}

					if (!deactivatedEngines.Contains(eng)) continue;
					eng.Activate();
					deactivatedEngines.Remove(eng);
				}
			}
		}
예제 #28
0
        //TODO should be expanded to search the entire vessel during flight (respecting stage/flow setup)
        //TODO should be expanded to search the entire ShipConstruct in the editor, respecting stage flow
        private float getEnginePropellantMass(ModuleEngines engine)
        {
            float fuelMass = 0;

            if (engine.propellants != null && engine.propellants.Count > 0)
            {
                int len = engine.propellants.Count;
                for (int i = 0; i < len; i++)
                {
                    string       propName = engine.propellants[0].name;
                    PartResource pr       = part.Resources[propName];
                    if (pr != null)
                    {
                        fuelMass += (float)(pr.info.density * pr.amount);
                    }
                }
            }
            return(fuelMass);
        }
예제 #29
0
        public override void Initialize(ModuleWaterfallFX host)
        {
            base.Initialize(host);

            engineController = host.GetComponents <ModuleEngines>().FirstOrDefault(x => x.engineID == engineID);
            if (engineController == null)
            {
                Utils.Log($"[{nameof(CustomPullController)}]: Could not find engine ID {engineID}, using first module if available");
                engineController = host.GetComponent <ModuleEngines>();
            }

            if (engineController == null)
            {
                Utils.LogError($"[{nameof(CustomPullController)}]: Could not find any {nameof(ModuleEngines)} to use with {nameof(CustomPullController)} named {name}, effect controller will not do anything");
                return;
            }

            pullValueMethod = FindSuitableMemberOnEnginesModule();
        }
예제 #30
0
        protected override void Overrides()
        {
            Fields["displayChance"].guiName = "Chance of Engine Failure";
            Fields["safetyRating"].guiName  = "Engine Safety Rating";

            engine        = part.FindModuleImplementing <ModuleEngines>();
            engineWrapper = new EngineModuleWrapper();
            engineWrapper.InitWithEngine(part, engine.engineID);

            gimbal = part.FindModuleImplementing <ModuleGimbal>();
            //If the ISP at sea level suggests this is a space engine, change the lifetime and failure rates accordingly
            float staticPressure = (float)(FlightGlobals.GetHomeBody().GetPressure(0) * PhysicsGlobals.KpaToAtmospheres);

            if (engine.atmosphereCurve.Evaluate(staticPressure) <= 100.0f)
            {
                expectedLifetime    = spaceEngineExpectedLifetime;
                baseChanceOfFailure = spaceEngineBaseChanceOfFailure;
            }
        }
        public override void OnStart(PartModule.StartState state)
        {
            try
            {
                part.maxTemp             = maxTemp;
                part.thermalMass         = 1;
                part.thermalMassModifier = 1;
                EngineGenerationType     = GenerationType.Mk1;

                curEngineT = this.part.FindModuleImplementing <ModuleEngines>();

                if (curEngineT == null)
                {
                    Debug.LogWarning("[KSPI] - FusionEngine OnStart Engine not found");
                    return;
                }

                minISP = curEngineT.atmosphereCurve.Evaluate(0);

                standard_deuterium_rate = curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.LqdDeuterium).ratio;
                standard_tritium_rate   = curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.LqdTritium).ratio;

                DetermineTechLevel();

                // calculate WasteHeat Capacity
                var wasteheatPowerResource = part.Resources[FNResourceManager.FNRESOURCE_WASTEHEAT];
                if (wasteheatPowerResource != null)
                {
                    var wasteheat_ratio = Math.Min(wasteheatPowerResource.amount / wasteheatPowerResource.maxAmount, 0.95);
                    wasteheatPowerResource.maxAmount = part.mass * 2.0e+4 * wasteHeatMultiplier;
                    wasteheatPowerResource.amount    = wasteheatPowerResource.maxAmount * wasteheat_ratio;
                }

                if (state != StartState.Editor)
                {
                    part.emissiveConstant = maxTempatureRadiators > 0 ? 1 - coldBathTemp / maxTempatureRadiators : 0.01;
                }
            }
            catch (Exception e)
            {
                Debug.LogError("[KSPI] - FusionEngine OnStart eception: " + e.Message);
            }
        }
예제 #32
0
        public override void OnStart(PartModule.StartState state)
        {
            if (state == StartState.Editor) return;

            flightStarted = true;

            if (part.Modules.Contains("ModuleEngines"))
                engine = part.Modules["ModuleEngines"] as ModuleEngines;

            anim[Animation].wrapMode = WrapMode.Loop;

            if (fixAnimLayers) {
                int i = 0;
                foreach (AnimationState s in anim) {
                    s.layer = i;
                    i++;
                }
            }
        }
예제 #33
0
        public static bool EngineHasFuel(this Part p)
        {
            for (int i = 0; i < p.Modules.Count; i++)
            {
                PartModule    m   = p.Modules[i];
                ModuleEngines eng = m as ModuleEngines;
                if (eng != null)
                {
                    return(!eng.getFlameoutState);
                }

                ModuleEnginesFX engFX = m as ModuleEnginesFX;
                if (engFX != null)
                {
                    return(!engFX.getFlameoutState);
                }
            }
            return(false);
        }
        private void updateEngineThrust()
        {
            ModuleEngines engine = part.GetComponent <ModuleEngines>();

            if (engine != null)
            {
                float scale           = getEngineScale();
                float thrustScalar    = Mathf.Pow(scale, thrustScalePower);
                float thrustPerEngine = engineThrust * thrustScalar;
                float totalThrust     = thrustPerEngine * numberOfEngines;
                guiEngineThrust = totalThrust;
                SSTUStockInterop.updateEngineThrust(engine, engine.minThrust, totalThrust);
            }
            else
            {
                print("Cannot update engine thrust -- no engine module found!");
                guiEngineThrust = 0;
            }
        }
예제 #35
0
 // Make "engine" and "engineFX" fields refer to the ModuleEngines and ModuleEnginesFX modules in part.Modules
 void FindModuleEngines()
 {
     foreach (PartModule pm in part.Modules)
     {
         if (pm is ModuleEngines)
         {
             engine             = pm as ModuleEngines;
             IsPersistentEngine = true;
         }
         else
         {
             Debug.Log("[PersistentThrust] No ModuleEngine found.");
         }
         if (pm is ModuleEnginesFX)
         {
             engineFX = pm as ModuleEnginesFX;
         }
     }
 }
예제 #36
0
 public override void OnStart(PartModule.StartState state)
 {
     base.OnStart(state);
     if (usesDeployAnimation == 1)
     {
         deployAnimation = part.Modules.OfType <FSanimateGeneric>().FirstOrDefault();
     }
     engine          = part.Modules.OfType <ModuleEngines>().FirstOrDefault();
     atmosphericNerf = part.Modules.OfType <FSpropellerAtmosphericNerf>().FirstOrDefault();
     if (rotorparent != "")
     {
         RotorParent     = part.FindModelTransform(rotorparent);
         spinRotorObject = true;
     }
     else
     {
         spinRotorObject = false;
     }
 }
예제 #37
0
        public int UpdateSymmetryCounterparts()
        {
            int i = 0;

            foreach (Part sPart in part.symmetryCounterparts)
            {
                ModuleEngineConfigs engine = (ModuleEngineConfigs)sPart.Modules ["ModuleEngineConfigs"];
                if (engine)
                {
                    i++;
                    engine.configuration = configuration;
                    engine.config        = config;
                    engine.modded        = true;
                    ModuleEngines thruster = (ModuleEngines)sPart.Modules ["ModuleEngines"];
                    thruster.Load(engine.config);
                }
            }
            return(i);
        }
예제 #38
0
        public override void OnStart(PartModule.StartState state)
        {
            //Debug.Log("[ModuleEngineLife]: OnStart()");
            List <ModuleEngines> engines = new List <ModuleEngines>();

            engines = this.GetComponents <ModuleEngines>().ToList();
            foreach (ModuleEngines e in engines)
            {
                if (e.engineID == engineID || engineID == "")
                {
                    engine     = e;
                    haveEngine = true;
                    break;
                }
            }
            if (!haveEngine)
            {
                foreach (ModuleEngines e in engines)
                {
                    if (e.thrustVectorTransformName == engineID)
                    {
                        engine     = e;
                        haveEngine = true;
                        break;
                    }
                }
            }
            if (haveEngine)
            {
                baseHeatProduction = engine.heatProduction;
                if (maxHeatProduction < baseHeatProduction)
                {
                    maxHeatProduction = baseHeatProduction * 30.0f;
                }
                failSeverityMin = Math.Max(0.01f, failSeverityMin);
                failSeverityMax = Math.Max(failSeverityMin + 0.01f, failSeverityMax);
            }
            else
            {
                Debug.Log("[ModuleEngineLife]: EngineID '" + engineID + "' not found on part " + part.name);
            }
        }
예제 #39
0
        private void updateStats()
        {
            ModuleEngines[] engines = part.GetComponents <ModuleEngines>();
            if (engines == null || engines.Length < 1 || engineModuleIndex < 0 || engineModuleIndex >= engines.Length)
            {
                //no valid engine module; set UI values to default/0, and disable UI fields
                return;
            }
            ModuleEngines engine = engines[engineModuleIndex];

            //derivation of fuel mass flow from isp and thrust, from expression of thrust from ISP (t = g * i * m)
            //t = thrust(kn), g = g0(m/s), i = isp(s), m = massflowrate(t/s)
            //t = g * i * m //basic definition
            //t = m * i * g //commutative re-arrangement
            //t/i/g = m //isolate mass flow

            float fuelMass = getEnginePropellantMass(engine);
            float ispValue = engine.atmosphereCurve.Evaluate(0);
            float delta    = engine.maxThrust - engine.minThrust;
            float limiter  = engine.thrustPercentage * 0.01f;
            float thrust   = engine.minThrust + limiter * delta;
            float massFlow = thrust / ispValue / 9.81f;//m = t/i/g
            float burnTime = (fuelMass / massFlow);

            this.ispGuiDisplay      = ispValue.ToString();
            this.thrustGuiDisplay   = thrust.ToString();
            this.burnTimeGuiDisplay = burnTime.ToString();
            this.fuelFlowGuiDisplay = (engine.maxThrust / ispValue).ToString();

            //old code from SSTUModularBooster
            //if (engineModule != null)
            //{
            //    string prop = engineModule.propellants[0].name;
            //    PartResource res = part.Resources[prop];
            //    double propMass = res.info.density * res.amount;
            //    float delta = engineModule.maxThrust - engineModule.minThrust;
            //    float limiter = engineModule.thrustPercentage * 0.01f;
            //    guiThrust = engineModule.minThrust + delta * limiter;
            //    float limit = guiThrust / engineModule.maxThrust;
            //    guiBurnTime = (float)(propMass / engineModule.maxFuelFlow) / limit;
            //}
        }
예제 #40
0
    public override void OnStart(PartModule.StartState state)
    {
        base.OnStart(state);

        engageAssigned    = createGroup(engageGroup, engage, false);
        runningAssigned   = createGroup(runningGroup, running, true);
        powerAssigned     = createGroup(powerGroup, power, true);
        disengageAssigned = createGroup(disengageGroup, disengage, false);
        flameoutAssigned  = createGroup(flameoutGroup, flameout, false);
        warningAssigned   = createGroup(warningGroup, warning, false);

        engine = part.GetComponent <ModuleEngines>();

        if (engine != null)
        {
            maxThrust = engine.maxThrust;
        }
        //GameEvents.onGamePause.Add(new EventVoid.OnEvent(OnPause));
        //GameEvents.onGameUnpause.Add(new EventVoid.OnEvent(OnResume));
    }
예제 #41
0
 private void updateNeedles(ModuleEngines engine)
 {
     if (thrustLimitNeedle != null)
     {
         thrustLimitNeedle.localRotation = Quaternion.Euler(rotationAxis * Mathf.Lerp(minAngle, maxAngle, engine.thrustPercentage / 100f));
     }
     if (RPMneedle != null)
     {
         RPMneedle.localRotation = Quaternion.Euler(rotationAxis * Mathf.Lerp(minAngle, maxAngle, engine.normalizedThrustOutput));
     }
     if (heatNeedle != null)
     {
         heatNeedle.localRotation = Quaternion.Euler(rotationAxis * Mathf.Lerp(minAngle, maxAngle, (float)engine.part.temperature / (float)engine.part.maxTemp));
     }
     //debug
     //float limiter = engine.thrustPercentage / 100f;
     //float rpm = engine.normalizedThrustOutput;
     //float heat = engine.part.maxTemp / engine.part.temperature;
     //Log.dbg("tLimit: {0} ({1}) rpm: {2} heat: {3}", limiter, engine.thrustPercentage, rpm, heat);
 }
예제 #42
0
 private void updateNeedles(ModuleEngines engine)
 {
     if (thrustLimitNeedle != null)
     {
         thrustLimitNeedle.localRotation = Quaternion.Euler(rotationAxis * Mathf.Lerp(minAngle, maxAngle, engine.thrustPercentage / 100f));
     }
     if (RPMneedle != null)
     {
         RPMneedle.localRotation = Quaternion.Euler(rotationAxis * Mathf.Lerp(minAngle, maxAngle, engine.normalizedThrustOutput));
     }
     if (heatNeedle != null)
     {
         heatNeedle.localRotation = Quaternion.Euler(rotationAxis * Mathf.Lerp(minAngle, maxAngle, engine.part.temperature / engine.part.maxTemp));
     }
     //debug
     //float limiter = engine.thrustPercentage / 100f;
     //float rpm = engine.normalizedThrustOutput;
     //float heat = engine.part.maxTemp / engine.part.temperature;
     //Debug.Log("tLimit: " + limiter + " (" + engine.thrustPercentage + ") rpm: " + rpm + " heat: " + heat);
 }
예제 #43
0
        void Process_engines(ModuleEngines me)
        {
            // calculate thrust fuel flow
            double thrust_flow = me.maxFuelFlow * 1e3 * me.thrustPercentage;

            // search fuel types
            foreach (Propellant fuel in me.propellants)
            {
                switch (fuel.name)
                {
                case "ElectricCharge":                          // mainly used for Ion Engines
                    Resource("ElectricCharge").Consume(thrust_flow * fuel.ratio, "engines");
                    break;

                case "LqdHydrogen":                             // added for cryotanks and any other supported mod that uses Liquid Hydrogen
                    Resource("LqdHydrogen").Consume(thrust_flow * fuel.ratio, "engines");
                    break;
                }
            }
        }
예제 #44
0
 public override void OnStart(StartState state)
 {
     foreach (var anim in part.FindModelAnimators(animationName))
     {
         aniEngine = anim;
         if (aniEngine.GetClipCount() > 1)
         {
             aniEngine.Stop(); //stopping any animations loaded by ModuleAnimateGeneric
         }
         print("[Maritime Pack] (aniEngine) Found animation: " + animationName);
     }
     if (partType == "Engine")
     {
         myEngine = this.part.Modules.OfType <ModuleEngines>().FirstOrDefault();
     }
     if (partType == "Intake")
     {
         myIntake = this.part.Modules.OfType <ModuleResourceIntake>().FirstOrDefault();
     }
 }
예제 #45
0
 //This function sets/unsets burst, and returns the new thrust value
 private float ToggleMaxThrust(ModuleEngines module, float Thrustpct, ref bool currentThrustState)
 {
     if (currentThrustState == true)
     {
         //i.e. if burst, then return the engine to normal state
         module.maxThrust   = module.maxThrust / (1 + Thrustpct / 100);
         module.maxFuelFlow = module.maxFuelFlow / (1 + Thrustpct / 100);
         maxFuelFlow        = module.maxFuelFlow;
         currentThrustState = false;                   //true = burst | false = normal
     }
     else
     {
         //i.e. if not burst, then burst the engine
         module.maxThrust   = module.maxThrust * (1 + Thrustpct / 100);
         module.maxFuelFlow = module.maxFuelFlow * (1 + Thrustpct / 100);
         maxFuelFlow        = module.maxFuelFlow;
         currentThrustState = true;
     }
     return(module.maxThrust);
 }
예제 #46
0
        /// <summary>
        /// Returns the maximum torque the ship can exert by gimbaling its engines while at full throttle
        /// </summary>
        /// <returns>The torque in N m, around the (pitch, roll, yaw) axes.</returns>
        /// <param name="p">The part providing the torque. Need not be an engine.</param>
        /// <param name="vessel">The vessel to which the torque is applied.</param>
        public static Vector3d GetThrustTorque(Part p, Vessel vessel)
        {
            double result = 0.0;

            foreach (ModuleGimbal gimbal in p.Modules.OfType <ModuleGimbal>())
            {
                if (gimbal.gimbalLock)
                {
                    continue;
                }

                // Standardize treatment of ModuleEngines and ModuleEnginesFX;
                //      IEngineStatus doesn't have the needed fields
                double maxThrust = 0.0;
                // Assume exactly one module of EITHER type ModuleEngines or ModuleEnginesFX exists in `p`
                bool engineFound = false;
                {
                    ModuleEngines engine = p.Modules.OfType <ModuleEngines>().FirstOrDefault();
                    if (engine != null)
                    {
                        if (!engine.isOperational)
                        {
                            continue;
                        }
                        engineFound = true;
                        maxThrust   = engine.maxThrust;
                    }
                }
                // Dummy ModuleGimbal, does nothing
                if (!engineFound)
                {
                    continue;
                }

                double gimbalRadians = Math.Sin(Math.Abs(gimbal.gimbalRange) * Math.PI / 180);
                result = gimbalRadians * maxThrust * (p.Rigidbody.worldCenterOfMass - vessel.CoM).magnitude;
            }

            // Better to overestimate roll torque than to underestimate it... calculate properly later
            return(new Vector3d(result, result, result));
        }
예제 #47
0
        /// <summary>
        /// Returns the average of the throttle limit for the selected engine group,
        /// ranging from 0 (no thrust) to 1 (maximum thrust).
        /// </summary>
        /// <param name="groupId">A number from 1 to 31 (inclusive) to select a specific group, or 0 to select all groups.</param>
        /// <returns>A number from 0 (no thrust or no engines) to 1 (maximum thrust).</returns>
        public double GetThrottleLimit(double groupId)
        {
            float limit = 0.0f;
            float count = 0.0f;

            int id = (int)groupId;

            if (id == 0)
            {
                for (int i = 0; i < vc.engineGroup.Length; ++i)
                {
                    ModuleEngines me = vc.engineGroup[i].engine;

                    if (me.EngineIgnited)
                    {
                        limit += me.thrustPercentage;
                        // We use 100 because thrustPercentage is in the range [0, 100].  So, using
                        // 100 here gives us a free conversion to [0, 1].
                        count += 100.0f;
                    }
                }
            }
            else
            {
                for (int i = 0; i < vc.engineGroup.Length; ++i)
                {
                    if (vc.engineGroup[i].partId == id)
                    {
                        ModuleEngines me = vc.engineGroup[i].engine;

                        if (me.EngineIgnited)
                        {
                            limit += me.thrustPercentage;
                            count += 100.0f;
                        }
                    }
                }
            }

            return((count > 0.0f) ? (limit / count) : 0.0);
        }
예제 #48
0
        public override void OnStart(StartState state)
        {
            // hook up to the part attach callback

            /*
             * if (state == StartState.Editor)
             * {
             *  part.OnEditorAttach += OnEditorAttach;
             * }
             */

            List <ModuleEngines> engines = part.FindModulesImplementing <ModuleEngines>();

            foreach (ModuleEngines e in engines)
            {
                if (e.engineID == escapeEngineID)
                {
                    escapeEngine = e;
                }
                else if (e.engineID == jettisonEngineID)
                {
                    jettisonEngine = e;
                }
                foreach (BaseAction a in e.Actions)
                {
                    a.active = false;
                }
                foreach (BaseField f in e.Fields)
                {
                    f.guiActive       = false;
                    f.guiActiveEditor = false;
                }
                foreach (BaseEvent ev in e.Events)
                {
                    ev.guiActive       = false;
                    ev.guiActiveEditor = false;
                }
            }

            // check for nulls in engines
        }
예제 #49
0
        private void checkEngines()
        {
            log.prefix = "[Landertron:" + part.flightID + "] ";
            //log.debug("Checking for engines.");
            engines.Clear();
            foreach (var p in vessel.parts)
            {
                //foreach (var p in vessel.FindPartModulesImplementing<ModuleEngines>()){
                ModuleEngines engine = new ModuleEngines();
                if (!p.Modules.Contains("Landertron"))
                {
                    if (p.Modules.Contains("ModuleEngines"))
                    {
                        engine = p.Modules ["ModuleEngines"] as ModuleEngines;
                    }
                    else if (p.Modules.Contains("ModuleEnginesFX"))
                    {
                        engine = p.Modules ["ModuleEnginesFX"] as ModuleEngines;
                    }
                    else if (p.Modules.Contains("ModuleEnginesRF"))
                    {
                        engine = p.Modules ["ModuleEnginesRF"] as ModuleEngines;
                    }
                    else
                    {
                        continue;
                    }
                }
                if (engine.EngineIgnited)
                {
                    //log.debug ("Added engine." + engine.maxThrust.ToString());
                    if (!engine.flameout)
                    {
                        engines.Add(engine);
                    }
                }
            }

            //if (engines.Count == 0)
            //    log.error("No engine found! Will crash!");
        }
예제 #50
0
        public void CheckShipForChallengeComplete()
        {
            Vessel active = FlightGlobals.ActiveVessel;
            double targetLat = -0.092222, targetLon = 285.4475, targetAlt = 102.0;

            if (active != null && !challengeCompleted)
            {
                if (active.Landed && KCT_Utilities.ApproximatelyEqual(targetLat, active.latitude, 0.006) && KCT_Utilities.ApproximatelyEqual(targetLon, active.longitude, 0.006) && KCT_Utilities.ApproximatelyEqual(targetAlt, active.altitude, 5))
                {
                    bool hasChutes = false;
                    bool hasSRB    = false;
                    foreach (Part p in active.parts)
                    {
                        if (p.Modules != null && (p.Modules.Contains("ModuleParachute") || p.Modules.Contains("RealChuteModule")))
                        {
                            hasChutes = true;
                        }
                        if (p.partInfo.title.ToLower().Contains("rt-10"))
                        {
                            if (p.Modules.Contains("ModuleEngines"))
                            {
                                ModuleEngines engine = (ModuleEngines)p.Modules["ModuleEngines"];
                                if (engine.EngineIgnited)
                                {
                                    hasSRB = true;
                                }
                            }
                        }
                    }

                    if (!hasChutes && hasSRB)
                    {
                        challengeCompleted = true;
                        string popupString = "Congratulations! You completed the Daily Challenge! Take some pictures to show your worth and post them on the forum thread!\n\n" +
                                             "(Ok, seriously? You seriously completed the Daily Challenge? Screw it, you get over 9000 Jeb Coins (a $45,000 value). Please, for the love of all things Kerbal, post your result on the KCT forum thread. I HAVE to see this.)";
                        PopupDialog.SpawnPopupDialog("Challenge Complete!", popupString, "Collect Reward!", false, HighLogic.Skin);
                        TotalJebCoins += 9001;
                    }
                }
            }
        }
        private void FuelConsumptionFromEngineModule(ModuleEngines e, ref double totalThrust, ref double totalThrust_Isp, ref double fuelConsumptionVol, ref double airDemandVol, double invDeltaTime)
        {
            if (e.EngineIgnited && !e.engineShutdown)
            {
                totalThrust     += e.finalThrust;
                totalThrust_Isp += e.finalThrust * e.realIsp;
                for (int i = 0; i < e.propellants.Count; i++)
                {
                    Propellant v = e.propellants[i];

                    if (v.id == intakeAirId)
                    {
                        airDemandVol += v.currentRequirement * invDeltaTime; // Rodhern: Added invDeltaTime so airDemandVol and fuelConsumptionVol is treated the same; i.e. in units per second.
                    }
                    if (!v.ignoreForIsp)
                    {
                        fuelConsumptionVol += v.currentRequirement * invDeltaTime;
                    }
                }
            }
        }
예제 #52
0
        /// Make "engine" and "engineFX" fields refer to the ModuleEngines and ModuleEnginesFX modules in part.Modules
        private void FindModuleEngines()
        {
            foreach (PartModule pm in part.Modules)
            {
                if (pm is MultiModeEngine)
                {
                    multiMode   = pm as MultiModeEngine;
                    IsMultiMode = true;
                }
                else if (pm is ModuleEngines)
                {
                    engine             = pm as ModuleEngines;
                    IsPersistentEngine = true;
                }
            }

            if (!IsPersistentEngine)
            {
                Debug.Log("[PersistentThrust] No ModuleEngine found.");
            }
        }
    protected override bool SetupModule()
    {
        foreach (PartModule cModule in part.Modules)
        {
            if (cModule.GetType() != typeof(ModuleEngines))
                continue;

            _Engine = cModule as ModuleEngines;
            break;
        }

        if (_Engine != null)
        {
            _Thrust = _Engine.GetType().GetField("finalThrust");

            if(UseMaxThrust)
                this.MaxValue = _Engine.maxThrust;
        }

        return base.SetupModule();
    }
예제 #54
0
    /*public bool fieldsEnabled = true;
     * [KSPEvent(name = "toggleFields", active = true, guiActive = true, guiName = "Toggle Fields")]
     * public void toggleFieldsEvent()
     * {
     *  toggleFields(!fieldsEnabled);
     * }
     * public void toggleFields(bool toggle)
     * {
     *  BaseFieldList test = part.Fields;
     *
     *
     *  Debug.Log("FS: part.Fields: " + test);
     *  Debug.Log("FS: part.Fields.Count: " + test.Count);
     *  //test["steeringEnabled"].guiActive = false;
     *
     *  foreach (KSPField field in test)
     *  {
     *      //field.guiActive = toggle;
     *      Debug.Log("FS guiName: " + field.guiName);
     *      //Debug.Log("FS name   : " + field.name);
     *  }
     * }*/

    public override void OnStart(PartModule.StartState state)
    {
        base.OnStart(state);
        engine                = part.Modules.OfType <ModuleEngines>().FirstOrDefault();
        rootTransform         = part.FindModelTransform(targetPartObject);
        defaultHeatProduction = engine.heatProduction;

        // Sound code from kethane kethanedetector.cs

        /*
         #region Sound effects
         * heatDing = gameObject.AddComponent<AudioSource>();
         * WWW wwwE = new WWW("file://" + KSPUtil.ApplicationRootPath.Replace("\\", "/") + "/sounds/sound_fsheatDing.wav");
         * if ((heatDing != null) && (wwwE != null))
         * {
         *  heatDing.clip = wwwE.GetAudioClip(false);
         *  heatDing.volume = 1;
         *  heatDing.Stop();
         * }
         #endregion*/
    }
예제 #55
0
    public EngineModuleWrapper(Part part, string engineID)
    {
        ModuleEngines _engine = null;

        foreach (PartModule pm in part.Modules)
        {
            _engine = pm as ModuleEngines;
            if (_engine != null && _engine.engineID.ToLowerInvariant() == engineID.ToLowerInvariant())
            {
                break;
            }
        }
        if (_engine != null)
        {
            engine = _engine;
            if (part.Modules.Contains("ModuleEnginesRF"))
            {
                engineType = EngineModuleType.REALENGINE;
            }
            else if (part.Modules.Contains("ModuleEngines"))
            {
                engineType = EngineModuleType.ENGINE;
            }
            else if (part.Modules.Contains("ModuleEnginesFX"))
            {
                engineType = EngineModuleType.ENGINEFX;
            }
            else
            {
                engineType = EngineModuleType.UNKNOWN;
            }

            _minFuelFlow = engine.minFuelFlow;
            _maxFuelFlow = engine.maxFuelFlow;
        }
        else
        {
            engineType = EngineModuleType.UNKNOWN;
        }
    }
예제 #56
0
 public override void OnStart(PartModule.StartState state)
 {
     Debug.Log("KTengineHover OnStart");
     base.OnStart(state);
     if (HighLogic.LoadedSceneIsFlight)
     {
         engine = part.Modules.OfType<ModuleEngines>().FirstOrDefault();
         if (engine != null)
         {
             if (maxThrustFetched && maxThrust > 0f)
             {
                 engine.maxThrust = maxThrust;
             }
             else
             {
                 maxThrust = engine.maxThrust;
                 maxThrustFetched = true;
             }
             minThrust = engine.minThrust;
         }
     }
 }
예제 #57
0
        private void updateUsage(float rate)
        {
            if (module == null)
            {
                module = Utils.getModuleByType<ModuleEngines>(base.part);
                return;
            }

            // usage due to time
            float timeUsage = usageUtils.getPartUsageInTime(rate);

            // usage modifier
            float usageMod = 1.0f;

            // modify usage when firing
            // modify usage when not shutdown
            // FIX: enabled/disabled?
            if (base.isActiveAndEnabled)
            {
                usageMod += 0.5f * module.currentThrottle + 0.2f;
            }

            conditionEngine -= timeUsage * usageMod * usageUtils.GLOBAL_MOD;
        }
예제 #58
0
 public EngineWrapper(ModuleEngines module)
 {
     engine = module;
 }
예제 #59
0
        public override void OnStart(PartModule.StartState state)
        {
            part.maxTemp = maxTemp;
            part.thermalMass = 1;
            part.thermalMassModifier = 1;

            engineType = originalName;
            //curEngineT = (ModuleEnginesFX)this.part.Modules["ModuleEnginesFX"];
            curEngineT = this.part.FindModuleImplementing<ModuleEngines>();

            if (curEngineT == null) return;

            minISP = curEngineT.atmosphereCurve.Evaluate(0);
            //currentHeatProduction = curEngineT.heatProduction;

            standard_deuterium_rate = curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.Deuterium).ratio;
            standard_tritium_rate = curEngineT.propellants.FirstOrDefault(pr => pr.name == InterstellarResourcesConfiguration.Instance.Tritium).ratio;

            // if we can upgrade, let's do so
            if (isupgraded)
                upgradePartModule();
            else if (this.HasTechsRequiredToUpgrade())
                hasrequiredupgrade = true;

            // calculate WasteHeat Capacity
            part.Resources[FNResourceManager.FNRESOURCE_WASTEHEAT].maxAmount = part.mass * 1.0e+5 * wasteHeatMultiplier;

            if (state == StartState.Editor && this.HasTechsRequiredToUpgrade())
            {
                isupgraded = true;
                upgradePartModule();
            }

            if (state != StartState.Editor)
                part.emissiveConstant = maxTempatureRadiators > 0 ? 1 - coldBathTemp / maxTempatureRadiators : 0.01;
        }
		public override void OnStart(PartModule.StartState state) {
            engineType = originalName;
            myAttachedEngine = this.part.Modules["ModuleEngines"] as ModuleEngines;
            // find attached thermal source
            foreach (AttachNode attach_node in part.attachNodes) {
                if (attach_node.attachedPart != null) {
                    List<IThermalSource> sources = attach_node.attachedPart.FindModulesImplementing<IThermalSource>();
                    if (sources.Count > 0) {
                        myAttachedReactor = sources.First();
                        if (myAttachedReactor != null) {
                            break;
                        }
                    }
                }
            }

            if (state == StartState.Editor) {
                part.OnEditorAttach += OnEditorAttach;
                propellants = getPropellants(isJet);
                if (this.HasTechsRequiredToUpgrade() && isJet)
                {
                    isupgraded = true;
                    upgradePartModule();
                }
                setupPropellants();
                estimateEditorPerformance();
                return;
            }
			fuel_gauge = part.stackIcon.DisplayInfo();
			
            // if engine isn't already initialised, initialise it
			if (engineInit == false) {
				engineInit = true;
			}
			// if we can upgrade, let's do so
			if (isupgraded && isJet) {
				upgradePartModule ();
			} else {
                if (this.HasTechsRequiredToUpgrade() && isJet)
                {
                    hasrequiredupgrade = true;
                }
				// if not, use basic propellants
				propellants = getPropellants (isJet);
			}
			
			setupPropellants();
			hasstarted = true;

			//print ("Start Complete");
		}