public override void Start()
        {
            base.Start();
            if (ullageSet == null)
            {
                ullageSet = new Ullage.UllageSet(this);
            }

            showPropStatus = (pressureFed || (ullage && RFSettings.Instance.simulateUllage));

            Fields["ignitions"].guiActive         = Fields["ignitions"].guiActiveEditor = (ignitions >= 0 && RFSettings.Instance.limitedIgnitions);
            Fields["propellantStatus"].guiActive  = Fields["propellantStatus"].guiActiveEditor = showPropStatus;
            Fields[nameof(pressureFed)].guiActive = true;

            igniteFailIgnitions = new ScreenMessage("<color=orange>[" + part.partInfo.title + "]: no ignitions remaining!</color>", 5f, ScreenMessageStyle.UPPER_CENTER);
            igniteFailResources = new ScreenMessage("<color=orange>[" + part.partInfo.title + "]: insufficient resources to ignite!</color>", 5f, ScreenMessageStyle.UPPER_CENTER);
            ullageFail          = new ScreenMessage("<color=orange>[" + part.partInfo.title + "]: vapor in feedlines, shut down!</color>", 5f, ScreenMessageStyle.UPPER_CENTER);
        }
        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)
                {
                    log.error("curveResource doesn't match node's!");
                    curveResource = node.GetValue("curveResource");
                }
                if (thrustCurve == null)
                {
                    log.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);
                log.info(this.name + "{0}.pressureFed = {1}", this.name, 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);
            }
        }