private void LateUpdate()
        {
            if (window == null)
            {
                return;
            }

            if (!SEP_Utilities.UIWindowReflectionLoaded)
            {
                return;
            }

            if (FlightGlobals.ActiveVessel == vessel)
            {
                return;
            }

            int l = Fields.Count;

            for (int i = 0; i < l; i++)
            {
                BaseField b = Fields[i];

                if (!b.guiActive)
                {
                    continue;
                }

                try
                {
                    window.GetType().InvokeMember("AddFieldControl", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreReturn | BindingFlags.InvokeMethod, null, window, new object[] { b, part, this });
                }
                catch (Exception e)
                {
                    SEP_Utilities.log("Error in adding KSP Field to unfocused UI Part Action Window\n{0}", logLevels.error, e);
                    continue;
                }

                try
                {
                    var items = SEP_Utilities.UIActionListField(window).GetValue(window) as List <UIPartActionItem>;

                    int c = items.Count;

                    for (int j = 0; j < c; j++)
                    {
                        UIPartActionItem item = items[j];

                        if (item is UIPartActionLabel)
                        {
                            item.UpdateItem();
                        }
                    }
                }
                catch (Exception e)
                {
                    SEP_Utilities.log("Error in setting KSP Field on unfocused UI Part Action Window\n{0}", logLevels.error, e);
                }
            }
        }
        public void addConnectecExperiment(ModuleSEPScienceExperiment mod)
        {
            if (experiments.Count >= maxExperiments)
            {
                SEP_Utilities.log("SEP Control Station module at capacity...", logLevels.log);
                return;
            }

            if (mod == null)
            {
                return;
            }

            if (!mod.IsDeployed)
            {
                return;
            }

            if (mod.Handler == null)
            {
                return;
            }

            experiments.Add(mod);
            setControllerFields();
            setCollectEvent();
        }
Пример #3
0
        public void SettingsApplied()
        {
            if (HighLogic.CurrentGame != null)
            {
                settings = HighLogic.CurrentGame.Parameters.CustomParams <SEP_GameParameters>();
            }

            if (settings == null)
            {
                return;
            }

            if (settings.useAsDefault)
            {
                showAllVessels = settings.showAllVessels;
                fadeout        = settings.fadeOut;
                stockToolbar   = settings.stockToolbar;
                hoverOpen      = settings.hoverOpen;
                scale          = settings.scale;

                if (Save())
                {
                    SEP_Utilities.log("[SEP Science] Settings file saved", logLevels.log);
                }
            }
        }
        public void gatherScience(bool silent = false)
        {
            int level = handler.getMaxLevel(instantResults);

            if (level <= 0)
            {
                return;
            }

            ScienceData data = SEP_Utilities.getScienceData(handler, handler.getExperimentLevel(instantResults), level);

            if (data == null)
            {
                SEP_Utilities.log("Null Science Data returned; something went wrong here...", logLevels.warning);
                return;
            }

            GameEvents.OnExperimentDeployed.Fire(data);

            if (handler == null)
            {
                return;
            }

            handler.GetData().Add(data);

            if (silent)
            {
                transferToEVA();
            }
            else
            {
                ReviewData();
            }
        }
        private void Awake()
        {
            if (instance != null)
            {
                Destroy(gameObject);
            }

            DontDestroyOnLoad(gameObject);

            instance = this;

            fullPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), fileName).Replace("\\", "/");
            GameEvents.OnGameSettingsApplied.Add(SettingsApplied);

            if (Load())
            {
                SEP_Utilities.log("Settings file loaded", logLevels.log);
            }
            else
            {
                if (Save())
                {
                    SEP_Utilities.log("New Settings file generated at:\n{0}", logLevels.log, fullPath);
                }
            }
        }
Пример #6
0
        private void watcher(float sci, ScienceSubject sub, ProtoVessel v, bool b)
        {
            if (sub == null)
            {
                return;
            }

            if (!sub.id.StartsWith("SEP"))
            {
                return;
            }

            GameScenes scene = HighLogic.LoadedScene;

            List <ScienceSubject> subjects = ResearchAndDevelopment.GetSubjects();

            if (scene == GameScenes.SPACECENTER || scene == GameScenes.TRACKSTATION)
            {
                //SEPUtilities.log("Recovery detected...\nSubject ID - {0}\nScience Recovered - {1:N2}", logLevels.warning, sub.id, sci);

                SEP_Utilities.checkAndUpdateRelatedSubjects(subjects, sub, sci);
            }
            else if (scene == GameScenes.FLIGHT)
            {
                //SEPUtilities.log("Transmission detected...\nSubject ID - {0}\nScience Recovered - {1:N2}", logLevels.warning, sub.id, sci);

                SEP_Utilities.checkAndUpdateRelatedSubjects(subjects, sub, sci);
            }
        }
Пример #7
0
        public bool Load()
        {
            bool b = false;

            try
            {
                if (File.Exists(fullPath))
                {
                    ConfigNode node      = ConfigNode.Load(fullPath);
                    ConfigNode unwrapped = node.GetNode(GetType().Name);
                    ConfigNode.LoadObjectFromConfig(this, unwrapped);
                    b = true;
                }
                else
                {
                    SEP_Utilities.log("[SEP Science] Settings file could not be found [{0}]", logLevels.warning, fullPath);
                    b = false;
                }
            }
            catch (Exception e)
            {
                SEP_Utilities.log("[SEP Science] Error while loading settings file from [{0}]\n{1}", logLevels.error, fullPath, e);
                b = false;
            }

            return(b);
        }
Пример #8
0
        private void onTransmitData(ScienceData data)
        {
            results = null;

            if (handler == null)
            {
                return;
            }

            IScienceDataTransmitter bestTransmitter = ScienceUtil.GetBestTransmitter(vessel);

            if (bestTransmitter != null)
            {
                SEP_Utilities.log("Sending data to vessel comms: {0}", logLevels.log, data.title);
                bestTransmitter.TransmitData(new List <ScienceData> {
                    data
                });
                DumpData(data);
            }
            else if (CommNet.CommNetScenario.CommNetEnabled)
            {
                ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_237738"), 3f, ScreenMessageStyle.UPPER_CENTER);
            }
            else
            {
                ScreenMessages.PostScreenMessage(Localizer.Format("#autoLOC_237740"), 3f, ScreenMessageStyle.UPPER_CENTER);
            }
        }
        private void onTransmitData(ScienceData data)
        {
            results = null;

            if (handler == null)
            {
                return;
            }

            IScienceDataTransmitter bestTransmitter = ScienceUtil.GetBestTransmitter(vessel);

            if (bestTransmitter != null)
            {
                SEP_Utilities.log("Sending data to vessel comms: {0}", logLevels.log, data.title);
                bestTransmitter.TransmitData(new List <ScienceData> {
                    data
                });
                DumpData(data);
            }
            else if (CommNet.CommNetScenario.CommNetEnabled)
            {
                ScreenMessages.PostScreenMessage("No usable, in-range Comms Devices on this vessel. Cannot Transmit Data.", 3f, ScreenMessageStyle.UPPER_CENTER);
            }
            else
            {
                ScreenMessages.PostScreenMessage("No Comms Devices on this vessel. Cannot Transmit Data.", 3f, ScreenMessageStyle.UPPER_CENTER);
            }
        }
        private IEnumerator loadSprites()
        {
            while (TelemetryUpdate.Instance == null)
            {
                yield return(null);
            }

            SEP_Utilities.loadSprites(TelemetryUpdate.Instance.SS0, TelemetryUpdate.Instance.SS1, TelemetryUpdate.Instance.SS2, TelemetryUpdate.Instance.SS3, TelemetryUpdate.Instance.SS4);
        }
Пример #11
0
        public float getSubmittedData()
        {
            ScienceSubject sub = SEP_Utilities.subjectIsValid(this);

            if (sub == null)
            {
                return(0);
            }

            return(sub.science / sub.subjectValue);
        }
        private void Start()
        {
            if (HighLogic.LoadedSceneIsEditor)
            {
                running = false;
                Destroy(gameObject);
            }

            if (!SEP_Utilities.partModulesLoaded)
            {
                SEP_Utilities.loadPartModules();
            }

            if (!SEP_Utilities.antennaModulesLoaded)
            {
                SEP_Utilities.loadAntennaParts();
            }

            if (!SEP_Utilities.spritesLoaded)
            {
                StartCoroutine(loadSprites());
            }

            if (ResearchAndDevelopment.GetTechnologyState(transmissionNode) == RDTech.State.Available)
            {
                transmissionUpgrade = true;
            }
            else
            {
                transmissionUpgrade = false;
            }

            if (running)
            {
                Destroy(gameObject);
            }

            if (HighLogic.LoadedSceneIsFlight)
            {
                StartCoroutine(attachWindowListener());
            }

            instance = this;

            running = true;

            usingCommNet = HighLogic.CurrentGame.Parameters.Difficulty.EnableCommNet;

            GameEvents.onLevelWasLoaded.Add(onReady);
            GameEvents.OnGameSettingsApplied.Add(onSettingsApplied);
        }
        private IEnumerator attachWindowListener()
        {
            while (UIPartActionController.Instance == null)
            {
                yield return(null);
            }

            while (UIPartActionController.Instance.windowPrefab == null)
            {
                yield return(null);
            }

            SEP_Utilities.attachWindowPrefab();
        }
Пример #14
0
        private ConfigNode AsConfigNode()
        {
            try
            {
                ConfigNode node = new ConfigNode(GetType().Name);

                node = ConfigNode.CreateConfigFromObject(this, node);
                return(node);
            }
            catch (Exception e)
            {
                SEP_Utilities.log("[SEP Science] Failed to generate settings file node...\n{0}", logLevels.error, e);
                return(new ConfigNode(GetType().Name));
            }
        }
        private void Start()
        {
            GameScenes scene = HighLogic.LoadedScene;

            if (scene == GameScenes.MAINMENU)
            {
                if (!SEP_Utilities.partModulesLoaded)
                {
                    SEP_Utilities.loadPartModules();
                }

                if (!SEP_Utilities.UIWindowReflectionLoaded)
                {
                    SEP_Utilities.assignReflectionMethod();
                }
            }

            if (!(scene == GameScenes.FLIGHT || scene == GameScenes.TRACKSTATION || scene == GameScenes.SPACECENTER))
            {
                running = false;
                Destroy(gameObject);
            }

            if (ResearchAndDevelopment.GetTechnologyState(transmissionNode) == RDTech.State.Available)
            {
                transmissionUpgrade = true;
            }
            else
            {
                transmissionUpgrade = false;
            }

            if (running)
            {
                Destroy(gameObject);
            }

            if (scene == GameScenes.FLIGHT)
            {
                StartCoroutine(attachWindowListener());
            }

            instance = this;

            running = true;

            GameEvents.onLevelWasLoaded.Add(onReady);
        }
Пример #16
0
        public bool Save()
        {
            bool b = false;

            try
            {
                ConfigNode node    = AsConfigNode();
                ConfigNode wrapper = new ConfigNode(GetType().Name);
                wrapper.AddNode(node);
                wrapper.Save(fullPath);
                b = true;
            }
            catch (Exception e)
            {
                SEP_Utilities.log("[SEP Science] Error while saving settings file from [{0}]\n{1}", logLevels.error, fullPath, e);
                b = false;
            }

            return(b);
        }
        public override void OnStart(PartModule.StartState state)
        {
            base.OnStart(state);

            usingEC = resHandler.inputResources.Count > 0;

            flightID = (int)part.flightID;

            if (complexity > 4)
            {
                complexity = 4;
            }
            else if (complexity < 1)
            {
                complexity = 1;
            }

            if (state == StartState.Editor)
            {
                return;
            }

            if (animated && !string.IsNullOrEmpty(animationName))
            {
                anim = part.FindModelAnimators(animationName)[0];
            }

            if (IsDeployed && animated)
            {
                animator(anim, animationName, 1, 1);
            }

            setupEvents();

            requiredPartList   = SEP_Utilities.parsePartStringList(requiredParts);
            requiredModuleList = SEP_Utilities.parseModuleStringList(requiredModules);

            GameEvents.onVesselSituationChange.Add(sitChange);
            SEP_Utilities.onWindowSpawn.Add(onWindowSpawn);
            SEP_Utilities.onWindowDestroy.Add(onWindowDestroy);
        }
Пример #18
0
        private bool canConduct()
        {
            failMessage = "";

            ExperimentSituations sit = ScienceUtil.GetExperimentSituation(vessel);

            if (handler == null)
            {
                SEP_Utilities.log("SEP Experiment Handler is null; Stopping any experiments...", logLevels.warning);
                failMessage = Localizer.Format("#LOC_SurfaceExperimentPack_ModuleSEPScienceExperiment_failExperimentError");
                return(false);
            }

            if (handler.basicExperiment == null)
            {
                SEP_Utilities.log("SEP Experiment definition is null; stopping experiment\npossible errors or corruption present in the SEP ScienceDefs file", logLevels.warning);
                failMessage = Localizer.Format("#LOC_SurfaceExperimentPack_ModuleSEPScienceExperiment_failExperimentError");
                return(false);
            }
            if (Inoperable)
            {
                failMessage = Localizer.Format("#LOC_SurfaceExperimentPack_ModuleSEPScienceExperiment_failFunctional");
                return(false);
            }
            else if (handler.basicExperiment.requireAtmosphere && !vessel.mainBody.atmosphere)
            {
                failMessage = includeAtmosphereMessage;
                return(false);
            }
            else if (!handler.basicExperiment.IsAvailableWhile(sit, vessel.mainBody))
            {
                if (!string.IsNullOrEmpty(situationFailMessage))
                {
                    failMessage = situationFailMessage;
                }
                return(false);
            }
            else if (excludeAtmosphere && vessel.mainBody.atmosphere)
            {
                if (!string.IsNullOrEmpty(excludeAtmosphereMessage))
                {
                    failMessage = excludeAtmosphereMessage;
                }
                return(false);
            }
            else if (!string.IsNullOrEmpty(controllerModule))
            {
                if (!VesselUtilities.VesselHasModuleName(controllerModule, vessel))
                {
                    failMessage = controllerModuleMessage;
                    return(false);
                }
            }

            if (requiredPartList.Count > 0)
            {
                for (int i = 0; i < requiredPartList.Count; i++)
                {
                    string partName = requiredPartList[i];

                    if (string.IsNullOrEmpty(partName))
                    {
                        continue;
                    }

                    if (!VesselUtilities.VesselHasPartName(partName, vessel))
                    {
                        failMessage = requiredPartsMessage;
                        return(false);
                    }
                }
            }

            if (requiredModuleList.Count > 0)
            {
                for (int i = 0; i < requiredModuleList.Count; i++)
                {
                    string moduleName = requiredModuleList[i];

                    if (string.IsNullOrEmpty(moduleName))
                    {
                        continue;
                    }

                    if (!VesselUtilities.VesselHasModuleName(moduleName, vessel))
                    {
                        failMessage = requiredModulesMessage;
                        return(false);
                    }
                }
            }

            return(true);
        }
Пример #19
0
        private void LateUpdate()
        {
            if (window == null)
            {
                return;
            }

            if (UIPartActionController.Instance == null)
            {
                return;
            }

            if (!SEP_Utilities.UIWindowReflectionLoaded)
            {
                return;
            }

            if (FlightGlobals.ActiveVessel == vessel)
            {
                return;
            }

            bool update = false;

            int l = part.Resources.Count;

            for (int i = 0; i < l; i++)
            {
                PartResource r = part.Resources[i];

                try
                {
                    window.GetType().InvokeMember("AddResourceFlightControl", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreReturn | BindingFlags.InvokeMethod, null, window, new object[] { r });
                    update = true;
                }
                catch (Exception e)
                {
                    SEP_Utilities.log("Error in adding EC Field to unfocused SEP UI Part Action Window\n{0}", logLevels.error, e);
                    continue;
                }

                try
                {
                    var items = SEP_Utilities.UIActionListField(window).GetValue(window) as List <UIPartActionItem>;

                    int c = items.Count;

                    for (int j = 0; j < c; j++)
                    {
                        UIPartActionItem item = items[j];

                        if (item is UIPartActionResource)
                        {
                            item.UpdateItem();
                        }
                    }
                }
                catch (Exception e)
                {
                    SEP_Utilities.log("Error in setting KSP Field on unfocused UI Part Action Window\n{0}", logLevels.error, e);
                }
            }

            if (update)
            {
                try
                {
                    window.GetType().InvokeMember("PointerUpdate", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreReturn | BindingFlags.InvokeMethod, null, window, null);
                }
                catch (Exception e)
                {
                    SEP_Utilities.log("Error in updating unfocused UI Part Action Window position\n{0}", logLevels.error, e);
                }
            }
        }
        private bool transmitData(SEP_ExperimentHandler exp, int level, float submittedData, float newData)
        {
            ScienceData data = SEP_Utilities.getScienceData(exp, exp.getExperimentLevel(level), level);

            if (exp.vessel.loaded)
            {
                IScienceDataTransmitter bestTransmitter = ScienceUtil.GetBestTransmitter(exp.vessel);

                if (bestTransmitter != null)
                {
                    ScienceExperiment e = exp.getExperimentLevel(level);

                    float transmitterCost = getLoadedTransmitterCost(bestTransmitter);

                    float ecCost = newData * e.dataScale * transmitterCost;

                    if (ecCost > SEP_Utilities.getTotalVesselEC(exp.vessel))
                    {
                        if (!dataOnboard(exp, level))
                        {
                            SEP_Utilities.log("Not enough power for transmissionon this vessel: {1}; saving data: {0}", logLevels.log, data.title, exp.vessel.vesselName);
                            exp.addData(data);
                            if (exp.host != null)
                            {
                                exp.host.Events["ReviewDataEvent"].active   = true;
                                exp.host.Events["TransferDataEvent"].active = exp.host.hasContainer;
                                exp.host.Events["CollectData"].active       = true;
                                if (exp.host.Controller != null)
                                {
                                    exp.host.Controller.setCollectEvent();
                                }
                            }
                        }
                        return(false);
                    }

                    SEP_Utilities.log("Sending data to vessel comms: {0}", logLevels.log, data.title);
                    bestTransmitter.TransmitData(new List <ScienceData> {
                        data
                    });
                    return(true);
                }
                else
                {
                    if (!dataOnboard(exp, level))
                    {
                        SEP_Utilities.log("No Comms Devices on this vessel: {1}. Cannot Transmit Data; saving data: {0}", logLevels.log, data.title, exp.vessel.vesselName);
                        exp.addData(data);
                        if (exp.host != null)
                        {
                            exp.host.Events["ReviewDataEvent"].active   = true;
                            exp.host.Events["TransferDataEvent"].active = exp.host.hasContainer;
                            exp.host.Events["CollectData"].active       = true;
                            if (exp.host.Controller != null)
                            {
                                exp.host.Controller.setCollectEvent();
                            }
                        }
                    }
                    return(false);
                }
            }
            else
            {
                List <ProtoPartSnapshot> transmitters = getProtoTransmitters(exp.vessel.protoVessel);

                float?transmitterCost = getBestTransmitterCost(transmitters);

                if (transmitterCost == null)
                {
                    if (!dataOnboard(exp, level))
                    {
                        SEP_Utilities.log("No Comms Devices on this vessel: {1}. Cannot Transmit Data; saving data: {0}", logLevels.log, data.title, exp.vessel.protoVessel.vesselName);
                        exp.addData(data);
                    }
                    return(false);
                }

                //SEP_Utilities.log("Transmission Score: {0:N4}EC", logLevels.warning, transmitterCost);

                ScienceExperiment e = exp.getExperimentLevel(level);

                float ecCost = newData * e.dataScale * (float)transmitterCost;

                //SEP_Utilities.log("Transmission Cost: {0:N4}EC", logLevels.warning, ecCost);

                if (ecCost > SEP_Utilities.getTotalVesselEC(exp.vessel.protoVessel))
                {
                    if (!dataOnboard(exp, level))
                    {
                        SEP_Utilities.log("Not enough electricity on this vessel: {1}. Cannot Transmit Data; saving data: {0}", logLevels.log, data.title, exp.vessel.protoVessel.vesselName);
                        exp.addData(data);
                    }
                    return(false);
                }

                ScienceSubject sub = SEP_Utilities.checkAndUpdateRelatedSubjects(exp, level, newData, submittedData);

                if (sub == null)
                {
                    return(false);
                }

                ResearchAndDevelopment.Instance.SubmitScienceData(newData * sub.dataScale, sub, 1, exp.vessel.protoVessel);

                if (exp.vessel.HasValidContractObjectives(new List <string> {
                    "Generator"
                }))
                {
                    consumeResources(exp.vessel.protoVessel, ecCost);
                }

                exp.submittedData += (newData - submittedData);

                return(true);
            }
        }
        private void experimentCheck(double time)
        {
            int l = experiments.Count;

            //if (l > 0)
            //SEP_Utilities.log("Performing SEP background check on {0} experiments at time: {1:N0}", logLevels.log, l , time);

            for (int i = 0; i < l; i++)
            {
                List <SEP_ExperimentHandler> modules = experiments.At(i);

                int c = modules.Count;

                for (int j = 0; j < c; j++)
                {
                    SEP_ExperimentHandler m = modules[j];

                    if (m == null)
                    {
                        continue;
                    }

                    if (!m.loaded)
                    {
                        continue;
                    }

                    if (!m.vessel.Landed)
                    {
                        continue;
                    }

                    if (!m.experimentRunning)
                    {
                        continue;
                    }

                    if (m.usingECResource && !m.vessel.loaded)
                    {
                        if (!m.vessel.HasValidContractObjectives(new List <string> {
                            "Generator"
                        }))
                        {
                            continue;
                        }
                    }

                    if (m.vessel.loaded)
                    {
                        if (m.host != null && m.host.Controller != null)
                        {
                            if (m.host.vessel != m.host.Controller.vessel)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            continue;
                        }
                    }

                    double t = m.experimentTime;

                    float calib = m.calibration;

                    if (usingCommNet)
                    {
                        if (m.vessel.Connection != null)
                        {
                            float signal = (float)m.vessel.Connection.SignalStrength - 0.5f;

                            if (signal < 0)
                            {
                                signal /= 2;
                            }

                            float bonus = calib * signal;

                            calib += bonus;
                        }
                    }

                    t /= calib;

                    double length = time - m.lastBackgroundCheck;

                    m.lastBackgroundCheck = time;

                    double days = length / 21600;

                    if (days < t)
                    {
                        double n = days / t;

                        //SEPUtilities.log("Updating SEP Experiment Handler [{0}]: Add {1:P6}", logLevels.warning, m.experimentTitle, n);

                        m.completion += (float)n;
                    }
                    else
                    {
                        m.completion = 1;
                    }

                    float max = m.getMaxCompletion();

                    if (max <= 0.5f)
                    {
                        if (m.completion >= 0.5f)
                        {
                            m.completion = 0.5f;
                        }
                    }
                    else if (max <= 0.75f)
                    {
                        if (m.completion >= 0.75f)
                        {
                            m.completion = 0.75f;
                        }
                    }
                    else
                    {
                        if (m.completion >= 1f)
                        {
                            m.completion = 1f;
                        }
                    }

                    bool transmitted = false;

                    m.submittedData = m.getSubmittedData();

                    if (m.canTransmit && m.controllerAutoTransmit && transmissionUpgrade)
                    {
                        transmitted = checkTransmission(m);
                    }
                    else
                    {
                        int level = m.getMaxLevel(false);

                        if (!dataOnboard(m, level))
                        {
                            m.addData(SEP_Utilities.getScienceData(m, m.getExperimentLevel(level), level));

                            if (m.vessel.loaded && m.host != null)
                            {
                                m.host.Events["ReviewDataEvent"].active   = true;
                                m.host.Events["TransferDataEvent"].active = m.host.hasContainer;
                                m.host.Events["CollectData"].active       = true;
                                if (m.host.Controller != null)
                                {
                                    m.host.Controller.setCollectEvent();
                                }
                            }
                        }
                    }

                    if (transmitted)
                    {
                        m.clearData();
                    }

                    if (m.completion >= max)
                    {
                        m.experimentRunning = false;
                        if (m.vessel.loaded && m.host != null)
                        {
                            int count = m.GetScienceCount();
                            m.host.Events["ReviewDataEvent"].active   = !transmitted && count > 0;
                            m.host.Events["TransferDataEvent"].active = !transmitted && count > 0 && m.host.hasContainer;
                            m.host.Events["CollectData"].active       = !transmitted && count > 0;
                            m.host.PauseExperiment();
                            if (m.host.Controller != null)
                            {
                                m.host.Controller.setCollectEvent();
                            }
                        }
                    }
                }
            }
        }
        private void populateExperiments()
        {
            experiments = new DictionaryValueList <Vessel, List <SEP_ExperimentHandler> >();

            int l = FlightGlobals.Vessels.Count;

            for (int i = 0; i < l; i++)
            {
                Vessel v = FlightGlobals.Vessels[i];

                if (v == null)
                {
                    continue;
                }

                if (v.vesselType == VesselType.Debris)
                {
                    continue;
                }

                if (experiments.Contains(v))
                {
                    continue;
                }

                List <SEP_ExperimentHandler> handlers = new List <SEP_ExperimentHandler>();

                if (v.loaded)
                {
                    handlers =
                        (from mod in v.FindPartModulesImplementing <ModuleSEPScienceExperiment>()
                         where mod.Handler != null && mod.IsDeployed
                         select mod.Handler).ToList();

                    if (handlers.Count > 0)
                    {
                        SEP_Utilities.log("Processing loaded SEP vessel: {0}\n{1} SEP modules found", logLevels.log, v.vesselName, handlers.Count);
                    }
                }
                else
                {
                    var snaps = v.protoVessel.protoPartSnapshots;

                    int s = snaps.Count;

                    for (int j = 0; j < s; j++)
                    {
                        ProtoPartSnapshot p = snaps[j];

                        if (!p.modules.Any(m => m.moduleName == "ModuleSEPScienceExperiment"))
                        {
                            continue;
                        }

                        var mods = p.modules;

                        int d = mods.Count;

                        for (int k = 0; k < d; k++)
                        {
                            ProtoPartModuleSnapshot mod = mods[k];

                            if (mod.moduleName != "ModuleSEPScienceExperiment")
                            {
                                continue;
                            }

                            if (!mod.moduleValues.HasValue("IsDeployed") || mod.moduleValues.GetValue("IsDeployed") != "True")
                            {
                                continue;
                            }

                            SEP_ExperimentHandler handler = new SEP_ExperimentHandler(mod, v);

                            if (handler.loaded)
                            {
                                handlers.Add(handler);
                            }
                        }
                    }

                    if (handlers.Count > 0)
                    {
                        SEP_Utilities.log("Processing unloaded SEP vessel: {0}\n{1} SEP modules found", logLevels.log, v.vesselName, handlers.Count);
                    }
                }

                if (handlers.Count > 0)
                {
                    if (VesselUtilities.VesselHasModuleName("ModuleSEPStation", v))
                    {
                        experiments.Add(v, handlers);
                    }
                }
            }

            setup = true;
        }
        private void experimentCheck(double time)
        {
            int l = experiments.Count;

            if (l > 0)
            {
                SEP_Utilities.log("Performing SEP background check on {0} experiments at time: {1:N0}", logLevels.log, l, time);
            }

            for (int i = 0; i < l; i++)
            {
                List <SEP_ExperimentHandler> modules = experiments.ElementAt(i).Value;

                int c = modules.Count;

                for (int j = 0; j < c; j++)
                {
                    SEP_ExperimentHandler m = modules[j];

                    if (m == null)
                    {
                        continue;
                    }

                    if (!m.loaded)
                    {
                        continue;
                    }

                    if (!m.experimentRunning)
                    {
                        continue;
                    }

                    if (m.usingECResource && !m.vessel.loaded)
                    {
                        List <string> generators = FinePrint.ContractDefs.GetModules("Power");

                        if (!FinePrint.Utilities.VesselUtilities.VesselHasAnyModules(generators, m.vessel))
                        {
                            continue;
                        }
                    }

                    if (m.vessel.loaded)
                    {
                        if (m.host != null && m.host.Controller != null)
                        {
                            if (m.host.vessel != m.host.Controller.vessel)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            continue;
                        }
                    }

                    double t = m.experimentTime;

                    t /= m.calibration;

                    double length = time - m.lastBackgroundCheck;

                    m.lastBackgroundCheck = time;

                    double days = length / 21600;

                    if (days < t)
                    {
                        double n = days / t;

                        //SEPUtilities.log("Updating SEP Experiment Handler [{0}]: Add {1:P6}", logLevels.warning, m.experimentTitle, n);

                        m.completion += (float)n;
                    }
                    else
                    {
                        m.completion = 1;
                    }

                    float max = m.getMaxCompletion();

                    if (max <= 0.5f)
                    {
                        if (m.completion >= 0.5f)
                        {
                            m.completion = 0.5f;
                        }
                    }
                    else if (max <= 0.75f)
                    {
                        if (m.completion >= 0.75f)
                        {
                            m.completion = 0.75f;
                        }
                    }
                    else
                    {
                        if (m.completion >= 1f)
                        {
                            m.completion = 1f;
                        }
                    }

                    bool transmitted = false;

                    m.submittedData = m.getSubmittedData();

                    if (m.canTransmit && m.controllerAutoTransmit && transmissionUpgrade)
                    {
                        transmitted = checkTransmission(m);
                    }
                    else
                    {
                        int   level   = m.getMaxLevel(false);
                        float science = m.currentMaxScience(level);

                        if (science > m.submittedData)
                        {
                            bool flag = true;
                            if (m.GetScienceCount() > 0)
                            {
                                ScienceData dat = m.GetData()[0];

                                ScienceSubject sub = ResearchAndDevelopment.GetSubjectByID(dat.subjectID);

                                if (sub != null)
                                {
                                    float d = dat.dataAmount / sub.dataScale;

                                    //SEPUtilities.log("Science Data value check: {0:N2} - {1:N2}", logLevels.warning, science, d);

                                    if (science <= d)
                                    {
                                        flag = false;
                                    }
                                }
                                else
                                {
                                    flag = false;
                                }
                            }

                            if (flag)
                            {
                                m.addData(SEP_Utilities.getScienceData(m, m.getExperimentLevel(level), level));

                                if (m.vessel.loaded && m.host != null)
                                {
                                    m.host.Events["ReviewDataEvent"].active = true;
                                    m.host.Events["CollectData"].active     = true;
                                    if (m.host.Controller != null)
                                    {
                                        m.host.Controller.setCollectEvent();
                                    }
                                }
                            }
                        }
                    }

                    if (transmitted)
                    {
                        m.clearData();
                    }

                    if (m.completion >= max)
                    {
                        m.experimentRunning = false;
                        if (m.vessel.loaded && m.host != null)
                        {
                            int count = m.GetScienceCount();
                            m.host.Events["ReviewDataEvent"].active = !transmitted && count > 0;
                            m.host.Events["CollectData"].active     = !transmitted && count > 0;
                            m.host.PauseExperiment();
                            if (m.host.Controller != null)
                            {
                                m.host.Controller.setCollectEvent();
                            }
                        }
                    }
                }
            }
        }
        private bool transmitData(SEP_ExperimentHandler exp, int level, float submittedData, float newData)
        {
            if (exp.vessel.loaded)
            {
                List <IScienceDataTransmitter> tranList = exp.vessel.FindPartModulesImplementing <IScienceDataTransmitter>();
                ScienceData data = SEP_Utilities.getScienceData(exp, exp.getExperimentLevel(level), level);
                if (tranList.Count > 0)
                {
                    SEP_Utilities.log("Sending data to vessel comms. {0} devices to choose from. Will try to pick the best one", logLevels.log, tranList.Count);
                    tranList.OrderBy(ScienceUtil.GetTransmitterScore).First().TransmitData(new List <ScienceData> {
                        data
                    });
                    return(true);
                }
                else
                {
                    exp.addData(data);
                    if (exp.vessel.loaded && exp.host != null)
                    {
                        exp.host.Events["ReviewDataEvent"].active = true;
                        exp.host.Events["CollectData"].active     = true;
                        if (exp.host.Controller != null)
                        {
                            exp.host.Controller.setCollectEvent();
                        }
                    }
                    return(false);
                }
            }
            else
            {
                List <ProtoPartSnapshot> transmitters = getProtoTransmitters(exp.vessel.protoVessel);

                float?transmitterCost = getBestTransmitterCost(transmitters);

                if (transmitterCost == null)
                {
                    exp.addData(SEP_Utilities.getScienceData(exp, exp.getExperimentLevel(level), level));
                    return(false);
                }

                //SEPUtilities.log("Transmission Score: {0:N4}EC", logLevels.warning, transmitterCost);

                ScienceExperiment e = exp.getExperimentLevel(level);

                float ecCost = newData * e.dataScale * (float)transmitterCost;

                //SEPUtilities.log("Transmission Cost: {0:N4}EC", logLevels.warning, ecCost);

                if (ecCost > SEP_Utilities.getTotalVesselEC(exp.vessel.protoVessel))
                {
                    exp.addData(SEP_Utilities.getScienceData(exp, exp.getExperimentLevel(level), level));
                    return(false);
                }

                ScienceSubject sub = SEP_Utilities.checkAndUpdateRelatedSubjects(exp, level, newData, submittedData);

                if (sub == null)
                {
                    return(false);
                }

                ResearchAndDevelopment.Instance.SubmitScienceData(newData * sub.dataScale, sub, 1, exp.vessel.protoVessel);

                List <string> generators = FinePrint.ContractDefs.GetModules("Power");

                if (!FinePrint.Utilities.VesselUtilities.VesselHasAnyModules(generators, exp.vessel))
                {
                    consumeResources(exp.vessel.protoVessel, ecCost);
                }

                exp.submittedData += (newData - submittedData);

                return(true);
            }
        }
        private bool canConduct()
        {
            failMessage = "";

            ExperimentSituations sit = ScienceUtil.GetExperimentSituation(vessel);

            if (handler == null)
            {
                SEP_Utilities.log("SEP Experiment Handler is null; Stopping any experiments...", logLevels.warning);
                failMessage = "Whoops, something went wrong with the SEP Experiment";
                return(false);
            }

            if (Inoperable)
            {
                failMessage = "Experiment is no longer functional";
                return(false);
            }
            else if (!handler.basicExperiment.IsAvailableWhile(sit, vessel.mainBody))
            {
                if (!string.IsNullOrEmpty(situationFailMessage))
                {
                    failMessage = situationFailMessage;
                }
                return(false);
            }
            else if (excludeAtmosphere && vessel.mainBody.atmosphere)
            {
                if (!string.IsNullOrEmpty(excludeAtmosphereMessage))
                {
                    failMessage = excludeAtmosphereMessage;
                }
                return(false);
            }
            else if (handler.basicExperiment.requireAtmosphere && !vessel.mainBody.atmosphere)
            {
                failMessage = includeAtmosphereMessage;
                return(false);
            }
            else if (!string.IsNullOrEmpty(controllerModule))
            {
                if (!VesselUtilities.VesselHasModuleName(controllerModule, vessel))
                {
                    failMessage = controllerModuleMessage;
                    return(false);
                }
            }

            if (requiredPartList.Count > 0)
            {
                for (int i = 0; i < requiredPartList.Count; i++)
                {
                    string partName = requiredPartList[i];

                    if (string.IsNullOrEmpty(partName))
                    {
                        continue;
                    }

                    if (!VesselUtilities.VesselHasPartName(partName, vessel))
                    {
                        failMessage = requiredPartsMessage;
                        return(false);
                    }
                }
            }

            if (requiredModuleList.Count > 0)
            {
                for (int i = 0; i < requiredModuleList.Count; i++)
                {
                    string moduleName = requiredModuleList[i];

                    if (string.IsNullOrEmpty(moduleName))
                    {
                        continue;
                    }

                    if (!VesselUtilities.VesselHasModuleName(moduleName, vessel))
                    {
                        failMessage = requiredModulesMessage;
                        return(false);
                    }
                }
            }

            return(true);
        }