internal static void cache_game_parts() { CraftManager.log("caching game parts"); locked_parts.Clear(); List <string> part_names = new List <string>(); foreach (AvailablePart part in PartLoader.LoadedPartsList) { if (!part_data.ContainsKey(part.name)) { part_data.Add(part.name, part); } part_names.AddUnique(part.name); if (!ResearchAndDevelopment.PartTechAvailable(part)) { locked_parts.AddUnique(part.name); } } //Make a string containing all the installed parts and the data from LoaderInfo in the save file and //then generate a checksum from it. This is used as a signature of the installed setup which will change //if the installed mods are changed enabling craft to disregard cached data after a change in mod setup. part_names.Sort(); string s = String.Join("", part_names.ToArray()); string lf = ""; try{ ConfigNode save_data = ConfigNode.Load(Paths.joined(CraftManager.ksp_root, "saves", HighLogic.SaveFolder, "persistent.sfs")); ConfigNode loader_info = save_data.GetNode("GAME").GetNode("LoaderInfo"); lf = loader_info.ToString(); } catch (Exception e) { CraftManager.log("Failed to read loaderinfo " + e.Message); } installed_part_sig = Checksum.digest(s + lf); }
public override bool MeetRequirements() { AvailablePart ap1 = PartLoader.getPartInfoByName("tarsierSpaceTelescope"); AvailablePart ap2 = PartLoader.getPartInfoByName("tarsierAdvSpaceTelescope"); return(ResearchAndDevelopment.PartTechAvailable(ap1) || ResearchAndDevelopment.PartTechAvailable(ap2)); }
public override bool RequirementMet(ConfiguredContract contract) { foreach (string tech in techs) { ProtoTechNode techNode = ResearchAndDevelopment.Instance.GetTechState(tech); if (techNode == null || techNode.state != RDTech.State.Available) { return(false); } } foreach (string partModule in partModules) { bool hasModule = false; foreach (AvailablePart part in PartLoader.LoadedPartsList) { if (part.partPrefab == null || part.partPrefab.Modules == null) { continue; } if (ResearchAndDevelopment.PartTechAvailable(part)) { hasModule = true; break; } } if (!hasModule) { return(false); } } foreach (string partModuleType in partModuleTypes) { bool hasType = false; foreach (AvailablePart part in PartLoader.LoadedPartsList) { if (part.partPrefab == null || part.partPrefab.Modules == null) { continue; } if (part.partPrefab.HasValidContractObjective(partModuleType) && ResearchAndDevelopment.PartTechAvailable(part)) { hasType = true; break; } } if (!hasType) { return(false); } } return(true); }
static bool PartResearched(AvailablePart p) { if (p == null) { return(false); } return(ResearchAndDevelopment.PartTechAvailable(p) && ResearchAndDevelopment.PartModelPurchased(p)); }
bool IsPartUnlocked(string name) { AvailablePart part = PartLoader.getPartInfoByName(name); if (part != null && ResearchAndDevelopment.PartTechAvailable(part)) { return(true); } return(false); }
public override bool MeetRequirements() { AvailablePart ap1 = PartLoader.getPartInfoByName("tarsierChemCam"); if (ap1 != null) { return(ResearchAndDevelopment.PartTechAvailable(ap1)); } Utilities.Log("It appears the TST ChemCam part is missing. Cannot check Contract Requirements"); return(false); }
public override bool RequirementMet(ConfiguredContract contract) { foreach (AvailablePart part in parts) { if (!ResearchAndDevelopment.PartTechAvailable(part)) { return(false); } } return(true); }
bool AllUnlocked(HashSet <string> set) { foreach (string entry in set) { AvailablePart part = PartLoader.getPartInfoByName(entry); if (!(ResearchAndDevelopment.PartTechAvailable(part) && ResearchAndDevelopment.PartModelPurchased(part))) { return(false); } } return(true); }
public override bool MeetRequirements() { AvailablePart ap = PartLoader.getPartInfoByName("Impact Spectrometer"); if (ap != null) { if (ResearchAndDevelopment.PartTechAvailable(ap)) { return(true); } } return(false); }
bool AllUnlocked(HashSet <string> set) { foreach (string entry in set) { AvailablePart part = PartLoader.getPartInfoByName(entry); if (!(ResearchAndDevelopment.PartTechAvailable(part) /*&& ResearchAndDevelopment.PartModelPurchased(part)*/)) { //In career mode I certainly don't purchase parts until I need them to fulfil a contract //And if you can't get the contracts until you have purchased them... return(false); } } return(true); }
public override void OnStart(StartState state) { base.OnStart(state); // Group our stuff in the engine's menu foreach (BaseField f in Fields) { f.group.name = guiGroup; f.group.displayName = guiGroupDisplayName; } foreach (BaseEvent e in Events) { e.group.name = guiGroup; e.group.displayName = guiGroupDisplayName; } if (state == StartState.Editor) // This is an upgrade, so don't give it to an already in flight vessel that doesn't have it { researchPartName = researchPartName.Replace("_", "."); var ap = PartLoader.getPartInfoByName(researchPartName); if (ap == null) { Log.Error("researchPartName = " + researchPartName + "; Part not found."); // set isResearched to false here? } else { isResearched = ResearchAndDevelopment.PartModelPurchased(ap) && ResearchAndDevelopment.PartTechAvailable(ap); if (!isResearched) { if (!ResearchAndDevelopment.PartModelPurchased(ap)) { Log.Info("SmartSRB not available due to PartModel not being purchased"); } if (!ResearchAndDevelopment.PartTechAvailable(ap)) { Log.Info("SmartSRB not available due to PartTech not being available"); } } } } moduleIsEnabled = isResearched; updateButtons(); //GameEvents.onEngineActiveChange.Add(onEngineActiveChange); //StartCoroutine(GuiUpdate()); }
public override bool MeetRequirements() { // stop checking when requirements are met if (!meet_requirements) { var greenhouse = PartLoader.getPartInfoByName("kerbalism-greenhouse"); meet_requirements = greenhouse != null && // greenhouse part is present greenhouse.tags.Contains("_kerbalism") && // greenhouse part is enabled ResearchAndDevelopment.PartTechAvailable(greenhouse) && // greenhouse part unlocked !DB.landmarks.space_harvest; // greenhouse never harvested in space before } return(meet_requirements); }
public override bool MeetRequirements() { // stop checking when requirements are met if (!meet_requirements) { var lab = PartLoader.getPartInfoByName("Large_Crewed_Lab"); meet_requirements = Features.Science && // science is enabled lab != null && // lab part is present ResearchAndDevelopment.PartTechAvailable(lab) && // lab part is unlocked !DB.landmarks.space_analysis; // never analyzed samples in space before } return(meet_requirements); }
// List available experiments private void GetExperiments() { unlockedExperiments.Clear(); availableExperiments.Clear(); List <AvailablePart> parts = PartLoader.Instance.loadedParts; // EVA Reports available from the beginning unlockedExperiments.Add(ResearchAndDevelopment.GetExperiment("evaReport")); // Don't check RnD level to determine if surface samples are available, in case another mod messes with the Facility Levels. //Instead just check the experiment is available directly. if (ResearchAndDevelopment.GetExperiment("surfaceSample").IsUnlocked()) { unlockedExperiments.Add(ResearchAndDevelopment.GetExperiment("surfaceSample")); } foreach ( AvailablePart part in parts.Where ( x => ResearchAndDevelopment.PartTechAvailable(x) && !excludedManufacturers.Contains(x.manufacturer) && ResearchAndDevelopment.PartModelPurchased(x) ) ) { // Part has some modules if (part.partPrefab.Modules != null) { // Check science modules foreach (ModuleScienceExperiment ex in part.partPrefab.Modules.OfType <ModuleScienceExperiment>()) { if (ex.experimentID == null) { Log.Error("part's " + part.name + " experimentID is null"); continue; } // Remove experiments with empty ids, by [Kerbas-ad-astra](https://github.com/Kerbas-ad-astra) // Remove Surface Experiments Pack experiments not meant to run in atmosphere if (ex.experimentID != "" && !excludedExperiments.Contains(ex.experimentID)) { unlockedExperiments.AddUnique <ScienceExperiment>(ResearchAndDevelopment.GetExperiment(ex.experimentID)); } } } } }
public static List <AvailablePart> getAvailableExperimentParts(string type, bool includeExperimental = false) { string[] partsRegistry = null; List <AvailablePart> list = null; switch (type) { case OMS_EXPERIMENTS: partsRegistry = omsRegistry; break; case KEMINI_EXPERIMENTS: //partsRegistry = keminiRegistry; partsRegistry = getKeminiRegister(); break; default: return(list); } // Avoid multiple allocations; the collection is small enough that the memory overhead is better than the reallocation overhead list = new List <AvailablePart>(partsRegistry.Length); for (int idx = 0, count = partsRegistry.Length; idx < count; idx++) { AvailablePart part = PartLoader.getPartInfoByName(partsRegistry[idx]); if (part == null) { continue; } /* * bool isPurchased = ResearchAndDevelopment.PartModelPurchased (part); * bool isTechAvailable = ResearchAndDevelopment.PartTechAvailable (part); * bool isExperimental = ResearchAndDevelopment.IsExperimentalPart (part); * NE_Helper.log ("Part " + part.name + * " techlevel: [" + isTechAvailable + "]" + * " experimental: [" + isExperimental + "]" + * " purchased: [" + isPurchased + "]"); */ if (ResearchAndDevelopment.PartModelPurchased(part) || (includeExperimental && ResearchAndDevelopment.PartTechAvailable(part))) { list.Add(part); } } return(list); }
// List available experiments private void GetExperiments() { unlockedExperiments.Clear(); availableExperiments.Clear(); List <AvailablePart> parts = PartLoader.Instance.loadedParts; // EVA Reports available from the beginning unlockedExperiments.Add(ResearchAndDevelopment.GetExperiment("evaReport")); // To take surface samples from other worlds you need to upgrade Astronaut Complex and R&D // But to take surface samples from home you need to only upgrade R&D if (ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.ResearchAndDevelopment) > 0.0) { unlockedExperiments.Add(ResearchAndDevelopment.GetExperiment("surfaceSample")); } foreach ( AvailablePart part in parts.Where ( x => ResearchAndDevelopment.PartTechAvailable(x) && !excludedManufacturers.Contains(x.manufacturer) && ResearchAndDevelopment.PartModelPurchased(x) ) ) { // Part has some modules if (part.partPrefab.Modules != null) { // Check science modules foreach (ModuleScienceExperiment ex in part.partPrefab.Modules.OfType <ModuleScienceExperiment>()) { if (ex.experimentID == null) { Log("part's " + part.name + " experimentID is null"); continue; } // Remove experiments with empty ids, by [Kerbas-ad-astra](https://github.com/Kerbas-ad-astra) // Remove Surface Experiments Pack experiments not meant to run in atmosphere if (ex.experimentID != "" && !excludedExperiments.Contains(ex.experimentID)) { unlockedExperiments.AddUnique <ScienceExperiment> (ResearchAndDevelopment.GetExperiment(ex.experimentID)); } } } } }
private static void addParts(List <string> partNames, List <ExperimentData> list) { foreach (string pn in partNames) { AvailablePart part = PartLoader.getPartInfoByName(pn); if (part != null) { if (ResearchAndDevelopment.PartTechAvailable(part)) { Part pPf = part.partPrefab; NE_ExperimentModule exp = pPf.GetComponent <NE_ExperimentModule>(); float mass = pPf.mass; list.Add(getExperiment(exp.type, mass)); } } } }
public static bool haveTechnology(string tech) { tech = tech.Replace('_', '.'); AvailablePart ap = PartLoader.getPartInfoByName(tech); if (ap != null) { if (ResearchAndDevelopment.PartTechAvailable(ap)) { return(true); } } else { Debug.LogWarning("Fine Print: Attempted to check for nonexistent technology: \"" + tech + "\"."); } return(false); }
public static List <LabEquipment> getAvailableRacks() { List <LabEquipment> list = new List <LabEquipment>(); foreach (KeyValuePair <EquipmentRacks, string> p in racks) { AvailablePart part = PartLoader.getPartInfoByName(p.Value); if (part != null) { Part pPf = part.partPrefab; LabEquipmentModule lem = pPf.GetComponent <LabEquipmentModule>(); if (ResearchAndDevelopment.PartTechAvailable(part)) { list.Add(getLabEquipment(part.partPrefab, p.Key)); } } } return(list); }
public override bool MeetRequirements() { AvailablePart ap1 = PartLoader.getPartInfoByName("tarsierSpaceTelescope"); AvailablePart ap2 = PartLoader.getPartInfoByName("tarsierAdvSpaceTelescope"); if (ap1 != null && ap2 != null) { return(ResearchAndDevelopment.PartTechAvailable(ap1) || ResearchAndDevelopment.PartTechAvailable(ap2)); } if (ap1 != null && ap2 == null) { return(ResearchAndDevelopment.PartTechAvailable(ap1)); } if (ap1 == null && ap2 != null) { return(ResearchAndDevelopment.PartTechAvailable(ap2)); } Utilities.Log("It appears the TST telescope parts are missing. Cannot check Contract Requirements"); return(false); }
public override bool RequirementMet(ConfiguredContract contract) { foreach (string partModuleType in partModuleTypes) { foreach (AvailablePart part in PartLoader.LoadedPartsList) { if (part.partPrefab == null || part.partPrefab.Modules == null) { continue; } if (part.partPrefab.HasValidContractObjective(partModuleType) && ResearchAndDevelopment.PartTechAvailable(part) && ResearchAndDevelopment.PartModelPurchased(part)) { return(true); } } } return(false); }
private static bool partResearched(AvailablePart ap) { if (ResearchAndDevelopment.Instance == null) { ASPConsoleStuff.AAprint("no ResearchAndDevelopment.Instance, must be sandbox mode"); return(true); } if (!ResearchAndDevelopment.PartTechAvailable(ap)) { ASPConsoleStuff.AAprint(ap.name + ".PartTechAvailable()==false"); return(false); } if (!ResearchAndDevelopment.PartModelPurchased(ap)) { ASPConsoleStuff.AAprint(ap.name + ".PartModelPurchased()==false"); return(false); } return(true); }
private static bool GetPartCost(ConfigNode part, out float total, bool includeFuel = true) { string name = GetPartName(part); float dryCost, fuelCost, mass; total = 0; var aP = GetAvailablePart(name); if (aP == null) { return(false); } //ShipConstruction.GetPartCostsAndMass total = ShipConstruction.GetPartCostsAndMass(part, aP, out dryCost, out fuelCost, out mass, out mass); if (!includeFuel) { total = dryCost; } return(ResearchAndDevelopment.PartTechAvailable(aP)); }
protected override bool Generate() { bool havePod = false; foreach (AvailablePart p in PartLoader.LoadedPartsList) { if (p.partPrefab.CrewCapacity > 0 && ResearchAndDevelopment.PartTechAvailable(p)) { havePod = true; break; } } // return false iff we have no crew pods AND we've not reached orbit // so you should get this if you've reached orbit, even if you haven't researched any pods yet. if (!havePod && !ProgressTracking.Instance.NodeComplete("Kerbin", "Orbit")) // SQUAD Y U HARDCODE { return(false); } // one at a time if (base.ContractState != State.Active) { HSFEarthOrbital[] currentContracts = ContractSystem.Instance.GetCurrentContracts <HSFEarthOrbital>(); for (int i = 0; i < currentContracts.Length; i++) { if (currentContracts[i].ContractState == State.Offered || currentContracts[i].ContractState == State.Active) { return(false); } } } prestige = Contract.ContractPrestige.Exceptional; AddParameter(new Contracts.Parameters.HSFOrbital(Planetarium.fetch.Home), null); base.AddKeywords(new string[] { "HSF" }); expiryType = Contract.DeadlineType.None; deadlineType = Contract.DeadlineType.None; // RP-0 scale funds by 0.1x base.SetFunds(10000f, 50000f, null); base.SetReputation(480f, null); return(true); }
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; } }
/// <summary> /// Returns TRUE if the part technology is available. /// </summary> /// <returns><c>true</c>, if part technology available, <c>false</c> otherwise.</returns> /// <param name="name">Name.</param> public static bool IsPartTechAvailable(string name) { AvailablePart part = PartLoader.getPartInfoByName(name); return(part != null && ResearchAndDevelopment.PartTechAvailable(part)); }
public static bool PartResearched(AvailablePart p) { return(ResearchAndDevelopment.PartTechAvailable(p) && ResearchAndDevelopment.PartModelPurchased(p)); }
// 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); } }
public override void OnAwake() { base.OnAwake(); GameEvents.onGameSceneLoadRequested.Add(this.GameSceneLoadHandler); GameEvents.OnPartPurchased.Add(this.PartPurchasedHandler); if (this.part.tryGetFirstModuleOfType <ModuleSAS>(out this.sasModule)) { this.SASServiceLevel = this.sasModule.SASServiceLevel; } if (researchedPartsLoaded) { this.SASServiceLevel = maxSASServiceLevel; return; } if (HighLogic.CurrentGame == null || PartLoader.LoadedPartsList == null) { return; } switch (HighLogic.CurrentGame.Mode) { case Game.Modes.CAREER: this.Fields["SASServiceLevel"].guiActiveEditor = true; break; default: this.Fields["SASServiceLevel"].guiActiveEditor = false; Array apModes = Enum.GetValues(typeof(AutopilotSkill.Skills)); int autopilotMode; for (int idx = 0; idx < apModes.Length; idx++) { try { autopilotMode = (int)apModes.GetValue(idx); maxSASServiceLevel = Math.Max(maxSASServiceLevel, autopilotMode); } catch { this.LogDebug( "Failed converting {0}.{1} to int.", typeof(AutopilotSkill.Skills).GetType().Name, Enum.GetName(typeof(AutopilotSkill.Skills), apModes.GetValue(idx)) ); } } researchedPartsLoaded = true; this.LogDebug("Sandbox mode: maxSASServiceLevel = {0}", maxSASServiceLevel); return; } this.LogDebug("Searching for researched parts with SAS modules..."); using (var logger = PooledDebugLogger.New(this)) { AvailablePart part; for (int idx = 0; idx < PartLoader.LoadedPartsList.Count; idx++) { part = PartLoader.LoadedPartsList[idx]; logger.AppendFormat("Checking {0}...", part.title); if (ResearchAndDevelopment.PartTechAvailable(part)) { logger.Append(" researched..."); ModuleSAS sasModule; if (part.partPrefab.tryGetFirstModuleOfType(out sasModule)) { logger.Append(" has SAS module, adding to list."); researchedSASParts.Add(part); maxSASServiceLevel = Math.Max(sasModule.SASServiceLevel, maxSASServiceLevel); logger.AppendFormat(" \n\tmaxSASServiceLevel = {0}.", maxSASServiceLevel); } } #if DEBUG else { logger.Append(" not researched!"); } #endif logger.Append('\n'); } logger.Append("Researched SAS parts loaded."); logger.Print(); } researchedPartsLoaded = true; }
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); } }