private void evolve(AvailablePart partToEvolve)
        {
            MerillData.log(" Part " + part.name + " want to evolve " + partToEvolve.name);

            //check what to change
            if (part.partInfo.title != null && part.partInfo.title != "")
            {
                MerillData.log(" change title from '" + partToEvolve.title + "' to '" + part.partInfo.title + "'");
                partToEvolve.title = part.partInfo.title;
            }
            if (part.mass > 0)
            {
                MerillData.log(" change mass from '" + partToEvolve.partPrefab.mass + "' to '" + part.mass + "'");
                partToEvolve.partPrefab.mass = part.mass;
            }
            foreach (PartResource ressource in part.Resources)
            {
                if (partToEvolve.partPrefab.Resources.Contains(ressource.resourceName))
                {
                    MerillData.log(" change resource from '" +
                                   partToEvolve.partPrefab.Resources[ressource.resourceName].amount + "' to '" +
                                   ressource.amount + "'");
                    partToEvolve.partPrefab.Resources[ressource.resourceName].amount    = ressource.amount;
                    partToEvolve.partPrefab.Resources[ressource.resourceName].maxAmount = ressource.maxAmount;
                }
            }
        }
        private void testShutdown()
        {
            MerillData.log(" enginetest " + part.name + " shutdown at " +
                           part.vessel.launchTime + "-" + timeIgnitedLaunch + " => "
                           + burnTime() + " != " + part.vessel.missionTime + " into " + "atmo");
            runningLastUpdate = false;
            wait4secRestart   = false;
            if (isLogingTest)
            {
                //log max burn time & test engine for the little duration
                testEngineDuration();
            }
            //? possible?
            else if (burnTime() > maxNBSecBurnAtmo)
            {
                // in testing mode?
                if (useInstrumentation())
                {
                    //we can test this engine to the last bit of possible.
                    updateSafeBurnTime();

                    //ScreenMessages.PostScreenMessage("Part " + part.partInfo.title.ToString()
                    //+ " is  successfully tested in "
                    //+ (atmo ? "atmosphere" : "vaccum") + " for a duration of "
                    //+ ((uint)(burnTime())) + " sec."
                    //, 10f, ScreenMessageStyle.UPPER_CENTER);

                    drawMsgToUser(string.Format(MerillData.str_enginetest_duration_successOK,
                                                part.partInfo.title.ToString(),
                                                "",
                                                (uint)(burnTime())));
                }
            }
            isLogingTest = false;
        }
示例#3
0
 //TODO: test using onawake
 public void Start()
 {
     if (!alreadyStarted || instance == null)
     {
         alreadyStarted = true;
         //print("[MERILL] DATA starting!!! because " + alreadyStarted + " , " + instance);
         DontDestroyOnLoad(this);
         GameEvents.Contract.onContractsLoaded.Add(new EventVoid.OnEvent(removeBoringBTSMContract));
         //set low alt of mun at higher alt to allow farside crater in a fly-by
         foreach (CelestialBody body in FlightGlobals.Bodies)
         {
             if (body.name == "Mun")
             {
                 body.scienceValues.spaceAltitudeThreshold = 90000;
             }
         }
         instance = this;
     }
     else
     {
         //print("[MERILL] DATA starting DESTROY? " + this + " ? " + instance + " =?= "
         //	+ System.Object.ReferenceEquals(this, instance));
         //Destroy(this);
     }
 }
 public override void OnStart(StartState state)
 {
     isRunning = isEngineRunning();
     MerillData.log("enginestart: is started? " + isRunning);
     if (part.Modules.OfType <ModuleEngines>().ToList().Capacity > 0)
     {
         engine        = part.Modules.OfType <ModuleEngines>().ToList()[0];
         realMaxThrust = engine.maxThrust;
         realMinThrust = engine.minThrust;
     }
     if (part.Modules.OfType <ModuleEnginesFX>().ToList().Capacity > 0)
     {
         engineFX      = part.Modules.OfType <ModuleEnginesFX>().ToList()[0];
         realMaxThrust = engine.maxThrust;
         realMinThrust = engineFX.minThrust;
     }
     // if at "load", the engine is activated but at 0 thrust, be sure to set the engine to really 0 thrust
     if (isEngineShutdown())
     {
         isRunning = false;
         if (engine == null)
         {
             engineFX.minThrust = 0;
         }
         else
         {
             engine.minThrust = 0;
         }
     }
 }
示例#5
0
 private void reEnable()
 {
     //re-enable
     if (partModuleToEnable.moduleName.Equals("MerillModuleScienceFail"))
     {
         if (((MerillModuleScienceFail)partModuleToEnable).isInactive)
         {
             ((MerillModuleScienceFail)partModuleToEnable).isInactive = false;
             BaseField merillShowState = partModuleToEnable.Fields["stateDisplay"];
             //TODO verify electricity
             merillShowState.SetValue("Working", merillShowState.host);
         }
     }
     MerillData.log("MerillScienceSlotModule : eventToEnable '" + eventToEnable + "', '" + actionToEnable + "'");
     if (eventToEnable != null)
     {
         eventToEnable.guiActive       = true;
         eventToEnable.guiActiveEditor = true;
         MerillData.log("MerillScienceSlotModule : reenable '" + eventToEnable + "'");
     }
     if (actionToEnable != null)
     {
         actionToEnable.active = true;
         MerillData.log("MerillScienceSlotModule : reenable '" + actionToEnable + "'");
     }
 }
示例#6
0
 private void checkSlot()
 {
     MerillData.log("MerillScienceSlotModule : checkSlot (hasASlot,slotResearched) (" + hasASlot + ", " + slotResearched + ")");
     if (!hasASlot && !slotResearched)
     {
         //find our attach-object
         if (part.parent != null)
         {
             MerillData.log("MerillScienceSlotModule : parent is " + part.parent.name);
             float nbRessource = part.parent.RequestResource("ScienceSlot", 1);
             MerillData.log("MerillScienceSlotModule : nbRessource is " + nbRessource);
             if (nbRessource == 1)
             {
                 hasASlot = true;
                 //add gui & action
                 reEnable();
             }
             slotResearched = true;
         }
     }
     else if (hasASlot && !slotResearched)
     {
         reEnable();
         slotResearched = true;
     }
 }
示例#7
0
 private void MerillEventDeployScienceEva()
 {
     MerillData.log("MerillEvaOnlyModule! MerillEventDeployScienceEva");
     if (btsmScienceEvent != null)
     {
         btsmScienceEvent.Invoke();
     }
 }
 private void OnContractFailCallback(Contract contract)
 {
     MerillData.log("ParameterSuccessContract FailCallback '" + contract.Title.ToLower() + "' ? '" + contractTitle + "'");
     if (contract.Title.ToLower().Equals(contractTitle.ToLower()))
     {
         SetFailed();
     }
 }
 public override void loadDataFromScenario(MerillData scenario)
 {
     alreadyCrashedPreviousShipAtmo = scenario.partNameCrashed.Contains(part.name + "Atmo");
     alreadyTestedPreviousShipAtmo  = scenario.partNameTested.Contains(part.name + "Atmo");
     alreadyCrashedPreviousShipVac  = scenario.partNameCrashed.Contains(part.name + "Vac");
     alreadyTestedPreviousShipVac   = scenario.partNameTested.Contains(part.name + "Vac");
     updateDisplay();
 }
示例#10
0
        public override void OnStart(StartState state)
        {
            // FindObjectOfType the BTSM science module
            MerillData.log("MerillEvaOnlyModule! start, search in " + part.Modules.Count + " modules");
            foreach (PartModule pm in part.Modules)
            {
                //MerillData.log("MerillEvaOnlyModule! start, find module " + pm.moduleName);
                //foreach (BaseEvent evt in pm.Events)
                //{
                //	MerillData.log("MerillEvaOnlyModule! ----- has event " + evt.guiName + ", " + evt + " act:" + evt.active);
                //	MerillData.log("MerillEvaOnlyModule! ----- --------- "
                //		+ "extoEVAOnly=" + evt.externalToEVAOnly+", cat: "+evt.category+", actEdit"+evt.guiActiveEditor
                //		+ ", ActUnfoc" + evt.guiActiveUnfocused+", assigned"+evt.assigned);
                //}

                // disable "deploy" on eva
                if (pm.moduleName.Equals("ModuleAnimateGeneric"))
                {
                    BaseEvent Toggle = pm.Events["Toggle"];
                    //MerillData.log("MerillEvaOnlyModule! ---- find Toggle " + Toggle);
                    if (Toggle != null)
                    {
                        Toggle.active            = false;
                        Toggle.externalToEVAOnly = false;
                        Toggle.guiActiveEditor   = false;
                    }
                    BaseEvent evt = Toggle;
                    //MerillData.log("MerillEvaOnlyModule! ----- has Toggle " + evt.guiName + ", " + evt + " act:" + evt.active);
                    //MerillData.log("MerillEvaOnlyModule! ----- --------- "
                    //	+ "extoEVAOnly=" + evt.externalToEVAOnly+", cat: "+evt.category+", actEdit"+evt.guiActiveEditor
                    //	+ ", ActUnfoc" + evt.guiActiveUnfocused+", assigned"+evt.assigned);
                }
                if (pm.moduleName.Equals("BTSMModuleScienceExperiment"))
                {
                    btsmScienceEvent = pm.Events["BTSMDeployExperiment"];
                    BaseAction btsmScienceAction  = pm.Actions["BTSMDeployExperimentAction"];
                    BaseEvent  merillScienceEvent = Events["MerillEventDeployScienceEva"];

                    MerillData.log("MerillEvaOnlyModule! ---- find btsmScienceEvent " + btsmScienceEvent);
                    MerillData.log("MerillEvaOnlyModule! ---- find btsmScienceAction " + btsmScienceAction);
                    string scienceName = "Deploy";
                    if (btsmScienceEvent != null)
                    {
                        //disable, i take control on event
                        btsmScienceEvent.active = false;
                        scienceName             = btsmScienceEvent.guiName;
                    }
                    if (btsmScienceAction != null)
                    {
                        btsmScienceAction.active = false;
                    }
                    if (merillScienceEvent != null)
                    {
                        merillScienceEvent.guiName = btsmScienceEvent.guiName;
                    }
                }
            }
        }
示例#11
0
        private void shutdownExperiment()
        {
            isRunning = false;

            //update this gui
            Events["shutdownEvent"].guiActive = false;
            energyConsumptionDisplay          = "0 per s";

            //update others ui
            foreach (PartModule pm in part.Modules)
            {
                MerillData.log("consumeEnergy start, find module " + pm.moduleName);

                for (int i = 0; i < pm.Events.Count; i++)
                {
                    if (pm.Events.GetByIndex(i) == null)
                    {
                        MerillData.log("consumeEnergy see Events[" + i + "] is null");
                    }
                    else
                    {
                        MerillData.log("consumeEnergy see event '" + pm.Events.GetByIndex(i).name + "'");
                    }
                }
                for (int i = 0; i < pm.Fields.Count; i++)
                {
                    if (pm.Fields[i] == null)
                    {
                        MerillData.log("consumeEnergy see field[" + i + "] is null");
                    }
                    else
                    {
                        MerillData.log("consumeEnergy see field '" + pm.Fields[i].name + "'");
                    }
                }
                //update my mod, you can add others below
                if (pm.moduleName.Equals("MerillModuleScienceFail"))
                {
                    BaseEvent  merillScienceEvent  = pm.Events["MERILLScienceEventDeployOrTest"];
                    BaseAction merillScienceAction = pm.Actions["MERILLScienceActionDeployOrTest"];
                    if (merillScienceEvent != null && merillScienceAction != null)
                    {
                        merillScienceEvent.guiActive = false;
                        merillScienceEvent.active    = false;
                        MerillData.log("consumeEnergy check field '" + pm.Fields["stateDisplay"] + "'");
                        BaseField merillShowState = pm.Fields["stateDisplay"];
                        merillShowState.SetValue("Dead", merillShowState.host);
                        MerillData.log("consumeEnergy field set '" + merillShowState.GetValue(merillShowState.host) + "'");
                    }
                }
                //update toogle vanilla
                if (pm.moduleName.Equals("ModuleEnviroSensor"))
                {
                    pm.Events["Toggle"].guiActive = false;
                }
            }
        }
        private void wip(Func <string, EventVoid> doWithApart)
        {
            foreach (AvailablePart aPart in PartLoader.Instance.parts)
            {
                if (aPart.partPrefab != null && aPart.partPrefab.Modules != null)
                {
                    foreach (PartModule pm in aPart.partPrefab.Modules)
                    {
                        if (pm.moduleName.Equals("MerillMissionStub"))
                        {
                            if (((MerillMissionStub)pm).missionName.Equals(this.GetType().Name))
                            {
                                if (ResearchAndDevelopment.GetTechnologyState(((MerillMissionStub)pm).techRequired) == RDTech.State.Available)
                                {
                                    MerillData.log(" RD purchased, is experimental? "
                                                   + ResearchAndDevelopment.IsExperimentalPart(
                                                       PartLoader.getPartInfoByName(((MerillMissionStub)pm).partUnlock)));
                                    //check if already experimental
                                    if (ResearchAndDevelopment.IsExperimentalPart(PartLoader.getPartInfoByName(((MerillMissionStub)pm).partUnlock)))
                                    {
                                        doWithApart(((MerillMissionStub)pm).partUnlock);
                                    }
                                }
                                else if (aPart.TechRequired != "specializedControl")
                                {
                                    try
                                    {
                                        //try to remove the stub to a research node
                                        MerillData.log(" RD find a part with r&d node " + pm.name);

                                        RDTech tech = AssetBase.RnDTechTree.FindTech(
                                            ((MerillMissionStub)pm).techRequired);
                                        if (tech != null)
                                        {
                                            MerillData.log(" RD find good tech " + tech.name);
                                            aPart.TechRequired = "specializedControl";
                                            tech.partsAssigned.Remove(aPart);
                                            MerillData.log(" RD find tech assigned ");
                                            if (ResearchAndDevelopment.GetTechnologyState(((MerillMissionStub)pm).techRequired) == RDTech.State.Available)
                                            {
                                                doWithApart(((MerillMissionStub)pm).partUnlock);
                                            }
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        MerillData.log(" RD Exeption:  " + e);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
 public override void OnStart(StartState state)
 {
     GameEvents.OnTechnologyResearched.Add(refreshExperimentalParts);
     if (part != null)
     {
         MerillData.log(" research OnStart " + part.name + " with info: " + part.partInfo);
     }
     else
     {
         MerillData.log(" research OnStart null ");
     }
 }
        private void refreshExperimentalParts(GameEvents.HostTargetAction <RDTech, RDTech.OperationResult> data)
        {
            if (data.host.partsPurchased.Contains(part.partInfo))
            {
                MerillData.log(" research done, and " + part.name + " is going to make an evolve on " + PartLoader.getPartInfoByName(initialPart));

                AvailablePart partToEvolve = PartLoader.getPartInfoByName(initialPart);
                if (partToEvolve != null && partToEvolve.partPrefab != null)
                {
                    evolve(partToEvolve);
                }
            }
        }
        private void explodePart()
        {
            //refund (waranty)
            MerillData.log("enginetestAtm : get cost: " + part.partInfo.cost);
            float cost = part.partInfo.cost;

            if (cost > 0)
            {
                MerillData.log("enginetestAtm : add fund: " + cost);
                Funding.Instance.AddFunds(cost, TransactionReasons.VesselLoss);
            }
            //explode
            part.explode();
        }
 protected override string GetTitle()
 {
     if (body2Shoot == null || situationForShoot == ExperimentSituations.SrfSplashed)
     {
         return("mmm... there're a bug, blame merill!");
     }
     else
     {
         return(string.Format(MerillData.str_camera_title_param,
                              body2Shoot.name,
                              MerillData.situation2String(situationForShoot))
                + (useKerbal ? MerillData.str_camera_title_param_withkerbal : ""));
         //"Take footage of "+body2Shoot.name+" at "+situationForShoot+" "+(useKerbal?" with a kerbal.":"");
     }
 }
        private void removeExperimentalPart(string sExperimentalPartName)
        {
            MerillData.log("plantmunflag: DECLINED contract with experimental part: " + sExperimentalPartName);

            if (sExperimentalPartName != null)
            {
                AvailablePart experimentalPart = PartLoader.getPartInfoByName(sExperimentalPartName);

                if (experimentalPart != null && ResearchAndDevelopment.IsExperimentalPart(experimentalPart))
                {
                    MerillData.log("plantmunflag: Locking part: " + sExperimentalPartName);

                    ResearchAndDevelopment.RemoveExperimentalPart(experimentalPart);
                }
            }
        }
示例#18
0
        public override void OnStart(StartState state)
        {
            base.OnStart(state);

            MerillData.log("consumeEnergy start : " + part.name + " " + isRunning + ", " + consumptionPerSecond);
            if (!isRunning)
            {
                MerillData.log("consumeEnergy shudown !");
                shutdownExperiment();
                energyConsumptionDisplay = "0 per s";
            }
            else
            {
                energyConsumptionDisplay = (consumptionPerSecond < 60 ? consumptionPerSecond * 60 : consumptionPerSecond).ToString("F2")
                                           + (consumptionPerSecond < 60 ? " per min" : "per sec");
            }
        }
示例#19
0
        public override void OnLoad(ConfigNode node)
        {
            base.OnLoad(node);
            instance = this;

            //load
            if (node.HasValue("partNameCrashed"))
            {
                partNameCrashed.AddRange(node.GetValues("partNameCrashed"));
            }
            if (node.HasValue("partNameTested"))
            {
                partNameTested.AddRange(node.GetValues("partNameTested"));
            }

            maxNBSecBurn = new Dictionary <string, int>();
            loadDictionnary(maxNBSecBurn, "maxNBSecBurn", node);
            //print("[MERILL]DATA Onload maxNBSecBurn count:" + maxNBSecBurn.Count);

            nbRestart = new Dictionary <string, int>();
            loadDictionnary(nbRestart, "nbRestart", node);
            //print("[MERILL]DATA Onload nbRestart count:" + nbRestart.Count);

            loadDictionnary(notAleatIndex, "notAleatIndex", node);

            //print("[MERILL]DATA Onload:" + node.name + " contain name " + node.GetValue("name"));
            //print("[MERILL]DATA Onload partNameCrashed:" + partNameCrashed.Count);


            //reload part info (because now i can display the right numbers)
            foreach (AvailablePart aPart in PartLoader.Instance.parts)
            {
                //print("[MERILL]recompute info for " + aPart.name);

                if (aPart.partPrefab != null && aPart.partPrefab.Modules != null)
                {
                    foreach (PartModule pm in aPart.partPrefab.Modules)
                    {
                        if (pm is MerillAbstractPartTest)
                        {
                            ((MerillAbstractPartTest)pm).recomputeInfoMsg();
                        }
                    }
                }
            }
        }
示例#20
0
        public override void OnStart(StartState state)
        {
            base.OnStart(state);

            if (isInactive)
            {
                stateDisplay = "Dead";
            }

            // FindObjectOfType the BTSM science module
            MerillData.log("SCIENCE! start, search in module " + part.Modules.Count);
            foreach (PartModule pm in part.Modules)
            {
                //MerillData.log("SCIENCE! start, find module " + pm.moduleName);
                if (pm.moduleName.Equals("BTSMModuleScienceExperiment"))
                {
                    scienceExperiment = (ModuleScienceExperiment)pm;
                    btsmScienceEvent  = pm.Events["BTSMDeployExperiment"];
                    btsmScienceAction = pm.Actions["BTSMDeployExperimentAction"];
                    BaseEvent  merillScienceEvent  = Events["MERILLScienceEventDeployOrTest"];
                    BaseAction merillScienceAction = Actions["MERILLScienceActionDeployOrTest"];
                    //MerillData.log("science! start, find evenat&action '" + btsmScienceEvent + "', '" + btsmScienceAction + "'");
                    //MerillData.log("science! start, find evenat&action '" + merillScienceEvent + "', '" + merillScienceAction + "'");
                    if (merillScienceEvent != null && merillScienceAction != null)
                    {
                        if (isInactive)
                        {
                            merillScienceEvent.guiActive = false;
                            merillScienceAction.active   = false;
                        }
                        if (btsmScienceEvent != null && btsmScienceAction != null)
                        {
                            canBeTested = true;
                            btsmScienceEvent.guiActive       = false;
                            btsmScienceEvent.guiActiveEditor = false;
                            btsmScienceAction.active         = false;
                            merillScienceEvent.guiName       = btsmScienceEvent.guiName;
                            merillScienceAction.guiName      = btsmScienceAction.guiName;
                            //MerillData.log("science! start, merillScienceEvent.name= '" + merillScienceEvent.guiName + "'");
                        }
                    }
                }
            }
        }
        public override void loadDataFromScenario(MerillData scenario)
        {
            //MerillData.log("loadDataFromScenario : " + scenario);
            if (!scenario.maxNBSecBurn.ContainsKey(part.name + "Atmo"))
            {
                scenario.maxNBSecBurn[part.name + "Atmo"] = 6;
            }
            maxNBSecBurnAtmo = scenario.maxNBSecBurn[part.name + "Atmo"];

            if (!scenario.nbRestart.ContainsKey(part.name + "Atmo"))
            {
                //MerillData.log("loadDataFromScenario maxNBRestartAtmo is not present ");
                scenario.nbRestart[part.name + "Atmo"] = 0;
            }
            maxNBRestartAtmo = scenario.nbRestart[part.name + "Atmo"];

            nbRestartDisplay = "Tested for: " + maxNBRestartAtmo;
            burnTimeDisplay  = "Tested for: " + maxNBSecBurnAtmo;

            //init these var only when ship start, after that it's via KSPField
            nbRestart           = 0;
            runningLastUpdate   = false;
            isLogingTest        = false;
            wait4secRestart     = false;
            nextDurationToCheck = 0;
            //check if igniter is needed
            maxIgniter = 0;
            //MerillData.log("loadDataFromScenario : '" + part + "'");
            //MerillData.log("loadDataFromScenario : '" + part.Resources + "'");
            foreach (PartResource resource in part.Resources)
            {
                //MerillData.log(" enginetest " + part.name + " has " + resource.maxAmount + " " + resource.resourceName);
                maxIgniter += resource.resourceName.Equals("EngineIgniter") ? (int)resource.maxAmount : 0;
            }
            if (maxIgniter == 0)
            {
                BaseField merilShowNbRestart = base.Fields["nbRestartDisplay"];
                if (merilShowNbRestart != null)
                {
                    merilShowNbRestart.guiActive = false;
                }
            }
            //MerillData.log(" enginetest " + part.name + " has " + maxIgniter + " igniter");
        }
示例#22
0
        //get situation, srfLanded = landed, SrfSplashed is used as "not a situation"
        static public ExperimentSituations getDetailedSituation(Vessel vessel)
        {
            //landed?
            if (vessel.situation == Vessel.Situations.LANDED
                | vessel.situation == Vessel.Situations.PRELAUNCH
                | vessel.situation == Vessel.Situations.SPLASHED)
            {
                return(ExperimentSituations.SrfLanded);
            }

            MerillData.log("getDetailedSituation atmosphere: " + vessel.mainBody.atmosphere);
            MerillData.log("getDetailedSituation flyingAltitudeThreshold: " + vessel.mainBody.scienceValues.flyingAltitudeThreshold + " ?> " + vessel.altitude);
            MerillData.log("getDetailedSituation maxAtmosphereAltitude: " + vessel.mainBody.maxAtmosphereAltitude + " ?< " + vessel.altitude);
            MerillData.log("getDetailedSituation spaceAltitudeThreshold: " + vessel.mainBody.scienceValues.spaceAltitudeThreshold + " ?> " + vessel.altitude);

            if (vessel.mainBody.atmosphere && vessel.mainBody.maxAtmosphereAltitude > vessel.altitude)       // i am in atmo?
            {
                if (vessel.mainBody.scienceValues.flyingAltitudeThreshold > vessel.altitude)                 // where in atmo?
                {
                    return(ExperimentSituations.FlyingLow);
                }
                else
                {
                    return(ExperimentSituations.FlyingHigh);
                }
            }

            if (!vessel.mainBody.atmosphere && vessel.mainBody.maxAtmosphereAltitude < vessel.altitude)     //i am in space?
            {
                if (vessel.mainBody.scienceValues.spaceAltitudeThreshold > vessel.altitude)                 //where in space?
                {
                    return(ExperimentSituations.InSpaceLow);
                }
                else
                {
                    return(ExperimentSituations.InSpaceHigh);
                }
            }

            //not landed, in atmo nether space => impossible!
            return(ExperimentSituations.SrfSplashed);
        }
        public override void OnUpdate()
        {
            base.OnUpdate();
            MerillData.log(" research onUpdate " + part.name + " with info: " + part.partInfo);
            if (loaded && !change)
            {
                //evolve if we are researched (TODO: test when it's necessary to do this: only 1 time?)
                MerillData.log(" research onload " + part.name + " with info: " + part.partInfo);
                if (part.partInfo != null && ResearchAndDevelopment.PartTechAvailable(this.part.partInfo))
                {
                    MerillData.log(" research onload " + part.name + ", i'm researched for " + PartLoader.getPartInfoByName(initialPart));

                    AvailablePart partToEvolve = PartLoader.getPartInfoByName(initialPart);
                    if (partToEvolve != null && partToEvolve.partPrefab != null)
                    {
                        evolve(partToEvolve);
                    }
                }
                change = true;
            }
        }
        protected override void OnLoad(ConfigNode node)
        {
            MerillData.log(" contract OnLoad " + this.dateAccepted);
            base.OnLoad(node);
            //accepted? register listener?
            if (this.dateAccepted > 0 && !listenerRegistered)
            {
                //need to do this, because reloading the game re-init the parts from cfg
                addExperimentalParts();

                //register for research event to add exp part.
                if (!listenerRegistered)
                {
                    GameEvents.OnTechnologyResearched.Add(refreshExperimentalParts);
                    listenerRegistered = true;
                }
            }
            else
            {
                removeExperimentalParts();
            }
        }
        private void addExperimentalPart(string sExperimentalPartName)
        {
            MerillData.log("accepted contract with experimental part: " + sExperimentalPartName);

            if (sExperimentalPartName != null)
            {
                AvailablePart experimentalPart = PartLoader.getPartInfoByName(sExperimentalPartName);

                MerillData.log("experimental part: " + experimentalPart + ", " + (experimentalPart == null ? "" : "" + ResearchAndDevelopment.IsExperimentalPart(experimentalPart)));
                if (experimentalPart != null && !ResearchAndDevelopment.IsExperimentalPart(experimentalPart))
                {
                    MerillData.log(": Unlocking part: " + sExperimentalPartName);

                    ResearchAndDevelopment.AddExperimentalPart(experimentalPart);
                    //expPartToRemove.Add(experimentalPart.name);
                }
                else
                {
                    MerillData.log(": Part unvailable / already research: " + sExperimentalPartName);
                }
            }
        }
        //TODO: separate ">50% thrust" and "sometimes <50% trust"
        private void checkFlightDuration()
        {
            //check if we have to do a duration test = (10 * 2^X) [ when (byte)X change => test ] + some random
            if (burnTime() > maxNBSecBurnAtmo)
            {
                if (nextDurationToCheck == 0)
                {
                    //init
                    nextDurationToCheck = Math.Max((7d + aleat.NextDouble() * 6f), maxNBSecBurnAtmo * (1.5d + aleat.NextDouble() / 2));


                    MerillData.log(" enginetest  init duration test to " + nextDurationToCheck);

                    // use instrumentation (if not in use)
                    isLogingTest = isLogingTest || useInstrumentation();

                    if (isLogingTest)
                    {
                        //ScreenMessages.PostScreenMessage("Part " + part.partInfo.title.ToString()
                        //	+ " is now instrumented in " + (atmo ? "atmosphere" : "vaccum") + " for a long burn test."
                        //	, 3f, ScreenMessageStyle.UPPER_CENTER);
                        drawMsgToUser(string.Format(MerillData.str_enginetest_duration_begin,
                                                    part.partInfo.title.ToString(),
                                                    "")
                                      , 3);
                    }
                }
                else if (burnTime() > nextDurationToCheck)
                {
                    //test
                    testEngineDuration();

                    //compute next
                    nextDurationToCheck = maxNBSecBurnAtmo * (1.5d + aleat.NextDouble() / 2);
                }
            }
        }
        //TODO: separate ">50% thrust" and "sometimes <50% trust"
        private void checkFlightDuration()
        {
            bool atmo = isAtmo();

            //MerillData.log(" enginetest checkFlightDuration into " + (atmo ? "atmo" : "vac") + ", and before = " + isFlyingAtmo);
            //isFlyingAtmo
            if (isFlyingAtmo != atmo)
            {
                //change!
                //update if needed
                //MerillData.log(" enginetest checkFlightDuration update?" + isLogingTest);
                if (isLogingTest)
                {
                    //log max burn time & test engine for the little duration
                    testEngineDuration(atmo);
                }
                //like a startup
                nextDurationToCheck = 0;
                nbRestart           = 0;
                isFlyingAtmo        = false;
                timeIgnitedLaunch   = part.vessel.launchTime;
                timeIgnitedMission  = part.vessel.missionTime;
                //begin test it the next udate
                return;
            }
            //MerillData.log(" enginetest " + part.name + " duration: " + (part.vessel.launchTime - timeIgnited ) + " ? "
            //	+ (atmo ? maxNBSecBurnAtmo : maxNBSecBurnVac));
            //check if we have to do a duration test = (10 * 2^X) [ when (byte)X change => test ] + some random
            if (burnTime() > (atmo ? maxNBSecBurnAtmo : maxNBSecBurnVac))
            {
                if (nextDurationToCheck == 0)
                {
                    //init
                    nextDurationToCheck = Math.Max((7d + aleat.NextDouble() * 6f), (atmo ? maxNBSecBurnAtmo : maxNBSecBurnVac) * (1.5d + aleat.NextDouble() / 2));
                    isFlyingAtmo        = atmo;

                    MerillData.log(" enginetest  init duration test to " + nextDurationToCheck);

                    // use instrumentation (if not in use)
                    isLogingTest = isLogingTest || useInstrumentation();

                    if (isLogingTest)
                    {
                        //ScreenMessages.PostScreenMessage("Part " + part.partInfo.title.ToString()
                        //	+ " is now instrumented in " + (atmo ? "atmosphere" : "vaccum") + " for a long burn test."
                        //	, 3f, ScreenMessageStyle.UPPER_CENTER);
                        drawMsgToUser(string.Format(MerillData.str_enginetest_duration_begin,
                                                    part.partInfo.title.ToString(),
                                                    (needVacuumTest?("in" + (atmo ? MerillData.str_atmo : MerillData.str_vac)):""))
                                      , 3);
                    }
                }
                else if (burnTime() > nextDurationToCheck)
                {
                    //test
                    testEngineDuration(atmo);

                    //compute next
                    nextDurationToCheck = (atmo ? maxNBSecBurnAtmo : maxNBSecBurnVac) * (1.5d + aleat.NextDouble() / 2);
                }
            }
        }
        // Add stub part into research node
        // Add exp part if in a researched node (from stub part)
        private void addExperimentalParts()
        {
            if (base.dateAccepted == 0)
            {
                MerillData.log("mun mission: can't add exp part: date accepted=" + dateAccepted);
            }
            try
            {
                //add mandatory parts
                addExperimentalPart("MerillnlineCockpitLander");

                //add part from stubs
                foreach (AvailablePart aPart in PartLoader.Instance.parts)
                {
                    if (aPart.partPrefab != null && aPart.partPrefab.Modules != null)
                    {
                        //MerillData.log("part " + aPart.name);
                        foreach (PartModule pm in aPart.partPrefab.Modules)
                        {
                            if (pm.moduleName.Equals("MerillMissionStub"))
                            {
                                if (((MerillMissionStub)pm).missionName.Equals(this.GetType().Name))
                                {
                                    MerillData.log(" RD find a part " + pm.name);
                                    MerillData.log(" RD purchased? " + ResearchAndDevelopment.PartModelPurchased(aPart));
                                    MerillData.log(" RD available? " + ResearchAndDevelopment.PartTechAvailable(aPart));
                                    MerillData.log(" RD mi " + aPart.moduleInfo);
                                    MerillData.log(" RD tech required: " + aPart.TechRequired);
                                    MerillData.log(" RD tech Really required: " + ((MerillMissionStub)pm).techRequired);
                                    MerillData.log(" RD tech Really required purchased? : "
                                                   + ResearchAndDevelopment.GetTechnologyState(((MerillMissionStub)pm).techRequired));
                                    //already set, and already researched?
                                    if (ResearchAndDevelopment.GetTechnologyState(
                                            ((MerillMissionStub)pm).techRequired) == RDTech.State.Available &&
                                        aPart.TechRequired == ((MerillMissionStub)pm).techRequired)
                                    {
                                        MerillData.log(" RD find a part with r&d node " + pm.name);
                                        //check if already experimental
                                        if (!ResearchAndDevelopment.IsExperimentalPart(
                                                PartLoader.getPartInfoByName(((MerillMissionStub)pm).partUnlock)))
                                        {
                                            addExperimentalPart(((MerillMissionStub)pm).partUnlock);
                                        }
                                    }
                                    // not set
                                    else if (aPart.TechRequired == "specializedControl")
                                    {
                                        try {
                                            //try to attach the stub to a research node
                                            MerillData.log(" RD find a part without r&d node " + pm.name);

                                            RDTech tech = AssetBase.RnDTechTree.FindTech(
                                                ((MerillMissionStub)pm).techRequired);
                                            if (tech != null)
                                            {
                                                //Set it
                                                MerillData.log(" RD find good tech " + tech.name);
                                                aPart.TechRequired = ((MerillMissionStub)pm).techRequired;
                                                tech.partsAssigned.Add(aPart);
                                                MerillData.log(" RD find tech assigned ");

                                                MerillData.log(" RD good tech purchased? " + tech.state
                                                               + " , " + tech.enabled + ", ");
                                                //already researched?
                                                if (ResearchAndDevelopment.GetTechnologyState(((MerillMissionStub)pm).techRequired) == RDTech.State.Available)
                                                {
                                                    addExperimentalPart(((MerillMissionStub)pm).partUnlock);
                                                }
                                            }
                                        }
                                        catch (Exception e)
                                        {
                                            MerillData.log(" RD Exeption:  " + e);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                //TODO: made this auto + add stub in tree
                //if (ResearchAndDevelopment.PartModelPurchased(PartLoader.getPartInfoByName("MerillCheapFuelTank1-2Stub")))
                //	addExperimentalPart("MerillCheapFuelTank1-2");


                //if (ResearchAndDevelopment.PartModelPurchased(PartLoader.getPartInfoByName("MerillCheapFuelTank3-2Stub")))
                //	addExperimentalPart("MerillCheapFuelTank3-2");

                //if (ResearchAndDevelopment.PartModelPurchased(PartLoader.getPartInfoByName("MerillLinearRcsExperimental")))
                //	addExperimentalPart("MerillLinearRcsExperimental");
            }
            catch (Exception e)
            {
                MerillData.log(" exception at contract OnAccepted:" + e);
            }
        }
 protected override void OnSave(ConfigNode node)
 {
     MerillData.log(" contract OnSave ");
     //GameEvents.OnTechnologyResearched.Remove(refreshExperimentalParts);
     base.OnSave(node);
 }
        protected void removeExperimentalParts()
        {
            try
            {
                //remove mandatory parts
                removeExperimentalPart("MerillnlineCockpitLander");

                foreach (AvailablePart aPart in PartLoader.Instance.parts)
                {
                    if (aPart.partPrefab != null && aPart.partPrefab.Modules != null)
                    {
                        foreach (PartModule pm in aPart.partPrefab.Modules)
                        {
                            if (pm.moduleName.Equals("MerillMissionStub"))
                            {
                                if (((MerillMissionStub)pm).missionName.Equals(this.GetType().Name))
                                {
                                    MerillData.log(" RD find a part " + pm.name);
                                    MerillData.log(" RD purchased? " + ResearchAndDevelopment.PartModelPurchased(aPart));
                                    MerillData.log(" RD available? " + ResearchAndDevelopment.PartTechAvailable(aPart));
                                    MerillData.log(" RD mi '" + aPart.moduleInfo + "'");
                                    MerillData.log(" RD tech required: " + aPart.TechRequired);
                                    MerillData.log(" RD tech Really required: " + ((MerillMissionStub)pm).techRequired);
                                    //research and set
                                    if (ResearchAndDevelopment.GetTechnologyState(((MerillMissionStub)pm).techRequired) == RDTech.State.Available &&
                                        aPart.TechRequired == ((MerillMissionStub)pm).techRequired)
                                    {
                                        MerillData.log(" RD purchased, is experimental? "
                                                       + ResearchAndDevelopment.IsExperimentalPart(
                                                           PartLoader.getPartInfoByName(((MerillMissionStub)pm).partUnlock)));
                                        //check if experimental
                                        if (ResearchAndDevelopment.IsExperimentalPart(
                                                PartLoader.getPartInfoByName(((MerillMissionStub)pm).partUnlock)))
                                        {
                                            removeExperimentalPart(((MerillMissionStub)pm).partUnlock);
                                        }
                                        //remove from tech
                                        RDTech tech = AssetBase.RnDTechTree.FindTech(aPart.TechRequired);
                                        if (tech != null)
                                        {
                                            MerillData.log(" RD find good tech " + tech.name);
                                            aPart.TechRequired = "specializedControl";
                                            tech.partsAssigned.Remove(aPart);
                                        }
                                    }
                                    //set? ==((MerillMissionStub)pm).techRequired
                                    else if (aPart.TechRequired != "specializedControl")
                                    {
                                        try {
                                            //try to remove the stub to a research node
                                            MerillData.log(" RD find a part with r&d node " + pm.name);

                                            RDTech tech = AssetBase.RnDTechTree.FindTech(aPart.TechRequired);
                                            if (tech != null)
                                            {
                                                MerillData.log(" RD find good tech " + tech.name);
                                                aPart.TechRequired = "specializedControl";
                                                tech.partsAssigned.Remove(aPart);
                                                MerillData.log(" RD find tech assigned ");
                                                if (ResearchAndDevelopment.GetTechnologyState(((MerillMissionStub)pm).techRequired) == RDTech.State.Available)
                                                {
                                                    removeExperimentalPart(((MerillMissionStub)pm).partUnlock);
                                                }
                                            }
                                        }
                                        catch (Exception e)
                                        {
                                            MerillData.log(" RD Exeption:  " + e);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                MerillData.log(" exception at contract OnAccepted:" + e);
            }
        }