/* * Returns true if the contract can be offered. */ public bool MeetRequirements(ConfiguredContract contract) { // Check prestige if (prestige != null && contract.Prestige != prestige) { return(false); } // Get the count of active contracts - excluding ours int activeContracts = ContractSystem.Instance.GetCurrentContracts <ConfiguredContract>().Count(c => c.contractType == this); if (contract.ContractState == Contract.State.Offered || contract.ContractState == Contract.State.Active) { activeContracts--; } // Check if we're breaching the active limit if (maxSimultaneous != 0 && activeContracts >= maxSimultaneous) { return(false); } // Check if we're breaching the completed limit if (maxCompletions != 0) { int finishedContracts = ContractSystem.Instance.GetCompletedContracts <ConfiguredContract>().Count(c => c.contractType == this); if (finishedContracts + activeContracts >= maxCompletions) { return(false); } } // Check the captured requirements return(ContractRequirement.RequirementsMet(contract, this, requirements)); }
/// <summary> /// Method for generating ContractParameter objects. This will call the Generate() method /// on the sub-class, load all common parameters and load child parameters. /// </summary> /// <param name="contract">Contract to generate for</param> /// <param name="contractParamHost">Parent object for the ContractParameter</param> /// <returns>Generated ContractParameter</returns> public virtual ContractParameter Generate(ConfiguredContract contract, IContractParameterHost contractParamHost) { // First check any requirements if (!ContractRequirement.RequirementsMet(contract, contract.contractType, requirements)) { LoggingUtil.LogVerbose(typeof(ParameterFactory), "Returning null for " + contract.contractType.name + "." + name + ": requirements not met."); return(null); } // Generate a parameter using the sub-class logic ContractParameter parameter = Generate(contract); if (parameter == null) { LoggingUtil.LogWarning(this, GetType().FullName + ".Generate() returned a null ContractParameter!"); return(null); } // Add ContractParameter to the host contractParamHost.AddParameter(parameter); // Set the funds/science/reputation parameters parameter.SetFunds(rewardFunds, failureFunds, targetBody); parameter.SetReputation(rewardReputation, failureReputation, targetBody); parameter.SetScience(rewardScience, targetBody); // Set other flags parameter.Optional = optional; if (disableOnStateChange != null) { parameter.DisableOnStateChange = (bool)disableOnStateChange; } parameter.ID = name; // Special stuff for contract configurator parameters ContractConfiguratorParameter ccParam = parameter as ContractConfiguratorParameter; if (ccParam != null) { ccParam.completeInSequence = completeInSequence; ccParam.notes = notes; ccParam.completedMessage = completedMessage; ccParam.hidden = hidden; ccParam.hideChildren = hideChildren; } return(parameter); }
/// <summary> /// Checks if the "extended" requirements that change due to expressions. /// </summary> /// <param name="contract">The contract</param> /// <returns>Whether the contract can be offered.</returns> public bool MeetExtendedRequirements(ConfiguredContract contract, ContractType contractType) { LoggingUtil.LogLevel origLogLevel = LoggingUtil.logLevel; try { // Turn tracing on if (trace) { LoggingUtil.logLevel = LoggingUtil.LogLevel.VERBOSE; LoggingUtil.LogWarning(this, "Tracing enabled for contract type " + name); } // Hash check if (contract.ContractState == Contract.State.Offered && contract.hash != hash) { throw new ContractRequirementException("Contract definition changed."); } // Check prestige if (prestige.Count > 0 && !prestige.Contains(contract.Prestige)) { throw new ContractRequirementException("Wrong prestige level."); } // Do a Research Bodies check, if applicable ResearchBodiesCheck(contract); // Check special values are not null if (contract.contractType == null) { foreach (KeyValuePair <string, DataValueInfo> pair in dataValues) { // Only check if it is a required value if (pair.Value.required) { CheckRequiredValue(pair.Key); } } } if (contract.contractType == null || contract.ContractState == Contract.State.Generated || contract.ContractState == Contract.State.Withdrawn) { // Check for unique values against other contracts of the same type foreach (KeyValuePair <string, DataNode.UniquenessCheck> pair in uniquenessChecks.Where(p => contract.uniqueData.ContainsKey(p.Key))) { string key = pair.Key; DataNode.UniquenessCheck uniquenessCheck = pair.Value; LoggingUtil.LogVerbose(this, "Doing unique value check for " + key); // Get the active/offered contract lists IEnumerable <ConfiguredContract> contractList = ConfiguredContract.CurrentContracts. Where(c => c != null && c.contractType != null && c != contract); // Add in finished contracts if (uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ALL || uniquenessCheck == DataNode.UniquenessCheck.GROUP_ALL) { contractList = contractList.Union(ContractSystem.Instance.ContractsFinished.OfType <ConfiguredContract>(). Where(c => c != null && c.contractType != null && c != contract)); } // Filter anything that doesn't have our key contractList = contractList.Where(c => c.uniqueData.ContainsKey(key)); // Check for contracts of the same type if (uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ALL || uniquenessCheck == DataNode.UniquenessCheck.CONTRACT_ACTIVE) { contractList = contractList.Where(c => c.contractType.name == name); } // Check for a shared group else if (contractType.group != null) { contractList = contractList.Where(c => c.contractType.group != null && c.contractType.group.name == contractType.group.name); } // Shared lack of group else { contractList = contractList.Where(c => c.contractType.group == null); } object val = contract.uniqueData[key]; if (val != null) { // Special case for vessels - convert to the Guid Vessel vessel = val as Vessel; if (vessel != null) { val = vessel.id; } foreach (ConfiguredContract otherContract in contractList) { if (val.Equals(otherContract.uniqueData[key])) { throw new ContractRequirementException("Failed on unique value check for key '" + key + "'."); } } } } } // Check the captured requirements if (!ContractRequirement.RequirementsMet(contract, this, contract.requirements != null ? contract.requirements : requirements)) { throw new ContractRequirementException("Failed on contract requirement check."); } return(true); } catch (ContractRequirementException e) { LoggingUtil.LogLevel level = contract.ContractState == Contract.State.Active ? LoggingUtil.LogLevel.INFO : contract.contractType != null ? LoggingUtil.LogLevel.DEBUG : LoggingUtil.LogLevel.VERBOSE; string prefix = contract.contractType != null ? "Cancelling contract of type " + name + " (" + contract.Title + "): " : "Didn't generate contract of type " + name + ": "; LoggingUtil.Log(level, this.GetType(), prefix + e.Message); return(false); } catch { LoggingUtil.LogError(this, "Exception while attempting to check requirements of contract type " + name); throw; } finally { LoggingUtil.logLevel = origLogLevel; loaded = true; } }
/// <summary> /// Tests whether a contract can be offered. /// </summary> /// <param name="contract">The contract</param> /// <returns>Whether the contract can be offered.</returns> public bool MeetRequirements(ConfiguredContract contract) { // Hash check if (contract.ContractState == Contract.State.Offered && contract.hash != hash) { LoggingUtil.LogDebug(this, "Cancelling offered contract of type " + name + ", contract definition changed."); return(false); } // Check prestige if (prestige.Count > 0 && !prestige.Contains(contract.Prestige)) { LoggingUtil.LogVerbose(this, "Didn't generate contract type " + name + ", wrong prestige level."); return(false); } // Checks for maxSimultaneous/maxCompletions if (maxSimultaneous != 0 || maxCompletions != 0) { // Get the count of active contracts - excluding ours int activeContracts = ContractSystem.Instance.GetCurrentContracts <ConfiguredContract>(). Count(c => c.contractType != null && c.contractType.name == name); if (contract.ContractState == Contract.State.Offered || contract.ContractState == Contract.State.Active) { activeContracts--; } // Check if we're breaching the active limit if (maxSimultaneous != 0 && activeContracts >= maxSimultaneous) { LoggingUtil.LogVerbose(this, "Didn't generate contract type " + name + ", too many active contracts."); return(false); } // Check if we're breaching the completed limit if (maxCompletions != 0) { int finishedContracts = ContractSystem.Instance.GetCompletedContracts <ConfiguredContract>(). Count(c => c.contractType != null && c.contractType.name == name); if (finishedContracts + activeContracts >= maxCompletions) { LoggingUtil.LogVerbose(this, "Didn't generate contract type " + name + ", too many completed/active/offered contracts."); return(false); } } } // Check the group values if (group != null) { // Check the group active limit int activeContracts = ContractSystem.Instance.GetCurrentContracts <ConfiguredContract>().Count(c => c.contractType != null && c.contractType.group == group); if (contract.ContractState == Contract.State.Offered || contract.ContractState == Contract.State.Active) { activeContracts--; } if (group.maxSimultaneous != 0 && activeContracts >= group.maxSimultaneous) { LoggingUtil.LogVerbose(this, "Didn't generate contract type " + name + ", too many active contracts in group."); return(false); } // Check the group completed limit if (group.maxCompletions != 0) { int finishedContracts = ContractSystem.Instance.GetCompletedContracts <ConfiguredContract>().Count(c => c.contractType != null && c.contractType.group == group); if (finishedContracts + activeContracts >= maxCompletions) { LoggingUtil.LogVerbose(this, "Didn't generate contract type " + name + ", too many completed contracts in group."); return(false); } } } // Check special values are not null if (contract.ContractState != Contract.State.Active) { foreach (KeyValuePair <string, bool> pair in dataValues) { // Only check if it is a required value if (pair.Value) { string name = pair.Key; object o = dataNode[name]; if (o == null) { LoggingUtil.LogVerbose(this, "Didn't generate contract type " + this.name + ", '" + name + "' was null."); return(false); } else if (o == typeof(List <>)) { PropertyInfo prop = o.GetType().GetProperty("Count"); int count = (int)prop.GetValue(o, null); if (count == 0) { LoggingUtil.LogVerbose(this, "Didn't generate contract type " + this.name + ", '" + name + "' had zero count."); return(false); } } else if (o == typeof(Vessel)) { Vessel v = (Vessel)o; if (v.state == Vessel.State.DEAD) { LoggingUtil.LogVerbose(this, "Didn't generate contract type " + this.name + ", vessel '" + v.vesselName + "' is dead."); return(false); } } } } } // Check the captured requirements return(ContractRequirement.RequirementsMet(contract, this, requirements)); }