public override void OnStart(PartModule.StartState state)
        {
            if (CloseAnimationName != "")
            {

                openAnim = true;
            }
            if (LoopAnimationName != "")
            {
                loopAnim = true;
            }
            if (HighLogic.LoadedSceneIsFlight)
            {
                intake = gameObject.GetComponent<ModuleResourceIntake>();
                if (intake == null)
                {
                    Utils.LogError("AnimatedIntake requires an intake module!");
                    return;
                }
                if (openAnim)
                {
                    Utils.Log("Setting up close animation");
                    openStates = Utils.SetUpAnimation(CloseAnimationName, this.part);
                }
                if (loopAnim)
                {
                    Utils.Log("Setting up loop animation");
                    loopStates = Utils.SetUpAnimation(LoopAnimationName, this.part);
                }

            }
        }
Exemplo n.º 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);
 }
Exemplo n.º 3
0
        public IntegratedIntakeEngineCrossSectionAdjuster(ModuleResourceIntake intake, Matrix4x4 worldToVesselMatrix)
        {
            this.part = intake.part;
            //ModuleResourceIntake intake = intake;

            intakeTrans = part.FindModelTransform(intake.intakeTransformName);
            vehicleBasisForwardVector = Vector3.forward;//intakeTrans.forward;

            if (intakeTrans == null)
            {
                intakeTrans = intake.part.partTransform;
            }

            foreach (AttachNode node in part.attachNodes)
            {
                if (node.nodeType == AttachNode.NodeType.Stack && Vector3.Dot(node.position, (part.transform.worldToLocalMatrix * intakeTrans.localToWorldMatrix).MultiplyVector(Vector3.forward)) > 0)
                {
                    frontNode = node;
                    break;
                }
            }

            thisToVesselMatrix = worldToVesselMatrix * intakeTrans.localToWorldMatrix;

            vehicleBasisForwardVector = thisToVesselMatrix.MultiplyVector(vehicleBasisForwardVector);

            intakeArea = INTAKE_AREA_SCALAR * intake.area;
        }
        public override void OnStart(PartModule.StartState state)
        {
            if (state == StartState.Editor)
            {
                return;                             // don't do any of this stuff in editor
            }
            bool hasJetUpgradeTech0 = PluginHelper.HasTechRequirementOrEmpty(PluginHelper.JetUpgradeTech1);
            bool hasJetUpgradeTech1 = PluginHelper.HasTechRequirementOrEmpty(PluginHelper.JetUpgradeTech2);
            bool hasJetUpgradeTech2 = PluginHelper.HasTechRequirementOrEmpty(PluginHelper.JetUpgradeTech3);
            bool hasJetUpgradeTech3 = PluginHelper.HasTechRequirementOrEmpty(PluginHelper.JetUpgradeTech4);

            var jetTechBonus = Convert.ToInt32(hasJetUpgradeTech0) + 1.2f * Convert.ToInt32(hasJetUpgradeTech1) + 1.44f * Convert.ToInt32(hasJetUpgradeTech2) + 1.728f * Convert.ToInt32(hasJetUpgradeTech3);

            jetTechBonusPercentage = 10 * (1 + (jetTechBonus / 10.736f));

            _moduleResourceIntake = this.part.FindModuleImplementing <ModuleResourceIntake>();

            // if _moduleResourceIntake is null there SHOULD be an exception - and it's a good thing.
            area = _moduleResourceIntake.area;
            intakeTransformName = _moduleResourceIntake.intakeTransformName;
            unitScalar          = _moduleResourceIntake.unitScalar;

            atmosphereBuffer = area * unitScalar * jetTechBonusPercentage * maxIntakeSpeed * 300;

            _intake_atmosphere_resource = part.Resources[InterstellarResourcesConfiguration.Instance.IntakeAtmosphere];
            _resourceAtmosphere         = PartResourceLibrary.Instance.GetDefinition(InterstellarResourcesConfiguration.Instance.IntakeAtmosphere);
            _intake_speed = maxIntakeSpeed;
        }
        public IntegratedIntakeEngineCrossSectionAdjuster(PartModule intake, Matrix4x4 worldToVesselMatrix)
        {
            this.part = intake.part;
            intakeModule = intake as ModuleResourceIntake;
            intakeTrans = intakeModule.intakeTransform;
            //ModuleResourceIntake intake = intake;


            /*vehicleBasisForwardVector = Vector3.forward;//intakeTrans.forward;

            foreach(AttachNode node in part.attachNodes)
                if(node.nodeType == AttachNode.NodeType.Stack && Vector3.Dot(node.position, (part.transform.worldToLocalMatrix * intakeTrans.localToWorldMatrix).MultiplyVector(Vector3.forward)) > 0)
                {
                    frontNode = node;
                    break;
                }*/

            thisToVesselMatrix = worldToVesselMatrix * intakeTrans.localToWorldMatrix;

            vehicleBasisForwardVector = Vector3.forward;
            vehicleBasisForwardVector = thisToVesselMatrix.MultiplyVector(vehicleBasisForwardVector);

            Type intakeType = intake.GetType();
            intakeArea = (float)intakeType.GetField("Area").GetValue(intake);
        }
Exemplo n.º 6
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);
 }
        public IntakeCrossSectionAdjuster(PartModule intake, Matrix4x4 worldToVesselMatrix)
        {
            this.part = intake.part;
            intakeModule = intake as ModuleResourceIntake;
            intakeTrans = intakeModule.intakeTransform;

            if (!string.IsNullOrEmpty(intakeModule.occludeNode))
                node = intakeModule.node; 
            
            foreach (AttachNode candidateNode in part.attachNodes)
                if (candidateNode.nodeType == AttachNode.NodeType.Stack && Vector3.Dot(candidateNode.position, (part.transform.worldToLocalMatrix * intakeTrans.localToWorldMatrix).MultiplyVector(Vector3.forward)) > 0)
                {
                    if (candidateNode == node)
                        continue;

                    nodeOffsetArea = candidateNode.size;
                    if (nodeOffsetArea == 0)
                        nodeOffsetArea = 0.5;

                    nodeOffsetArea *= 0.625;     //scale it up as needed
                    nodeOffsetArea *= nodeOffsetArea;
                    nodeOffsetArea *= Math.PI;  //calc area;

                    nodeOffsetArea *= -1;        //and the adjustment area
                    break;
                }

            thisToVesselMatrix = worldToVesselMatrix * intakeTrans.localToWorldMatrix;

            vehicleBasisForwardVector = Vector3.forward;
            vehicleBasisForwardVector = thisToVesselMatrix.MultiplyVector(vehicleBasisForwardVector);

            Type intakeType = intake.GetType();
            intakeArea = (float)intakeType.GetField("Area").GetValue(intake);
        }
Exemplo n.º 8
0
        public override void OnStart(PartModule.StartState state)
        {
            if (state == StartState.Editor)
            {
                return;                             // don't do any of this stuff in editor
            }
            _moduleResourceIntake = this.part.FindModuleImplementing <ModuleResourceIntake>();

            if (_moduleResourceIntake == null)
            {
                return;
            }

            bool hasJetUpgradeTech0 = PluginHelper.HasTechRequirementOrEmpty(PluginHelper.JetUpgradeTech1);
            bool hasJetUpgradeTech1 = PluginHelper.HasTechRequirementOrEmpty(PluginHelper.JetUpgradeTech2);
            bool hasJetUpgradeTech2 = PluginHelper.HasTechRequirementOrEmpty(PluginHelper.JetUpgradeTech3);
            bool hasJetUpgradeTech3 = PluginHelper.HasTechRequirementOrEmpty(PluginHelper.JetUpgradeTech4);

            var jetTechBonus = Convert.ToInt32(hasJetUpgradeTech0) + 1.2f * Convert.ToInt32(hasJetUpgradeTech1) + 1.44f * Convert.ToInt32(hasJetUpgradeTech2) + 1.728f * Convert.ToInt32(hasJetUpgradeTech3);

            jetTechBonusPercentage = 10 * (1 + (jetTechBonus / 10.736f));

            area = _moduleResourceIntake.area;
            intakeTransformName = _moduleResourceIntake.intakeTransformName;
            unitScalar          = _moduleResourceIntake.unitScalar;

            resourceBuffers = new ResourceBuffers();
            resourceBuffers.AddConfiguration(
                new ResourceBuffers.TimeBasedConfig(InterstellarResourcesConfiguration.Instance.IntakeAtmosphere, 300, area * unitScalar * jetTechBonusPercentage * maxIntakeSpeed));
            resourceBuffers.Init(this.part);

            _resourceAtmosphere = PartResourceLibrary.Instance.GetDefinition(InterstellarResourcesConfiguration.Instance.IntakeAtmosphere);
            _intake_speed       = maxIntakeSpeed;
        }
Exemplo n.º 9
0
        public void SetupAdjuster(ModuleResourceIntake intake, Matrix4x4 worldToVesselMatrix)
        {
            this.part    = intake.part;
            intakeModule = intake as ModuleResourceIntake;
            intakeTrans  = intakeModule.intakeTransform;
            //ModuleResourceIntake intake = intake;

            /*intakeTrans = part.FindModelTransform(intake.intakeTransformName);
             * vehicleBasisForwardVector = Vector3.forward;//intakeTrans.forward;
             *
             * foreach (AttachNode node in part.attachNodes)
             *  if (node.nodeType == AttachNode.NodeType.Stack && Vector3.Dot(node.position, (part.transform.worldToLocalMatrix * intakeTrans.localToWorldMatrix).MultiplyVector(Vector3.forward)) > 0)
             *  {
             *      frontNode = node;
             *      break;
             *  }*/

            thisToVesselMatrix = worldToVesselMatrix * intakeTrans.localToWorldMatrix;

            vehicleBasisForwardVector = Vector3.forward;
            vehicleBasisForwardVector = thisToVesselMatrix.MultiplyVector(vehicleBasisForwardVector);

            intakeArea = INTAKE_AREA_SCALAR * intake.area;

            FARLogger.Info("Integrated cross-section adjuster");
        }
        public override void OnStart(PartModule.StartState state)
        {
            if (state == StartState.Editor)
            {
                return;                             // don't do any of this stuff in editor
            }
            bool hasJetUpgradeTech0 = PluginHelper.HasTechRequirementOrEmpty(PluginHelper.JetUpgradeTech1);
            bool hasJetUpgradeTech1 = PluginHelper.HasTechRequirementOrEmpty(PluginHelper.JetUpgradeTech2);
            bool hasJetUpgradeTech2 = PluginHelper.HasTechRequirementOrEmpty(PluginHelper.JetUpgradeTech3);
            bool hasJetUpgradeTech3 = PluginHelper.HasTechRequirementOrEmpty(PluginHelper.JetUpgradeTech4);

            var jetTechBonus = Convert.ToInt32(hasJetUpgradeTech0) + 1.2f * Convert.ToInt32(hasJetUpgradeTech1) + 1.44f * Convert.ToInt32(hasJetUpgradeTech2) + 1.728f * Convert.ToInt32(hasJetUpgradeTech3);

            jetTechBonusPercentage = 10 * (1 + (jetTechBonus / 10.736f));

            _moduleResourceIntake = this.part.FindModuleImplementing <ModuleResourceIntake>();

            foundModuleResourceIntake = _moduleResourceIntake != null;

            atmosphereBuffer = area * unitScalar * jetTechBonusPercentage * maxIntakeSpeed * 300;

            if (!part.Resources.Contains(InterstellarResourcesConfiguration.Instance.IntakeAtmosphere))
            {
                ConfigNode node = new ConfigNode("RESOURCE");
                node.AddValue("name", InterstellarResourcesConfiguration.Instance.IntakeAtmosphere);
                node.AddValue("maxAmount", atmosphereBuffer);
                node.AddValue("amount", 0);
                part.AddResource(node);
            }
            _intake_atmosphere_resource = part.Resources[InterstellarResourcesConfiguration.Instance.IntakeAtmosphere];
            _resourceAtmosphere         = PartResourceLibrary.Instance.GetDefinition(InterstellarResourcesConfiguration.Instance.IntakeAtmosphere);
            _intake_speed = maxIntakeSpeed;
        }
Exemplo n.º 11
0
        public void SetupAdjuster(PartModule intake, Matrix4x4 worldToVesselMatrix)
        {
            this.part    = intake.part;
            intakeModule = intake as ModuleResourceIntake;
            intakeTrans  = intakeModule.intakeTransform;
            //ModuleResourceIntake intake = intake;


            /*vehicleBasisForwardVector = Vector3.forward;//intakeTrans.forward;
             *
             * foreach(AttachNode node in part.attachNodes)
             *  if(node.nodeType == AttachNode.NodeType.Stack && Vector3.Dot(node.position, (part.transform.worldToLocalMatrix * intakeTrans.localToWorldMatrix).MultiplyVector(Vector3.forward)) > 0)
             *  {
             *      frontNode = node;
             *      break;
             *  }*/

            thisToVesselMatrix = worldToVesselMatrix * intakeTrans.localToWorldMatrix;

            vehicleBasisForwardVector = Vector3.forward;
            vehicleBasisForwardVector = thisToVesselMatrix.MultiplyVector(vehicleBasisForwardVector);

            Type intakeType = intake.GetType();

            intakeArea = (float)intakeType.GetField("Area").GetValue(intake);
        }
    protected override bool SetupModule()
    {
        if (!base.SetupModule())
        {
            return(false);
        }

        foreach (PartModule current in part.Modules)
        {
            if (current.GetType().UnderlyingSystemType != typeof(ModuleResourceIntake))
            {
                continue;
            }

            _Intake     = current as ModuleResourceIntake;
            _AirSpeed   = _Intake.GetType().GetField("airSpeedGui");
            _AirFlow    = _Intake.GetType().GetField("airFlow");
            _IntakeOpen = _Intake.GetType().GetField("intakeEnabled");

            break;
        }

        return(_Intake != null &&
               _AirSpeed != null &&
               _IntakeOpen != null);
    }
 public override void OnStart(PartModule.StartState state)
 {
     if (CloseAnimationName != "")
     {
         openAnim = true;
     }
     if (LoopAnimationName != "")
     {
         loopAnim = true;
     }
     if (HighLogic.LoadedSceneIsFlight)
     {
         intake = gameObject.GetComponent <ModuleResourceIntake>();
         if (intake == null)
         {
             Utils.LogError("AnimatedIntake requires an intake module!");
             return;
         }
         if (openAnim)
         {
             Utils.Log("Setting up close animation");
             openStates = Utils.SetUpAnimation(CloseAnimationName, this.part);
         }
         if (loopAnim)
         {
             Utils.Log("Setting up loop animation");
             loopStates = Utils.SetUpAnimation(LoopAnimationName, this.part);
         }
     }
 }
Exemplo n.º 14
0
        public static IntegratedIntakeEngineCrossSectionAdjuster CreateAdjuster(ModuleResourceIntake intake, Matrix4x4 worldToVesselMatrix)
        {
            IntegratedIntakeEngineCrossSectionAdjuster adjuster = new IntegratedIntakeEngineCrossSectionAdjuster();

            adjuster.SetupAdjuster(intake, worldToVesselMatrix);

            return(adjuster);
        }
Exemplo n.º 15
0
 public override void OnStart(StartState state)
 {
     if (state == StartState.Editor)
         return;
     if (vessel == null)
         return;
     intake=(ModuleResourceIntake)part.Modules["ModuleResourceIntake"];
 }
Exemplo n.º 16
0
        //Returns the intake air required by all engines in the vessel
        //Intake air calculation courtesy of FAR and a.g.
        public static double getRequiredAir(Vessel v, out double airReq, out double airAvailable)
        {
            double dt = TimeWarp.fixedDeltaTime;

            //if (SteamGauges.debug) Debug.Log("dT: " + Math.Round(dt, 3));
            airReq = airAvailable = 0;
            foreach (Part P in v.parts)
            {
                foreach (PartModule PM in P.Modules)
                {
                    if (PM is ModuleEngines)
                    {
                        ModuleEngines ME = PM as ModuleEngines;
                        if (ME.engineShutdown || !ME.EngineIgnited)
                        {
                            continue;
                        }
                        foreach (Propellant Pro in ME.propellants)
                        {
                            if (Pro.name.Equals("IntakeAir"))
                            {
                                //if (SteamGauges.debug) Debug.Log("Air Req: " + Math.Round(Pro.currentRequirement,2));
                                airReq += Pro.currentRequirement;
                            }
                        }
                    }
                    else if (PM is ModuleEnginesFX)  //tricky RAPIERs!
                    {
                        ModuleEnginesFX MFX = PM as ModuleEnginesFX;
                        if (MFX.engineShutdown || !MFX.EngineIgnited)
                        {
                            continue;
                        }
                        foreach (Propellant Pro in MFX.propellants)
                        {
                            if (Pro.name.Equals("IntakeAir"))
                            {
                                //if (SteamGauges.debug) Debug.Log("Air Req: " + Math.Round(Pro.currentRequirement, 2));
                                airReq += Pro.currentRequirement;
                            }
                        }
                    }
                    else if (PM is ModuleResourceIntake)
                    {
                        ModuleResourceIntake MRI = PM as ModuleResourceIntake;
                        if (MRI.intakeEnabled && MRI.resourceName.Equals("IntakeAir"))
                        {
                            //if (SteamGauges.debug) Debug.Log("Air In: " + Math.Round(MRI.airFlow*dt, 2));
                            airAvailable += MRI.airFlow * dt;
                        }
                    }
                }
            }
            //Debug.Log("Calc Air: " + Math.Round(airAvailable/airReq, 2));
            //Debug.Log("Sim Air: " + Math.Round(SteamShip.AirPercent, 2));
            //if (SteamGauges.debug) Debug.Log("Air Req: " + Math.Round(airReq, 2) + " In: " + Math.Round(airAvailable, 2));
            return(airReq);
        }
Exemplo n.º 17
0
        public static Vector3 GuessUpVector(Part part)
        {
            // For intakes, use the intake vector
            if (part.Modules.Contains("ModuleResourceIntake"))
            {
                ModuleResourceIntake i           = part.Modules["ModuleResourceIntake"] as ModuleResourceIntake;
                Transform            intakeTrans = part.FindModelTransform(i.intakeTransformName);
                if ((object)intakeTrans != null)
                {
                    return(part.transform.InverseTransformDirection(intakeTrans.forward));
                }
            }
            // If surface attachable, and node normal is up, check stack nodes or use forward
            if (part.srfAttachNode != null &&
                part.attachRules.srfAttach &&
                Mathf.Abs(part.srfAttachNode.orientation.normalized.y) > 0.9f)
            {
                // When the node normal is exactly Vector3.up, the editor orients forward along the craft axis
                Vector3 dir     = Vector3.forward;
                String  dirname = null;

                foreach (AttachNode node in part.attachNodes)
                {
                    // Doesn't seem to ever happen, but anyway
                    if (node.nodeType == AttachNode.NodeType.Surface)
                    {
                        continue;
                    }

                    if (node.id.ToLowerInvariant() == "strut")
                    {
                        continue;
                    }

                    // If all node orientations agree, use that axis
                    String name = UpVectorFromDir(node.orientation);

                    if (dirname == null)
                    {
                        dirname = name;
                        dir     = node.orientation;
                    }
                    // Conflicting node directions - bail out
                    else if (dirname != name)
                    {
                        return(Vector3.up);
                    }
                }

                //Debug.Log(part.partInfo.title + ": Choosing " + (dirname == null ? "heuristic forward" : dirname) + " axis for FAR drag model.");
                return(dir);
            }
            else
            {
                return(Vector3.up);
            }
        }
Exemplo n.º 18
0
 internal Intake(Part part)
 {
     Part   = part;
     intake = part.InternalPart.Module <ModuleResourceIntake> ();
     if (intake == null)
     {
         throw new ArgumentException("Part is not an intake");
     }
 }
        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);
            }
        }
Exemplo n.º 20
0
 public override void OnStart(StartState state)
 {
     if (state == StartState.Editor)
     {
         return;
     }
     if (vessel == null)
     {
         return;
     }
     intake = (ModuleResourceIntake)part.Modules["ModuleResourceIntake"];
 }
Exemplo n.º 21
0
        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);
            }
        }
        public override void OnStart(PartModule.StartState state) {
            if (state == StartState.Editor) { return; }

            foreach (AttachNode attach_node in part.attachNodes) {
                if (attach_node.attachedPart != null) {
                    List<ModuleResourceIntake> mres = attach_node.attachedPart.FindModulesImplementing<ModuleResourceIntake>().Where(mre => mre.resourceName == "IntakeAir").ToList();
                    if(mres.Count > 0) {
                        attachedIntake = mres.First();
                    }
                }
            }
            part.force_activate();
        }
        public static Vector3 GuessUpVector(Part part)
        {
            // For intakes, use the intake vector
            if (part.Modules.Contains <ModuleResourceIntake>())
            {
                ModuleResourceIntake i           = part.Modules.GetModule <ModuleResourceIntake>();
                Transform            intakeTrans = part.FindModelTransform(i.intakeTransformName);
                return(part.transform.InverseTransformDirection(intakeTrans.forward));
            }
            // If surface attachable, and node normal is up, check stack nodes or use forward
            else if (part.srfAttachNode != null &&
                     part.attachRules.srfAttach &&
                     Mathf.Abs(part.srfAttachNode.orientation.normalized.y) > 0.9f)
            {
                // When the node normal is exactly Vector3.up, the editor orients forward along the craft axis
                Vector3 dir   = Vector3.forward;
                bool    first = true;

                foreach (AttachNode node in part.attachNodes)
                {
                    // Doesn't seem to ever happen, but anyway
                    if (node.nodeType == AttachNode.NodeType.Surface)
                    {
                        continue;
                    }

                    // If all node orientations agree, use that axis
                    if (first)
                    {
                        first = false;
                        dir   = node.orientation.normalized;
                    }
                    // Conflicting node directions - bail out
                    else if (Mathf.Abs(Vector3.Dot(dir, node.orientation.normalized)) < 0.9f)
                    {
                        return(Vector3.up);
                    }
                }

                if (debug)
                {
                    MonoBehaviour.print(part.partInfo.title + ": Choosing axis " + dir + " for KJR surface attach" + (first ? "" : " from node") + ".");
                }

                return(dir);
            }
            else
            {
                return(Vector3.up);
            }
        }
        public void SetupAdjuster(ModuleResourceIntake intake, Matrix4x4 worldToVesselMatrix)
        {
            part         = intake.part;
            intakeModule = intake;
            intakeTrans  = intakeModule.intakeTransform;
            if (intakeTrans == null)
            {
                intakeTrans = intake.part.partTransform;
            }

            if (!string.IsNullOrEmpty(intakeModule.occludeNode))
            {
                node = intakeModule.node;
            }

            foreach (AttachNode candidateNode in part.attachNodes)
            {
                if (candidateNode.nodeType == AttachNode.NodeType.Stack &&
                    Vector3.Dot(candidateNode.position,
                                (part.transform.worldToLocalMatrix * intakeTrans.localToWorldMatrix)
                                .MultiplyVector(Vector3.forward)) >
                    0)
                {
                    if (candidateNode == node)
                    {
                        continue;
                    }

                    nodeOffsetArea = candidateNode.size;
                    if (nodeOffsetArea.NearlyEqual(0))
                    {
                        nodeOffsetArea = 0.5;
                    }

                    nodeOffsetArea *= 0.625;   //scale it up as needed
                    nodeOffsetArea *= nodeOffsetArea;
                    nodeOffsetArea *= Math.PI; //calc area;

                    nodeOffsetArea *= -1;      //and the adjustment area
                    break;
                }
            }

            thisToVesselMatrix = worldToVesselMatrix * intakeTrans.localToWorldMatrix;

            vehicleBasisForwardVector = Vector3.forward;
            vehicleBasisForwardVector = thisToVesselMatrix.MultiplyVector(vehicleBasisForwardVector);

            intakeArea = INTAKE_AREA_SCALAR * intake.area;
        }
Exemplo n.º 25
0
        public void SetupAdjuster(ModuleResourceIntake intake, Matrix4x4 worldToVesselMatrix)
        {
            part         = intake.part;
            intakeModule = intake;
            intakeTrans  = intakeModule.intakeTransform;

            thisToVesselMatrix = worldToVesselMatrix * intakeTrans.localToWorldMatrix;

            vehicleBasisForwardVector = Vector3.forward;
            vehicleBasisForwardVector = thisToVesselMatrix.MultiplyVector(vehicleBasisForwardVector);

            intakeArea = INTAKE_AREA_SCALAR * intake.area;

            FARLogger.Info("Integrated cross-section adjuster");
        }
        public override void OnStart(PartModule.StartState state)
        {
            Debug.Log("[KSPI]: AtmosphericIntake OnStart Reading PluginHelper Upgrades");

            JetUpgradeTech1 = PluginHelper.JetUpgradeTech1;
            JetUpgradeTech2 = PluginHelper.JetUpgradeTech2;
            JetUpgradeTech3 = PluginHelper.JetUpgradeTech3;
            JetUpgradeTech4 = PluginHelper.JetUpgradeTech4;
            JetUpgradeTech5 = PluginHelper.JetUpgradeTech5;

            hasJetUpgradeTech1 = PluginHelper.HasTechRequirementOrEmpty(PluginHelper.JetUpgradeTech1);
            hasJetUpgradeTech2 = PluginHelper.HasTechRequirementOrEmpty(PluginHelper.JetUpgradeTech2);
            hasJetUpgradeTech3 = PluginHelper.HasTechRequirementOrEmpty(PluginHelper.JetUpgradeTech3);
            hasJetUpgradeTech4 = PluginHelper.HasTechRequirementOrEmpty(PluginHelper.JetUpgradeTech4);
            hasJetUpgradeTech5 = PluginHelper.HasTechRequirementOrEmpty(PluginHelper.JetUpgradeTech5);

            var jetTech = Convert.ToInt32(hasJetUpgradeTech1) * 1.2f + 1.44f * Convert.ToInt32(hasJetUpgradeTech2) + 1.728f * Convert.ToInt32(hasJetUpgradeTech3) + 2.0736f * Convert.ToInt32(hasJetUpgradeTech4) + 2.48832f * Convert.ToInt32(hasJetUpgradeTech5);

            jetTechBonus = 5 * (1 + (jetTech / 9.92992f));

            _moduleResourceIntake         = this.part.FindModulesImplementing <ModuleResourceIntake>().FirstOrDefault(m => m.resourceName == InterstellarResourcesConfiguration._INTAKE_AIR);
            _resourceAtmosphereDefinition = PartResourceLibrary.Instance.GetDefinition(InterstellarResourcesConfiguration.Instance.IntakeAtmosphere);

            if (_moduleResourceIntake == null)
            {
                Debug.LogWarning("[KSPI]: ModuleResourceIntake with IntakeAir is missing on " + part.partInfo.title);
            }

            var field        = Fields["intakeOpen"];
            var flightToggle = field.uiControlFlight as UI_Toggle;
            var editorToggle = field.uiControlEditor as UI_Toggle;

            flightToggle.onFieldChanged = IntakeOpenChanged;
            editorToggle.onFieldChanged = IntakeOpenChanged;

            UpdateResourceIntakeConfiguration();

            if (state == StartState.Editor)
            {
                return;                             // don't do any of this stuff in editor
            }
            resourceBuffers = new ResourceBuffers();
            resourceBuffers.AddConfiguration(new ResourceBuffers.TimeBasedConfig(InterstellarResourcesConfiguration.Instance.IntakeAtmosphere, 300, area * unitScalar * 100));
            resourceBuffers.Init(this.part);
        }
Exemplo n.º 27
0
        protected void setupGUI()
        {
            //Hide seat GUI
            seat = this.part.FindModuleImplementing <KerbalSeat>();
            seat.Events["BoardSeat"].guiActive          = false;
            seat.Events["BoardSeat"].guiActiveEditor    = false;
            seat.Events["BoardSeat"].guiActiveUnfocused = false;

            //Hide probe command GUI
            wingCommander = this.part.FindModuleImplementing <ModuleCommand>();
            wingCommander.Events["MakeReference"].guiActive          = false;
            wingCommander.Events["MakeReference"].guiActiveUnfocused = false;
            wingCommander.Events["RenameVessel"].guiActive           = false;

            //Hide decoupler GUI
            decoupler = this.part.FindModuleImplementing <ModuleDecouple>();
            decoupler.Events["Decouple"].guiActive          = false;
            decoupler.Events["Decouple"].guiActiveEditor    = false;
            decoupler.Events["Decouple"].guiActiveUnfocused = false;

            //Hide MultiModeEngine toggle button
            multiModeEngine = this.part.FindModuleImplementing <MultiModeEngine>();
            multiModeEngine.Events["ModeEvent"].guiActive          = false;
            multiModeEngine.Events["ModeEvent"].guiActiveEditor    = false;
            multiModeEngine.Events["ModeEvent"].guiActiveUnfocused = false;

            //Hide the Close Intake button.
            ModuleResourceIntake intake = this.part.FindModuleImplementing <ModuleResourceIntake>();

            intake.Events["Deactivate"].guiActive = false;

            //Hide RCS GUI
            ModuleRCS rcs = this.part.FindModuleImplementing <ModuleRCS>();

            rcs.Fields["realISP"].guiActive    = false;
            rcs.Fields["rcsEnabled"].guiActive = false;

            //Hide hover engine gui
            hoverEngine = this.part.FindModuleImplementing <WBIMultiEngineHover>();
            hoverEngine.SetGUIVisible(false);

            //Set fuel type
            resourceSwitcher = this.part.FindModuleImplementing <WBIResourceSwitcher>();
            resourceSwitcher.Fields["shortName"].guiName = "Fuel Type";
        }
Exemplo n.º 28
0
            public void addIntake(ModuleResourceIntake intake)
            {
                // TODO: figure out how much airflow we have, how much we could have,
                // drag, etc etc.
                List <ModuleResourceIntake> thelist;
                int id = PartResourceLibrary.Instance.GetDefinition(intake.resourceName).id;

                if (allIntakes.ContainsKey(id))
                {
                    thelist = allIntakes[id];
                }
                else
                {
                    thelist        = new List <ModuleResourceIntake>();
                    allIntakes[id] = thelist;
                }
                thelist.Add(intake);
            }
Exemplo n.º 29
0
            // Return the number of kg of resource provided per second under certain conditions.
            // We use kg since the numbers are typically small.
            private double massProvided(double vesselSpeed, Vector3d vesselFwd, double atmDensity,
                                        ModuleResourceIntake intake, Vector3d intakeFwd)
            {
                if (intake.checkForOxygen && !FlightGlobals.currentMainBody.atmosphereContainsOxygen)
                {
                    return(0);
                }

                // This is adapted from code shared by Amram at:
                // http://forum.kerbalspaceprogram.com/showthread.php?34288-Maching-Bird-Challeng?p=440505
                // Seems to be accurate for 0.18.2 anyway.
                double intakeSpeed = intake.maxIntakeSpeed; // airspeed when the intake isn't moving

                double aoa = Vector3d.Dot(vesselFwd, intakeFwd);

                if (aoa < 0)
                {
                    aoa = 0;
                }
                else if (aoa > 1)
                {
                    aoa = 1;
                }

                double finalSpeed;

                if (aoa <= intake.aoaThreshold)
                {
                    finalSpeed = intakeSpeed;
                }
                else
                {
                    // This is labeled as a bug for double-counting intakeSpeed.
                    // It also double-counts unitScalar...
                    double airSpeedGUI = vesselSpeed + intakeSpeed;
                    double airSpeed    = airSpeedGUI * intake.unitScalar;
                    finalSpeed = aoa * (airSpeed + intakeSpeed);
                }
                double airVolume = finalSpeed * intake.area * intake.unitScalar;
                double airmass   = atmDensity * airVolume; // tonnes per second

                // TODO: limit by the amount the intake can store
                return(airmass * 1000);
            }
Exemplo n.º 30
0
        public void SetupAdjuster(PartModule intake, Matrix4x4 worldToVesselMatrix)
        {
            this.part    = intake.part;
            intakeModule = intake as ModuleResourceIntake;
            intakeTrans  = intakeModule.intakeTransform;

            if (!string.IsNullOrEmpty(intakeModule.occludeNode))
            {
                node = intakeModule.node;
            }

            foreach (AttachNode candidateNode in part.attachNodes)
            {
                if (candidateNode.nodeType == AttachNode.NodeType.Stack && Vector3.Dot(candidateNode.position, (part.transform.worldToLocalMatrix * intakeTrans.localToWorldMatrix).MultiplyVector(Vector3.forward)) > 0)
                {
                    if (candidateNode == node)
                    {
                        continue;
                    }

                    nodeOffsetArea = candidateNode.size;
                    if (nodeOffsetArea == 0)
                    {
                        nodeOffsetArea = 0.5;
                    }

                    nodeOffsetArea *= 0.625;    //scale it up as needed
                    nodeOffsetArea *= nodeOffsetArea;
                    nodeOffsetArea *= Math.PI;  //calc area;

                    nodeOffsetArea *= -1;       //and the adjustment area
                    break;
                }
            }

            thisToVesselMatrix = worldToVesselMatrix * intakeTrans.localToWorldMatrix;

            vehicleBasisForwardVector = Vector3.forward;
            vehicleBasisForwardVector = thisToVesselMatrix.MultiplyVector(vehicleBasisForwardVector);

            Type intakeType = intake.GetType();

            intakeArea = (float)intakeType.GetField("Area").GetValue(intake);
        }
Exemplo n.º 31
0
        private static void intakeAirForEachModule(object sender, VOIDForEachPartModuleArgs args)
        {
            PartModule        module         = args.Data;
            List <Propellant> propellantList = null;

            if (!module.part.enabled)
            {
                return;
            }

            if (module is ModuleEngines)
            {
                propellantList = ((ModuleEngines)module).propellants;
            }
            else if (module is ModuleEnginesFX)
            {
                propellantList = ((ModuleEnginesFX)module).propellants;
            }
            else if (module is ModuleResourceIntake)
            {
                ModuleResourceIntake intakeModule = (ModuleResourceIntake)module;

                if (intakeModule.resourceName == "IntakeAir")
                {
                    airFlowCurrent += intakeModule.airFlow;
                }
            }

            if (propellantList != null)
            {
                Propellant propellant;
                for (int propIdx = 0; propIdx < propellantList.Count; propIdx++)
                {
                    propellant = propellantList[propIdx];

                    if (propellant.name == "IntakeAir")
                    {
                        airFlowRequired += propellant.currentRequirement / TimeWarp.fixedDeltaTime;
                        break;
                    }
                }
            }
        }
Exemplo n.º 32
0
        public override void OnStart(StartState state)
        {
            Debug.Log("[KSPI]: AtmosphericIntake OnStart Reading PluginHelper Upgrades");

            JetUpgradeTech1 = PluginSettings.Config.JetUpgradeTech1;
            JetUpgradeTech2 = PluginSettings.Config.JetUpgradeTech2;
            JetUpgradeTech3 = PluginSettings.Config.JetUpgradeTech3;
            JetUpgradeTech4 = PluginSettings.Config.JetUpgradeTech4;
            JetUpgradeTech5 = PluginSettings.Config.JetUpgradeTech5;

            hasJetUpgradeTech1 = PluginHelper.HasTechRequirementOrEmpty(PluginSettings.Config.JetUpgradeTech1);
            hasJetUpgradeTech2 = PluginHelper.HasTechRequirementOrEmpty(PluginSettings.Config.JetUpgradeTech2);
            hasJetUpgradeTech3 = PluginHelper.HasTechRequirementOrEmpty(PluginSettings.Config.JetUpgradeTech3);
            hasJetUpgradeTech4 = PluginHelper.HasTechRequirementOrEmpty(PluginSettings.Config.JetUpgradeTech4);
            hasJetUpgradeTech5 = PluginHelper.HasTechRequirementOrEmpty(PluginSettings.Config.JetUpgradeTech5);

            var jetTech = Convert.ToInt32(hasJetUpgradeTech1) * 1.2f + 1.44f * Convert.ToInt32(hasJetUpgradeTech2) + 1.728f * Convert.ToInt32(hasJetUpgradeTech3) + 2.0736f * Convert.ToInt32(hasJetUpgradeTech4) + 2.48832f * Convert.ToInt32(hasJetUpgradeTech5);

            jetTechBonus = 5 * (1 + (jetTech / 9.92992f));

            _moduleResourceIntake         = part.FindModulesImplementing <ModuleResourceIntake>().FirstOrDefault(m => m.resourceName == KITResourceSettings.IntakeOxygenAir);
            _resourceAtmosphereDefinition = PartResourceLibrary.Instance.GetDefinition(KITResourceSettings.IntakeAtmosphere);

            if (_moduleResourceIntake == null)
            {
                Debug.LogWarning("[KSPI]: ModuleResourceIntake with IntakeAir is missing on " + part.partInfo.title);
            }

            var field = Fields[nameof(intakeOpen)];

            if (field.uiControlFlight is UI_Toggle flightToggle)
            {
                flightToggle.onFieldChanged = IntakeOpenChanged;
            }
            if (field.uiControlEditor is UI_Toggle editorToggle)
            {
                editorToggle.onFieldChanged = IntakeOpenChanged;
            }

            UpdateResourceIntakeConfiguration();

            // if (state == StartState.Editor) return; // don't do any of this stuff in editor
        }
Exemplo n.º 33
0
        public override void OnStart(PartModule.StartState state)
        {
            if (state == StartState.Editor)
            {
                return;
            }

            foreach (AttachNode attach_node in part.attachNodes)
            {
                if (attach_node.attachedPart != null)
                {
                    List <ModuleResourceIntake> mres = attach_node.attachedPart.FindModulesImplementing <ModuleResourceIntake>().Where(mre => mre.resourceName == "IntakeAir").ToList();
                    if (mres.Count > 0)
                    {
                        attachedIntake = mres.First();
                    }
                }
            }
            part.force_activate();
        }
        public override void OnAwake()
        {
            this.Actions["ActivateAction"].active   = false;
            this.Actions["DeactivateAction"].active = false;

            PartModule module;

            for (int idx = 0; idx < this.part.Modules.Count; idx++)
            {
                module = this.part.Modules[idx];

                if (module is ModuleResourceIntake)
                {
                    this.intakeModule = module as ModuleResourceIntake;

                    this.Actions["ActivateAction"].active   = true;
                    this.Actions["DeactivateAction"].active = true;
                }
            }
        }
Exemplo n.º 35
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();
     }
 }
        private void ApplyIntakeDrag(float currentRamDrag, Vector3 vesselVelNorm, float dynPres)
        {
            for (int i = _intakeTransforms.Count - 1; i >= 0; i--)
            {
                ModuleResourceIntake intake = _intakeModules[i];
                if (!intake.intakeEnabled)
                {
                    continue;
                }

                Transform transform = _intakeTransforms[i];
                if (transform == null)
                {
                    _intakeModules.RemoveAt(i);
                    _intakeTransforms.RemoveAt(i);
                    _aeroModulesWithIntakes.RemoveAt(i);
                    //++i;
                    continue;
                }

                float cosAoA = Vector3.Dot(_intakeTransforms[i].forward, vesselVelNorm);
                if (cosAoA < 0)
                {
                    cosAoA = 0;
                }

                if (cosAoA <= 0)
                {
                    continue;
                }

                FARAeroPartModule aeroModule = _aeroModulesWithIntakes[i];


                Vector3 force = -aeroModule.partLocalVelNorm * cosAoA * currentRamDrag * (float)intake.area * 100f;
                //if(float.IsNaN(force.sqrMagnitude))
                //    force = Vector3.zero;
                aeroModule.AddLocalForce(force, Vector3.zero);
            }
        }
Exemplo n.º 37
0
        public void SetupIntake()
        {
            ModuleResourceIntake intake = this.part.FindModuleImplementing <ModuleResourceIntake>();

            if (intake == null)
            {
                return;
            }
            PartResourceDefinitionList definitions = PartResourceLibrary.Instance.resourceDefinitions;
            PartResourceDefinition     resourceDef = null;
            PartResource resource       = null;
            string       resourceName   = "";
            bool         checkForOxygen = false;

            if (multiModeEngine.runningPrimary)
            {
                resourceName   = primaryEngineIntake;
                resourceDef    = ResourceHelper.DefinitionForResource(resourceName);
                resource       = this.part.Resources[resourceDef.name];
                checkForOxygen = primaryCheckForOxygen;
            }

            else
            {
                resourceName   = secondaryEngineIntake;
                resourceDef    = ResourceHelper.DefinitionForResource(resourceName);
                resource       = this.part.Resources[resourceDef.name];
                checkForOxygen = secondaryCheckForOxygen;
            }

            //Change the resource to intake
            intake.resourceName   = resourceName;
            intake.resourceDef    = resourceDef;
            intake.resourceId     = resourceDef.id;
            intake.res            = resource;
            intake.checkForOxygen = checkForOxygen;
        }
    protected override bool SetupModule()
    {
        if(!base.SetupModule())
            return false;

        foreach (PartModule current in part.Modules)
        {
            if (current.GetType().UnderlyingSystemType != typeof(ModuleResourceIntake))
                continue;

            _Intake = current as ModuleResourceIntake;
            _AirFlow = _Intake.GetType().GetField("airFlow");
            _IntakeOpen = _Intake.GetType().GetField("intakeEnabled");
            break;
        }

        return _Intake != null
            && _AirFlow != null
            && _IntakeOpen != null;
    }
Exemplo n.º 39
0
 public override void OnStart(PartModule.StartState state)
 {
     base.OnStart(state);
     intake = base.part.FindModuleImplementing<ModuleResourceIntake>();
 }
Exemplo n.º 40
0
            // Return the number of kg of resource provided per second under certain conditions.
            // We use kg since the numbers are typically small.
            private double massProvided(double vesselSpeed, Vector3d vesselFwd, double atmDensity,
                ModuleResourceIntake intake, Vector3d intakeFwd)
            {
                if (intake.checkForOxygen && !FlightGlobals.currentMainBody.atmosphereContainsOxygen)
                {
                    return 0;
                }

                // This is adapted from code shared by Amram at:
                // http://forum.kerbalspaceprogram.com/showthread.php?34288-Maching-Bird-Challeng?p=440505
                // Seems to be accurate for 0.18.2 anyway.
                double intakeSpeed = intake.maxIntakeSpeed; // airspeed when the intake isn't moving

                double aoa = Vector3d.Dot(vesselFwd, intakeFwd);
                if (aoa < 0) { aoa = 0; }
                else if (aoa > 1) { aoa = 1; }

                double finalSpeed;
                if (aoa <= intake.aoaThreshold)
                {
                    finalSpeed = intakeSpeed;
                }
                else
                {
                    // This is labeled as a bug for double-counting intakeSpeed.
                    // It also double-counts unitScalar...
                    double airSpeedGUI = vesselSpeed + intakeSpeed;
                    double airSpeed = airSpeedGUI * intake.unitScalar;
                    finalSpeed = aoa * (airSpeed + intakeSpeed);
                }
                double airVolume = finalSpeed * intake.area * intake.unitScalar;
                double airmass = atmDensity * airVolume; // tonnes per second

                // TODO: limit by the amount the intake can store
                return airmass * 1000;
            }
Exemplo n.º 41
0
 public void addIntake(ModuleResourceIntake intake)
 {
     // TODO: figure out how much airflow we have, how much we could have,
     // drag, etc etc.
     List<ModuleResourceIntake> thelist;
     int id = PartResourceLibrary.Instance.GetDefinition(intake.resourceName).id;
     if (allIntakes.ContainsKey(id))
     {
         thelist = allIntakes[id];
     }
     else
     {
         thelist = new List<ModuleResourceIntake>();
         allIntakes[id] = thelist;
     }
     thelist.Add(intake);
 }
Exemplo n.º 42
0
 protected override void DI_Start(StartState state)
 {
     intake = this.part.Modules.OfType<ModuleResourceIntake>().Single();
 }
Exemplo n.º 43
0
 public override void OnStart(PartModule.StartState state)
 {
     base.OnStart(state);
     intakeMeshTransform = part.FindModelTransform(intakeMeshName);
     intakeModule = part.Modules.OfType<ModuleResourceIntake>().FirstOrDefault();
 }
        public IntegratedIntakeEngineCrossSectionAdjuster(ModuleResourceIntake intake, Matrix4x4 worldToVesselMatrix)
        {
            this.part = intake.part;
            //ModuleResourceIntake intake = intake;

            intakeTrans = part.FindModelTransform(intake.intakeTransformName);
            vehicleBasisForwardVector = Vector3.forward;//intakeTrans.forward;

            foreach (AttachNode node in part.attachNodes)
                if (node.nodeType == AttachNode.NodeType.Stack && Vector3.Dot(node.position, (part.transform.worldToLocalMatrix * intakeTrans.localToWorldMatrix).MultiplyVector(Vector3.forward)) > 0)
                {
                    frontNode = node;
                    break;
                }

            thisToVesselMatrix = worldToVesselMatrix * intakeTrans.localToWorldMatrix;

            vehicleBasisForwardVector = thisToVesselMatrix.MultiplyVector(vehicleBasisForwardVector);

            intakeArea = INTAKE_AREA_SCALAR * intake.area;
        }
Exemplo n.º 45
0
        public override void OnStart(PartModule.StartState state) {
            if (state == StartState.Editor) { return; }

            foreach (AttachNode attach_node in part.attachNodes) {
                if (attach_node.attachedPart != null) {
                    List<ModuleResourceIntake> mres = attach_node.attachedPart.FindModulesImplementing<ModuleResourceIntake>().Where(mre => mre.resourceName == "IntakeAir").ToList();
                    if(mres.Count > 0) {
                        attachedIntake = mres.First();
                        break;                          //added by attosecond 3/10/14 -- no need to keep the loop going if we found what we wanted
                    }
                }
            }
            
            /*Added by attosecond 3/10/14. Code checks if this is an "all-in-one" intake + precooler part, also checks
             * parts attached to children and parent parts for intakes, on the assumption that the child/parent parts can
             * transfer the intake air to the precooler */

            //first check if this is an all-in-one part
            if (attachedIntake == null)
            {
                List<ModuleResourceIntake> mres = part.FindModulesImplementing<ModuleResourceIntake>().Where(mre => mre.resourceName == "IntakeAir").ToList();
                if (mres.Count > 0)
                    attachedIntake = mres.First();
            }

            //now check all parts attached to the parent part
            if (attachedIntake == null)
            {
                foreach (AttachNode attach_node in part.parent.attachNodes)
                {
                    if (attach_node.attachedPart != null && attach_node.attachedPart != part)
                    {
                        List<ModuleResourceIntake> mres = attach_node.attachedPart.FindModulesImplementing<ModuleResourceIntake>().Where(mre => mre.resourceName == "IntakeAir").ToList();
                        if (mres.Count > 0)
                        {
                            attachedIntake = mres.First();
                            break;
                        }
                    }
                }
            }

            //and do the same for child parts
            if (attachedIntake == null)
            {
                foreach (Part childpart in part.children)
                {
                    foreach (AttachNode attach_node in childpart.attachNodes)
                    {
                        if (attach_node.attachedPart != null && attach_node.attachedPart != part)
                        {
                            List<ModuleResourceIntake> mres = attach_node.attachedPart.FindModulesImplementing<ModuleResourceIntake>().Where(mre => mre.resourceName == "IntakeAir").ToList();
                            if (mres.Count > 0)
                            {
                                attachedIntake = mres.First();
                                break;
                            }
                        }
                    }
                }
            }

            /* 
             * End edits by attosecond
            */
            
            part.force_activate();
        }
Exemplo n.º 46
0
        public override void OnStart(PartModule.StartState state) 
        {
            if (state == StartState.Editor) return;

            UnityEngine.Debug.Log("[KSPI] - FNModulePreecooler - Onstart start search for Air Intake module to cool");

            // first check if part itself has an air intake
            attachedIntake = part.FindModulesImplementing<ModuleResourceIntake>().FirstOrDefault(mre => mre.resourceName == "IntakeAir");

            if (attachedIntake != null)
                UnityEngine.Debug.Log("[KSPI] - FNModulePreecooler - Found Airintake on self");

            if (attachedIntake == null)
            {
                // then look to connect radial attached children
                radialAttachedIntakes = part.children
                    .Where(p => p.attachMode == AttachModes.SRF_ATTACH)
                    .SelectMany(p => p.FindModulesImplementing<ModuleResourceIntake>()).Where(mre => mre.resourceName == "IntakeAir").ToList();

                if (radialAttachedIntakes.Count > 0)
                    UnityEngine.Debug.Log("[KSPI] - FNModulePreecooler - Found Airintake in children");
            }

            // third look for stack attachable air intake
            if (attachedIntake == null && (radialAttachedIntakes == null || radialAttachedIntakes.Count == 0))
            {
                UnityEngine.Debug.Log("[KSPI] - FNModulePreecooler - looking at attached nodes");

                foreach (AttachNode attach_node in part.attachNodes.Where(a => a.attachedPart != null))
                {
                    var attachedPart = attach_node.attachedPart;

                    // skip any parts that contain a precooler
                    if (attachedPart.FindModulesImplementing<FNModulePreecooler>().Any())
                    {
                        UnityEngine.Debug.Log("[KSPI] - FNModulePreecooler - skipping Module Implementing FNModulePreecooler");
                        continue;
                    }

                    attachedIntake = attachedPart.FindModulesImplementing<ModuleResourceIntake>().FirstOrDefault(mre => mre.resourceName == "IntakeAir");

                    if (attachedIntake != null)
                    {
                        UnityEngine.Debug.Log("[KSPI] - FNModulePreecooler - found Airintake in attached part with name " + attachedIntake.name);
                        break;
                    }
                }

                if (attachedIntake == null)
                {
                    UnityEngine.Debug.Log("[KSPI] - FNModulePreecooler - looking at deeper attached nodes");

                    // look for stack attacked parts one part further
                    foreach (AttachNode attach_node in part.attachNodes.Where(a => a.attachedPart != null))
                    {
                        if (attach_node.attachedPart.FindModulesImplementing<FNModulePreecooler>().Any()) continue;
                        
                        foreach (AttachNode subAttach_node in attach_node.attachedPart.attachNodes.Where(a => a.attachedPart != null))
                        {
                            attachedIntake = subAttach_node.attachedPart.FindModulesImplementing<ModuleResourceIntake>().FirstOrDefault(mre => mre.resourceName == "IntakeAir");

                            if (attachedIntake != null)
                            {
                                UnityEngine.Debug.Log("[KSPI] - FNModulePreecooler - found Airintake in deeper attached part with name " + attachedIntake.name);
                                break;
                            }
                        }
                        if (attachedIntake != null) break;
                    }
                }
            }

            part.force_activate();

            if (attachedIntake != null)
                attachedIntakeName = attachedIntake.name;
            else
            {
                if (radialAttachedIntakes == null )
                    attachedIntakeName = "Null found";
                else if (radialAttachedIntakes.Count > 1)
                    attachedIntakeName = "Multiple intakes found";
                else if (radialAttachedIntakes.Count > 0)
                    attachedIntakeName = radialAttachedIntakes.First().name;
                else
                    attachedIntakeName = "Not found";
            }
        }