private IEnumerable <ConfiguredContract> GenerateContract(ContractType contractType) { // Set the desired prestige int t1, t2, t3; ContractSystem.GetContractCounts(Reputation.CurrentRep, 1000, out t1, out t2, out t3); if (contractType.prestige.Any()) { if (!contractType.prestige.Contains(Contract.ContractPrestige.Trivial)) { t1 = 0; } if (!contractType.prestige.Contains(Contract.ContractPrestige.Significant)) { t2 = 0; } if (!contractType.prestige.Contains(Contract.ContractPrestige.Exceptional)) { t3 = 0; } } int selection = rand.Next(0, t1 + t2 + t3); Contract.ContractPrestige prestige = selection < t1 ? Contract.ContractPrestige.Trivial : selection < (t1 + t2) ? Contract.ContractPrestige.Significant : Contract.ContractPrestige.Exceptional; // Generate the template ConfiguredContract templateContract = Contract.Generate(typeof(ConfiguredContract), prestige, rand.Next(), Contract.State.Withdrawn) as ConfiguredContract; // First, check the basic requirements if (!contractType.MeetBasicRequirements(templateContract)) { LoggingUtil.LogVerbose(this, "{0} was not generated: basic requirements not met.", contractType.name); if (++contractType.failedGenerationAttempts >= contractType.maxConsecutiveGenerationFailures) { contractType.lastGenerationFailure = Time.realtimeSinceStartup; } yield return(null); yield break; } // Try to refresh non-deterministic values before we check extended requirements OnInitializeValues.Fire(); LoggingUtil.LogLevel origLogLevel = LoggingUtil.logLevel; LoggingUtil.LogLevel newLogLevel = contractType.trace ? LoggingUtil.LogLevel.VERBOSE : LoggingUtil.logLevel; try { // Set up for loop LoggingUtil.logLevel = newLogLevel; ConfiguredContract.currentContract = templateContract; // Set up the iterator to refresh non-deterministic values IEnumerable <string> iter = ConfigNodeUtil.UpdateNonDeterministicValuesIterator(contractType.dataNode); for (ContractGroup g = contractType.group; g != null; g = g.parent) { iter = ConfigNodeUtil.UpdateNonDeterministicValuesIterator(g.dataNode).Concat(iter); } // Update the actual values LoggingUtil.LogVerbose(this, "Refresh non-deterministic values for CONTRACT_TYPE = {0}", contractType.name); foreach (string val in iter) { lastKey = contractType.name + "[" + val + "]"; // Clear temp stuff LoggingUtil.logLevel = origLogLevel; ConfiguredContract.currentContract = null; if (val == null) { LoggingUtil.LogVerbose(this, "{0} was not generated: non-deterministic expression failure.", contractType.name); if (++contractType.failedGenerationAttempts >= contractType.maxConsecutiveGenerationFailures) { contractType.lastGenerationFailure = Time.realtimeSinceStartup; } OnInitializeFail.Fire(); yield return(null); yield break; } else { // Quick pause yield return(null); } // Re set up LoggingUtil.logLevel = newLogLevel; ConfiguredContract.currentContract = templateContract; } } finally { LoggingUtil.logLevel = origLogLevel; ConfiguredContract.currentContract = null; } // Store unique data foreach (string key in contractType.uniquenessChecks.Keys) { if (contractType.dataNode.GetType(key) == typeof(Vessel)) { Vessel v = contractType.dataNode[key] as Vessel; templateContract.uniqueData[key] = v != null ? (object)v.id : null; } else { templateContract.uniqueData[key] = contractType.dataNode[key]; } } templateContract.targetBody = contractType.targetBody; // Check the requirements for our selection if (contractType.MeetExtendedRequirements(templateContract, contractType) && templateContract.Initialize(contractType)) { templateContract.ContractState = Contract.State.Offered; yield return(templateContract); } // Failure, add a pause in before finishing else { LoggingUtil.LogVerbose(this, "{0} was not generated: requirement not met.", contractType.name); if (++contractType.failedGenerationAttempts >= contractType.maxConsecutiveGenerationFailures) { contractType.lastGenerationFailure = Time.realtimeSinceStartup; } OnInitializeFail.Fire(); yield return(null); } }