/*
         * Generates a ContractRequirement from a configuration node.
         */
        public static ContractRequirement GenerateRequirement(ConfigNode configNode, ContractType contractType)
        {
            // Get the type
            string type = configNode.GetValue("type");

            if (!requirementTypes.ContainsKey(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                                     "REQUIREMENT '" + configNode.GetValue("name") + "' of type '" + configNode.GetValue("type") + "': " +
                                     "No ContractRequirement has been registered for type '" + type + "'.");
                return(null);
            }

            // Create an instance of the ContractRequirement
            ContractRequirement requirement = (ContractRequirement)Activator.CreateInstance(requirementTypes[type]);

            // Set attributes
            requirement.contractType = contractType;
            requirement.targetBody   = contractType.targetBody;

            // Load config
            bool valid = requirement.Load(configNode);

            // Check for unexpected values - always do this last
            valid &= ConfigNodeUtil.ValidateUnexpectedValues(configNode, requirement);

            return(valid ? requirement : null);
        }
        /*
         * Checks if all the given ContractRequirement meet the requirement.
         */
        public static bool RequirementsMet(ConfiguredContract contract, ContractType contractType, List <ContractRequirement> contractRequirements)
        {
            bool allReqMet = true;

            try
            {
                LoggingUtil.LogVerbose(typeof(ContractRequirement), "Checking requirements for contract '" + contractType.name);
                foreach (ContractRequirement requirement in contractRequirements)
                {
                    if (requirement.checkOnActiveContract || contract.ContractState != Contract.State.Active)
                    {
                        bool nodeMet = requirement.RequirementMet(contract);
                        LoggingUtil.LogVerbose(typeof(ContractRequirement), "Checked requirement '" + requirement.name + "' of type " + requirement.type + ": " + nodeMet);
                        allReqMet = allReqMet && (requirement.invertRequirement ? !nodeMet : nodeMet);
                    }
                }

                // Force fail the contract if a requirement becomes unmet
                if (contract.ContractState == Contract.State.Active && !allReqMet)
                {
                    // Fail the contract - unfortunately, the player won't know why. :(
                    contract.Fail();

                    // Force the stock contracts window to refresh
                    GameEvents.Contract.onContractsLoaded.Fire();
                }
            }
            catch (Exception e)
            {
                Debug.LogException(new Exception("ContractConfigurator: Exception checking requirements!", e));
                return(false);
            }
            return(allReqMet);
        }
        /// <summary>
        /// Generates a BehaviourFactory from a configuration node.
        /// </summary>
        /// <param name="behaviourConfig">ConfigNode to use in the generation.</param>
        /// <param name="contractType">ContractType that this behaviour falls under</param>
        /// <param name="behaviourFactory">The BehaviourFactory object.</param>
        /// <returns>Whether the load was successful</returns>
        public static bool GenerateBehaviourFactory(ConfigNode behaviourConfig, ContractType contractType, out BehaviourFactory behaviourFactory)
        {
            // Logging on
            LoggingUtil.CaptureLog = true;
            bool valid = true;

            // Get the type
            string type = behaviourConfig.GetValue("type");
            string name = behaviourConfig.HasValue("name") ? behaviourConfig.GetValue("name") : type;

            if (string.IsNullOrEmpty(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                                     "BEHAVIOUR '" + behaviourConfig.GetValue("name") + "' does not specify the mandatory 'type' attribute.");
                behaviourFactory = new InvalidBehaviourFactory();
                valid            = false;
            }
            else if (!factories.ContainsKey(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                                     "BEHAVIOUR '" + behaviourConfig.GetValue("name") + "' of type '" + behaviourConfig.GetValue("type") + "': " +
                                     "No BehaviourFactory has been registered for type '" + type + "'.");
                behaviourFactory = new InvalidBehaviourFactory();
                valid            = false;
            }
            else
            {
                // Create an instance of the factory
                behaviourFactory = (BehaviourFactory)Activator.CreateInstance(factories[type]);
            }

            // Set attributes
            behaviourFactory.contractType = contractType;
            behaviourFactory.dataNode     = new DataNode(name, contractType.dataNode, behaviourFactory);

            // Load config
            valid &= behaviourFactory.Load(behaviourConfig);

            // Check for unexpected values - always do this last
            if (behaviourFactory.GetType() != typeof(InvalidBehaviourFactory))
            {
                valid &= ConfigNodeUtil.ValidateUnexpectedValues(behaviourConfig, behaviourFactory);
            }

            behaviourFactory.enabled = valid;
            behaviourFactory.log     = LoggingUtil.capturedLog;
            LoggingUtil.CaptureLog   = false;

            return(valid);
        }
        /// <summary>
        /// Generates a BehaviourFactory from a configuration node.
        /// </summary>
        /// <param name="behaviourConfig">ConfigNode to use in the generation.</param>
        /// <param name="contractType">ContractType that this behaviour falls under</param>
        /// <param name="behaviourFactory">The BehaviourFactory object.</param>
        /// <returns>Whether the load was successful</returns>
        public static bool GenerateBehaviourFactory(ConfigNode behaviourConfig, ContractType contractType, out BehaviourFactory behaviourFactory)
        {
            // Logging on
            LoggingUtil.CaptureLog = true;
            bool valid = true;

            // Get the type
            string type = behaviourConfig.GetValue("type");
            string name = behaviourConfig.HasValue("name") ? behaviourConfig.GetValue("name") : type;
            if (string.IsNullOrEmpty(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                    "BEHAVIOUR '" + behaviourConfig.GetValue("name") + "' does not specify the mandatory 'type' attribute.");
                behaviourFactory = new InvalidBehaviourFactory();
                valid = false;
            }
            else if (!factories.ContainsKey(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                    "BEHAVIOUR '" + behaviourConfig.GetValue("name") + "' of type '" + behaviourConfig.GetValue("type") + "': " +
                    "Unknown behaviour '" + type + "'.");
                behaviourFactory = new InvalidBehaviourFactory();
                valid = false;
            }
            else
            {
                // Create an instance of the factory
                behaviourFactory = (BehaviourFactory)Activator.CreateInstance(factories[type]);
            }

            // Set attributes
            behaviourFactory.contractType = contractType;
            behaviourFactory.dataNode = new DataNode(name, contractType.dataNode, behaviourFactory);

            // Load config
            valid &= behaviourFactory.Load(behaviourConfig);

            // Check for unexpected values - always do this last
            if (behaviourFactory.GetType() != typeof(InvalidBehaviourFactory))
            {
                valid &= ConfigNodeUtil.ValidateUnexpectedValues(behaviourConfig, behaviourFactory);
            }

            behaviourFactory.enabled = valid;
            behaviourFactory.log = LoggingUtil.capturedLog;
            LoggingUtil.CaptureLog = false;

            return valid;
        }
        public override bool Load(ConfigNode configNode)
        {
            // Load base class
            bool valid = base.Load(configNode);

            // Get type
            string contractType = null;

            valid &= ConfigNodeUtil.ParseValue <string>(configNode, "contractType", x => contractType = x, this);
            if (valid)
            {
                if (ContractType.GetContractType(contractType) != null)
                {
                    ccType = contractType;
                }
                else
                {
                    ccType = null;

                    // Search for the correct type
                    var classes =
                        from assembly in AppDomain.CurrentDomain.GetAssemblies()
                        from type in assembly.GetTypes()
                        where type.IsSubclassOf(typeof(Contract)) && type.Name.Equals(contractType)
                        select type;

                    if (classes.Count() < 1)
                    {
                        valid = false;
                        LoggingUtil.LogError(this.GetType(), "contractType '" + contractType +
                                             "' must either be a Contract sub-class or ContractConfigurator contract type");
                    }
                    else
                    {
                        contractClass = classes.First();
                    }
                }
            }

            valid &= ConfigNodeUtil.ParseValue <uint>(configNode, "minCount", x => minCount = x, this, 1);
            valid &= ConfigNodeUtil.ParseValue <uint>(configNode, "maxCount", x => maxCount = x, this, UInt32.MaxValue);
            valid &= ConfigNodeUtil.ParseValue <Duration>(configNode, "cooldownDuration", x => cooldownDuration = x, this, new Duration(0.0));

            return(valid);
        }
Example #6
0
        protected override void OnLoad(ConfigNode node)
        {
            try
            {
                subType          = node.GetValue("subtype");
                contractType     = string.IsNullOrEmpty(subType) ? null : ContractType.GetContractType(subType);
                title            = ConfigNodeUtil.ParseValue <string>(node, "title", contractType != null ? contractType.title : subType);
                description      = ConfigNodeUtil.ParseValue <string>(node, "description", contractType != null ? contractType.description : "");
                synopsis         = ConfigNodeUtil.ParseValue <string>(node, "synopsis", contractType != null ? contractType.synopsis : "");
                completedMessage = ConfigNodeUtil.ParseValue <string>(node, "completedMessage", contractType != null ? contractType.completedMessage : "");
                notes            = ConfigNodeUtil.ParseValue <string>(node, "notes", contractType != null ? contractType.notes : "");
                hash             = ConfigNodeUtil.ParseValue <int>(node, "hash", contractType != null ? contractType.hash : 0);

                foreach (ConfigNode child in node.GetNodes("BEHAVIOUR"))
                {
                    ContractBehaviour behaviour = ContractBehaviour.LoadBehaviour(child, this);
                    behaviours.Add(behaviour);
                }

                // If the contract type is null, then it likely means that it was uninstalled
                if (contractType == null)
                {
                    LoggingUtil.LogWarning(this, "Error loading contract for contract type '" + subType +
                                           "'.  The contract type either failed to load or was uninstalled.");
                    try
                    {
                        SetState(State.Failed);
                    }
                    catch { }
                    return;
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error loading contract from persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.CONTRACT_LOAD, e, this);

                try
                {
                    SetState(State.Failed);
                }
                catch { }
            }
        }
Example #7
0
 private static void BehaviourGui(ContractType contractType, IEnumerable <BehaviourFactory> behaviourList, int indent)
 {
     foreach (BehaviourFactory behaviour in behaviourList)
     {
         GUILayout.BeginHorizontal(GUILayout.ExpandWidth(false));
         GUILayout.Space(28);
         GUILayout.Label(new GUIContent(new string(' ', indent * 4) + behaviour, DebugInfo(behaviour)),
                         behaviour.enabled ? behaviour.hasWarnings ? yellowLabel : GUI.skin.label : redLabel);
         if (contractType.enabled)
         {
             if (GUILayout.Button(behaviour.enabled ? check : cross, GUILayout.ExpandWidth(false)))
             {
                 behaviour.enabled = !behaviour.enabled;
             }
         }
         GUILayout.EndHorizontal();
     }
 }
Example #8
0
        /// <summary>
        /// Checks if all the given ContractRequirement meet the requirement.
        /// </summary>
        /// <param name="contract">Contract to check</param>
        /// <param name="contractType">Contract type of the contract (in case the contract type has not yet been assigned).</param>
        /// <param name="contractRequirements">The list of requirements to check</param>
        /// <returns>Whether the requirement is met or not.</returns>
        public static bool RequirementsMet(ConfiguredContract contract, ContractType contractType, IEnumerable <ContractRequirement> contractRequirements)
        {
            bool allReqMet = true;

            try
            {
                LoggingUtil.LogVerbose(typeof(ContractRequirement), "Checking requirements for contract '{0}'", contractType.name);
                foreach (ContractRequirement requirement in contractRequirements)
                {
                    if (requirement.enabled)
                    {
                        if (requirement.checkOnActiveContract || contract == null || contract.ContractState != Contract.State.Active)
                        {
                            allReqMet = allReqMet && requirement.CheckRequirement(contract);

                            if (!allReqMet)
                            {
                                LoggingUtil.Log(contract != null && contract.ContractState == Contract.State.Active ? LoggingUtil.LogLevel.INFO :
                                                contract != null && contract.ContractState == Contract.State.Offered ? LoggingUtil.LogLevel.DEBUG : LoggingUtil.LogLevel.VERBOSE,
                                                requirement.GetType(), "Contract {0}: requirement {1} was not met.", contractType.name, requirement.name);
                                break;
                            }
                        }
                    }
                }

                // Force fail the contract if a requirement becomes unmet
                if (contract != null && contract.ContractState == Contract.State.Active && !allReqMet)
                {
                    // Fail the contract - unfortunately, the player won't know why. :(
                    contract.Fail();

                    // Force the stock contracts window to refresh
                    GameEvents.Contract.onContractsLoaded.Fire();
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogException(new Exception("ContractConfigurator: Exception checking requirements!", e));
                return(false);
            }
            return(allReqMet);
        }
        /// <summary>
        /// Checks if the given contract type belongs to the given group
        /// </summary>
        /// <param name="contractType">The contract type to check</param>
        /// <returns>True if the contract type is a part of this group</returns>
        public bool BelongsToGroup(ContractType contractType)
        {
            if (contractType == null)
            {
                return(false);
            }

            ContractGroup group = contractType.group;

            while (group != null)
            {
                if (group.name == name)
                {
                    return(true);
                }
                group = group.parent;
            }

            return(false);
        }
Example #10
0
        static GUIContent CurrencyGUIContent(Currency currency, ContractType contractType, double baseValue)
        {
            // Figure out the multiplier
            double multiplier = 1.0;

            if (contractType.targetBody != null)
            {
                multiplier *= GameVariables.Instance.GetContractDestinationWeight(contractType.targetBody);
            }
            string multInfo = baseValue.ToString("N0") + " (base) * " + multiplier.ToString("F1") + " (body)";

            if (contractType.prestige.Count > 0)
            {
                double val = GameVariables.Instance.GetContractPrestigeFactor(contractType.prestige.First());
                multiplier *= val;
                multInfo   += " * " + val.ToString("F2") + " (prestige)";
            }

            // Get the proper amount, add color
            double adjustedValue = multiplier * baseValue;
            string text          = "<color=#";

            switch (currency)
            {
            case Currency.Funds:
                text += "b4d455";
                break;

            case Currency.Reputation:
                text += "e0d503";
                break;

            case Currency.Science:
                text += "6dcff6";
                break;
            }
            text += ">" + adjustedValue.ToString("N0") + "</color>";

            // Return the gui content
            return(new GUIContent(text, multInfo));
        }
Example #11
0
        private static void RequirementGui(ContractType contractType, IEnumerable <ContractRequirement> requirementList, int indent)
        {
            foreach (ContractRequirement requirement in requirementList)
            {
                GUILayout.BeginHorizontal(GUILayout.ExpandWidth(false));
                GUILayout.Space(28);
                GUIStyle style = requirement.lastResult == null ? GUI.skin.label : requirement.lastResult.Value ? greenLabel : yellowLabel;
                GUILayout.Label(new GUIContent(new string(' ', indent * 4) + requirement, DebugInfo(requirement)),
                                requirement.enabled ? requirement.hasWarnings ? yellowLabel : style : redLabel);
                if (contractType.enabled)
                {
                    if (GUILayout.Button(requirement.enabled ? check : cross, GUILayout.ExpandWidth(false)))
                    {
                        requirement.enabled = !requirement.enabled;
                    }
                }
                GUILayout.EndHorizontal();

                RequirementGui(contractType, requirement.ChildRequirements, indent + 1);
            }
        }
Example #12
0
        private static void ParamGui(ContractType contractType, IEnumerable <ParameterFactory> paramList, int indent)
        {
            foreach (ParameterFactory param in paramList)
            {
                GUILayout.BeginHorizontal(GUILayout.ExpandWidth(false));
                GUILayout.Space(28);
                GUILayout.Label(new GUIContent(new string(' ', indent * 4) + param, DebugInfo(param)),
                                param.enabled ? param.hasWarnings ? yellowLabel : GUI.skin.label : redLabel);
                if (contractType.enabled)
                {
                    if (GUILayout.Button(param.enabled ? check : cross, GUILayout.ExpandWidth(false)))
                    {
                        param.enabled = !param.enabled;
                    }
                }
                GUILayout.EndHorizontal();

                ParamGui(contractType, param.ChildParameters, indent + 1);
                RequirementGui(contractType, param.ChildRequirements, indent + 1);
            }
        }
        protected string ContractTitle()
        {
            string contractTitle;

            if (ccType != null)
            {
                ContractType contractType = ContractType.AllValidContractTypes.Where(ct => ct.name == ccType).FirstOrDefault();
                if (contractType != null)
                {
                    contractTitle = contractType.genericTitle;
                }
                else
                {
                    contractTitle = ccType;
                }
            }
            else
            {
                // TODO - normalize name
                contractTitle = contractClass.Name;
            }

            return(contractTitle);
        }
        public bool Initialize(ContractType contractType)
        {
            LoggingUtil.LogLevel origLogLevel = LoggingUtil.logLevel;
            try
            {
                this.contractType = contractType;
                if (contractType.trace)
                {
                    LoggingUtil.logLevel = LoggingUtil.LogLevel.VERBOSE;
                }

                LoggingUtil.LogDebug(this, "Initializing contract: " + contractType);

                // Set stuff from contract type
                subType = contractType.name;
                hash = contractType.hash;
                AutoAccept = contractType.autoAccept;

                // Set the contract expiry
                if (contractType.maxExpiry == 0.0f)
                {
                    LoggingUtil.LogDebug(this, contractType.name + ": Setting expirty to none");
                    SetExpiry();
                    expiryType = DeadlineType.None;
                }
                else
                {
                    SetExpiry(contractType.minExpiry, contractType.maxExpiry);
                    // Force set the expiry, in stock this is normally done on Contract.Offer()
                    dateExpire = GameTime + TimeExpiry;
                }

                // Set the contract deadline
                if (contractType.deadline == 0.0f)
                {
                    deadlineType = Contract.DeadlineType.None;
                }
                else
                {
                    SetDeadlineDays(contractType.deadline, null);
                }

                // Set rewards
                SetScience(contractType.rewardScience, contractType.targetBody);
                SetReputation(contractType.rewardReputation, contractType.failureReputation, contractType.targetBody);
                SetFunds(contractType.advanceFunds, contractType.rewardFunds, contractType.advanceFunds + contractType.failureFunds, contractType.targetBody);

                // Copy text from contract type
                title = contractType.title;
                synopsis = contractType.synopsis;
                completedMessage = contractType.completedMessage;
                notes = contractType.notes;

                // Set the agent
                if (contractType.agent != null)
                {
                    agent = contractType.agent;
                }
                else
                {
                    agent = AgentList.Instance.GetSuitableAgentForContract(this);
                }

                // Set description
                if (string.IsNullOrEmpty(contractType.description) && agent != null)
                {
                    // Generate the contract description
                    description = TextGen.GenerateBackStories(agent.Name, agent.GetMindsetString(),
                        contractType.topic, contractType.subject, contractType.motivation, random.Next());
                }
                else
                {
                    description = contractType.description;
                }

                // Generate behaviours
                behaviours = new List<ContractBehaviour>();
                if (!contractType.GenerateBehaviours(this))
                {
                    return false;
                }

                // Generate parameters
                bool paramsGenerated = contractType.GenerateParameters(this);
                bodiesLoaded = false;
                contractType.contractBodies = ContractBodies;
                if (!paramsGenerated)
                {
                    return false;
                }

                // Do a very late research bodies check
                try
                {
                    contractType.ResearchBodiesCheck(this);
                }
                catch (ContractRequirementException)
                {
                    return false;
                }

                // Copy in the requirement nodes
                requirements = new List<ContractRequirement>();
                foreach (ContractRequirement requirement in contractType.Requirements)
                {
                    requirements.Add(requirement);
                }

                LoggingUtil.LogDebug(this, "Initialized contract: " + contractType);
                return true;
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error initializing contract " + contractType);
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.CONTRACT_GENERATION, e,
                    contractType == null ? "unknown" : contractType.FullName);

                return false;
            }
            finally
            {
                LoggingUtil.logLevel = origLogLevel;
            }
        }
 /// <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, ContractType contractType)
 {
     return MeetBasicRequirements(contract) && MeetExtendedRequirements(contract, contractType);
 }
Example #16
0
 /// <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, ContractType contractType)
 {
     return(MeetBasicRequirements(contract) && MeetExtendedRequirements(contract, contractType));
 }
Example #17
0
        /// <summary>
        /// Loads the contract type details from the given config node.
        /// </summary>
        /// <param name="configNode">The config node to load from.</param>
        /// <returns>Whether the load was successful.</returns>
        public bool Load(ConfigNode configNode)
        {
            LoggingUtil.LogLevel origLogLevel = LoggingUtil.logLevel;

            try
            {
                // Logging on
                LoggingUtil.CaptureLog = true;
                ConfigNodeUtil.SetCurrentDataNode(null);
                LoggingUtil.LogInfo(this, "Loading CONTRACT_TYPE: '" + name + "'");

                // Clear the config node cache
                ConfigNodeUtil.ClearCache(true);

                // Load values that are immediately required
                bool valid = true;
                valid &= ConfigNodeUtil.ParseValue <ContractGroup>(configNode, "group", x => group = x, this, (ContractGroup)null);

                // Set up the data node
                dataNode = new DataNode(configNode.GetValue("name"), group != null ? group.dataNode : null, this);
                ConfigNodeUtil.SetCurrentDataNode(dataNode);

                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "name", x => name = x, this);

                // Try to turn on trace mode
                valid &= ConfigNodeUtil.ParseValue <bool>(configNode, "trace", x => trace = x, this, false);
                if (trace)
                {
                    LoggingUtil.logLevel = LoggingUtil.LogLevel.VERBOSE;
                    LoggingUtil.LogWarning(this, "Tracing enabled for contract type " + name);
                }

                // Load contract text details
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "title", x => title = x, this);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "tag", x => tag = x, this, "");
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "description", x => description = x, this, (string)null);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "topic", x => topic = x, this, "");
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "subject", x => subject = x, this, "");
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "notes", x => notes = x, this, (string)null);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "synopsis", x => synopsis = x, this);
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "completedMessage", x => completedMessage = x, this);

                if (configNode.HasValue("motivation)"))
                {
                    string motivation;
                    valid &= ConfigNodeUtil.ParseValue <string>(configNode, "motivation", x => motivation = x, this, "");
                    LoggingUtil.LogWarning(this, "The 'motivation' attribute is no longer supported as of Contract Configurator 1.23.0");
                }

                // Load optional attributes
                valid &= ConfigNodeUtil.ParseValue <Agent>(configNode, "agent", x => agent = x, this, group != null ? group.agent : null);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "minExpiry", x => minExpiry = x, this, 5.0f, x => Validation.GE(x, 0.0f));
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "maxExpiry", x => maxExpiry = x, this, 100.0f, x => Validation.GE(x, minExpiry));
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "deadline", x => deadline = x, this, 0.0f, x => Validation.GE(x, 0.0f));
                valid &= ConfigNodeUtil.ParseValue <bool>(configNode, "cancellable", x => cancellable = x, this, true);
                valid &= ConfigNodeUtil.ParseValue <bool>(configNode, "declinable", x => declinable = x, this, true);
                valid &= ConfigNodeUtil.ParseValue <bool>(configNode, "autoAccept", x => autoAccept = x, this, false);
                valid &= ConfigNodeUtil.ParseValue <List <Contract.ContractPrestige> >(configNode, "prestige", x => prestige = x, this, new List <Contract.ContractPrestige>());
                valid &= ConfigNodeUtil.ParseValue <CelestialBody>(configNode, "targetBody", x => targetBody = x, this, (CelestialBody)null);

                valid &= ConfigNodeUtil.ParseValue <int>(configNode, "maxCompletions", x => maxCompletions = x, this, 0, x => Validation.GE(x, 0));
                valid &= ConfigNodeUtil.ParseValue <int>(configNode, "maxSimultaneous", x => maxSimultaneous = x, this, (maxCompletions == 0 ? 4 : 0), x => Validation.GE(x, 0));

                // Load rewards
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "rewardFunds", x => rewardFunds = x, this, 0.0f);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "rewardReputation", x => rewardReputation = x, this, 0.0f);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "rewardScience", x => rewardScience = x, this, 0.0f);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "failureFunds", x => failureFunds = x, this, 0.0f);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "failureReputation", x => failureReputation = x, this, 0.0f);
                valid &= ConfigNodeUtil.ParseValue <float>(configNode, "advanceFunds", x => advanceFunds = x, this, 0.0f);

                // Load other values
                if (configNode.HasValue("weight"))
                {
                    double weight;
                    valid &= ConfigNodeUtil.ParseValue <double>(configNode, "weight", x => weight = x, this);
                    LoggingUtil.LogWarning(this, ErrorPrefix() + ": The weight attribute is deprecated as of Contract Configurator 1.15.0.  Contracts are no longer generated using a weighted system.");
                }

                // Merge in data from the parent contract group
                for (ContractGroup currentGroup = group; currentGroup != null; currentGroup = currentGroup.parent)
                {
                    // Merge dataValues - this is a flag saying what values need to be unique at the contract level
                    foreach (KeyValuePair <string, DataValueInfo> pair in currentGroup.dataValues)
                    {
                        dataValues[currentGroup.name + ":" + pair.Key] = pair.Value;
                    }

                    // Merge uniquenessChecks
                    foreach (KeyValuePair <string, DataNode.UniquenessCheck> pair in currentGroup.uniquenessChecks)
                    {
                        uniquenessChecks[currentGroup.name + ":" + pair.Key] = pair.Value;
                    }
                }

                // Load DATA nodes
                valid &= dataNode.ParseDataNodes(configNode, this, dataValues, uniquenessChecks);

                log = LoggingUtil.capturedLog;
                LoggingUtil.CaptureLog = false;

                // Load parameters
                foreach (ConfigNode contractParameter in ConfigNodeUtil.GetChildNodes(configNode, "PARAMETER"))
                {
                    ParameterFactory paramFactory = null;
                    valid &= ParameterFactory.GenerateParameterFactory(contractParameter, this, out paramFactory);
                    if (paramFactory != null)
                    {
                        paramFactories.Add(paramFactory);
                        if (paramFactory.hasWarnings)
                        {
                            hasWarnings = true;
                        }
                    }
                }

                // Load behaviours
                foreach (ConfigNode requirementNode in ConfigNodeUtil.GetChildNodes(configNode, "BEHAVIOUR"))
                {
                    BehaviourFactory behaviourFactory = null;
                    valid &= BehaviourFactory.GenerateBehaviourFactory(requirementNode, this, out behaviourFactory);
                    if (behaviourFactory != null)
                    {
                        behaviourFactories.Add(behaviourFactory);
                        if (behaviourFactory.hasWarnings)
                        {
                            hasWarnings = true;
                        }
                    }
                }

                // Load requirements
                foreach (ConfigNode requirementNode in ConfigNodeUtil.GetChildNodes(configNode, "REQUIREMENT"))
                {
                    ContractRequirement requirement = null;
                    valid &= ContractRequirement.GenerateRequirement(requirementNode, this, out requirement);
                    if (requirement != null)
                    {
                        requirements.Add(requirement);
                        if (requirement.hasWarnings)
                        {
                            hasWarnings = true;
                        }
                    }
                }

                // Logging on
                LoggingUtil.CaptureLog = true;

                // Check we have at least one valid parameter
                if (paramFactories.Count() == 0)
                {
                    LoggingUtil.LogError(this, ErrorPrefix() + ": Need at least one parameter for a contract!");
                    valid = false;
                }

                ConfigNodeUtil.SetCurrentDataNode(dataNode);

                //
                // Process the DATA_EXPAND nodes - this could cause a restart to the load process
                //
                ConfigNode dataExpandNode = configNode.GetNodes("DATA_EXPAND").FirstOrDefault();
                if (dataExpandNode != null)
                {
                    Type type = null;
                    valid &= ConfigNodeUtil.ParseValue <Type>(dataExpandNode, "type", x => type = x, this);

                    if (type != null)
                    {
                        foreach (ConfigNode.Value pair in dataExpandNode.values)
                        {
                            string key = pair.name;
                            if (key != "type")
                            {
                                object value = null;

                                // Create the setter function
                                Type     actionType = typeof(Action <>).MakeGenericType(type);
                                Delegate del        = Delegate.CreateDelegate(actionType, value, typeof(DataNode).GetMethod("NullAction"));

                                // Set the ParseDataExpandString method generic value
                                MethodInfo method = methodParseExpand.MakeGenericMethod(new Type[] { type });

                                // Invoke the ParseDataExpandString method
                                List <string> values = (List <string>)method.Invoke(this, new object[] { dataExpandNode, key });

                                // Stop at this point if we're invalid
                                if (values == null || !valid)
                                {
                                    if (values == null)
                                    {
                                        LoggingUtil.LogWarning(this, ErrorPrefix() + ": Received an empty list of values when trying to do a DATA_EXPAND");
                                    }
                                    valid = false;
                                    break;
                                }

                                // Expand
                                configNode.RemoveNode(dataExpandNode);
                                foreach (string val in values)
                                {
                                    // Set up for expansion
                                    ConfigNode copy    = configNode.CreateCopy();
                                    string     newName = name + "." + val;
                                    copy.SetValue("name", newName);

                                    // Set up the data node in the copy
                                    ConfigNode dataNode = new ConfigNode("DATA");
                                    copy.AddNode(dataNode);
                                    dataNode.AddValue("type", dataExpandNode.GetValue("type"));
                                    dataNode.AddValue(key, val);

                                    ContractType contractTypeCopy = new ContractType(newName);
                                    contractTypeCopy.Load(copy);
                                }

                                // Remove the original
                                contractTypes.Remove(name);

                                // Don't do any more loading for this one
                                LoggingUtil.LogInfo(this, "Successfully expanded CONTRACT_TYPE '" + name + "'");
                                return(valid);
                            }
                        }
                    }
                }

                //
                // Do the deferred loads
                //
                valid &= ConfigNodeUtil.ExecuteDeferredLoads();

                //
                // Do generic fields that need to happen after deferred loads
                //
                ConfigNodeUtil.SetCurrentDataNode(dataNode);

                // Generic title
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "genericTitle", x => genericTitle = x, this, title);
                if (!configNode.HasValue("genericTitle") && !dataNode.IsDeterministic("title"))
                {
                    LoggingUtil.Log(minVersion >= ContractConfigurator.ENHANCED_UI_VERSION ? LoggingUtil.LogLevel.ERROR : LoggingUtil.LogLevel.WARNING, this,
                                    ErrorPrefix() + ": The field 'genericTitle' is required when the title is not determistic (ie. when expressions are used).");

                    // Error on newer versions of contract packs
                    if (minVersion >= ContractConfigurator.ENHANCED_UI_VERSION)
                    {
                        valid = false;
                    }
                }
                else if (!dataNode.IsDeterministic("genericTitle"))
                {
                    valid = false;
                    LoggingUtil.LogError(this, ErrorPrefix() + ": The field 'genericTitle' must be deterministic.");
                }

                // Generic description
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "genericDescription", x => genericDescription = x, this, description);
                if (!configNode.HasValue("genericDescription") && !dataNode.IsDeterministic("description"))
                {
                    LoggingUtil.Log(minVersion >= ContractConfigurator.ENHANCED_UI_VERSION ? LoggingUtil.LogLevel.ERROR : LoggingUtil.LogLevel.WARNING, this,
                                    ErrorPrefix() + ": The field 'genericDescription' is required when the description is not determistic (ie. when expressions are used).");

                    // Error on newer versions of contract packs
                    if (minVersion >= ContractConfigurator.ENHANCED_UI_VERSION)
                    {
                        valid = false;
                    }
                }
                else if (!dataNode.IsDeterministic("genericDescription"))
                {
                    valid = false;
                    LoggingUtil.LogError(this, ErrorPrefix() + ": The field 'genericDescription' must be deterministic.");
                }

                // Sorting key
                valid &= ConfigNodeUtil.ParseValue <string>(configNode, "sortKey", x => sortKey = x, this, genericTitle);

                // Check for unexpected values - always do this last
                valid &= ConfigNodeUtil.ValidateUnexpectedValues(configNode, this);

                if (valid)
                {
                    LoggingUtil.LogInfo(this, "Successfully loaded CONTRACT_TYPE '" + name + "'");
                }
                else
                {
                    LoggingUtil.LogWarning(this, "Errors encountered while trying to load CONTRACT_TYPE '" + name + "'");
                }
                config  = configNode.ToString();
                hash    = config.GetHashCode();
                enabled = valid;
                log    += LoggingUtil.capturedLog;

                if (LoggingUtil.logLevel >= LoggingUtil.LogLevel.DEBUG)
                {
                    // Get the contract configurator log file
                    string[] dirComponents  = new string[] { KSPUtil.ApplicationRootPath, "GameData", "ContractConfigurator", "log", (group == null ? "!NO_GROUP" : group.Root.name) };
                    string[] pathComponents = dirComponents.Union(new string[] { name + ".log" }).ToArray();
                    string   dir            = string.Join(Path.DirectorySeparatorChar.ToString(), dirComponents);
                    string   path           = string.Join(Path.DirectorySeparatorChar.ToString(), pathComponents);

                    // Delete the file if it exists
                    if (File.Exists(path))
                    {
                        try
                        {
                            File.Delete(path);
                        }
                        catch (Exception e)
                        {
                            LoggingUtil.LogException(new Exception("Exception while attempting to delete the file: " + path, e));
                        }
                    }

                    // Create the directory if it doesn't exist
                    Directory.CreateDirectory(dir);

                    // Now write the config and the cleaned up log to it
                    try
                    {
                        using (StreamWriter sw = File.AppendText(path))
                        {
                            sw.Write("Debug information for CONTRACT_TYPE '" + name + "':\n");
                            sw.Write("\nConfiguration:\n");
                            sw.Write(config);
                            sw.Write("\nData Nodes:\n");
                            sw.Write(DataNodeDebug(dataNode));
                            sw.Write("\nOutput log:\n");
                            sw.Write(log);
                        }
                    }
                    catch
                    {
                        LoggingUtil.LogError(this, "Exception while attempting to write to the file: " + path);
                    }
                }

                return(valid);
            }
            catch (Exception e)
            {
                enabled = false;
                throw new Exception("Error loading CONTRACT_TYPE '" + name + "'", e);
            }
            finally
            {
                LoggingUtil.CaptureLog = false;
                LoggingUtil.logLevel   = origLogLevel;
                loaded = true;
            }
        }
        /// <summary>
        /// Generates a ContractRequirement from a configuration node.
        /// </summary>
        /// <param name="configNode">ConfigNode to use in the generation.</param>
        /// <param name="contractType">ContractType that this requirement falls under</param>
        /// <param name="requirement">The ContractRequirement object.</param>
        /// <returns>Whether the load was successful</returns>
        public static bool GenerateRequirement(ConfigNode configNode, ContractType contractType, out ContractRequirement requirement,
            IContractConfiguratorFactory parent = null)
        {
            // Logging on
            LoggingUtil.CaptureLog = true;
            bool valid = true;

            // Get the type
            string type = configNode.GetValue("type");
            string name = configNode.HasValue("name") ? configNode.GetValue("name") : type;
            if (string.IsNullOrEmpty(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                    "REQUIREMENT '" + configNode.GetValue("name") + "' does not specify the mandatory 'type' attribute.");
                requirement = new InvalidContractRequirement();
                valid = false;
            }
            else if (!requirementTypes.ContainsKey(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                    "REQUIREMENT '" + configNode.GetValue("name") + "' of type '" + configNode.GetValue("type") + "': " +
                    "Unknown requirement '" + type + "'.");
                requirement = new InvalidContractRequirement();
                valid = false;
            }
            else
            {
                // Create an instance of the ContractRequirement
                requirement = (ContractRequirement)Activator.CreateInstance(requirementTypes[type]);
            }

            // Set attributes
            requirement.contractType = contractType;
            requirement.dataNode = new DataNode(name, parent != null ? parent.dataNode : contractType.dataNode, requirement);

            // Load config
            valid &= requirement.Load(configNode);

            // Check for unexpected values - always do this last
            if (requirement.GetType() != typeof(InvalidContractRequirement))
            {
                valid &= ConfigNodeUtil.ValidateUnexpectedValues(configNode, requirement);
            }

            // Load child nodes
            foreach (ConfigNode childNode in ConfigNodeUtil.GetChildNodes(configNode, "REQUIREMENT"))
            {
                ContractRequirement child = null;
                valid &= ContractRequirement.GenerateRequirement(childNode, contractType, out child, requirement);
                if (child != null)
                {
                    requirement.childNodes.Add(child);
                    if (child.hasWarnings)
                    {
                        requirement.hasWarnings = true;
                    }
                }
            }

            requirement.enabled = valid;
            requirement.log = LoggingUtil.capturedLog;
            LoggingUtil.CaptureLog = false;

            return valid;
        }
        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 < 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, contractType.name + " was not generated: basic requirements not met.");
                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 = " + 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, contractType.name + " was not generated: non-deterministic expression failure.");
                        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, contractType.name + " was not generated: requirement not met.");
                if (++contractType.failedGenerationAttempts >= contractType.maxConsecutiveGenerationFailures)
                {
                    contractType.lastGenerationFailure = Time.realtimeSinceStartup;
                }

                OnInitializeFail.Fire();
                yield return null;
            }
        }
        /// <summary>
        /// Generates a ContractRequirement from a configuration node.
        /// </summary>
        /// <param name="configNode">ConfigNode to use in the generation.</param>
        /// <param name="contractType">ContractType that this requirement falls under</param>
        /// <param name="requirement">The ContractRequirement object.</param>
        /// <returns>Whether the load was successful</returns>
        public static bool GenerateRequirement(ConfigNode configNode, ContractType contractType, out ContractRequirement requirement,
            IContractConfiguratorFactory parent = null)
        {
            // Logging on
            LoggingUtil.CaptureLog = true;
            bool valid = true;

            // Get the type
            string type = configNode.GetValue("type");
            string name = configNode.HasValue("name") ? configNode.GetValue("name") : type;
            if (string.IsNullOrEmpty(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                    "REQUIREMENT '" + configNode.GetValue("name") + "' does not specify the mandatory 'type' attribute.");
                requirement = new InvalidContractRequirement();
                valid = false;
            }
            else if (!requirementTypes.ContainsKey(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                    "REQUIREMENT '" + configNode.GetValue("name") + "' of type '" + configNode.GetValue("type") + "': " +
                    "Unknown requirement '" + type + "'.");
                requirement = new InvalidContractRequirement();
                valid = false;
            }
            else
            {
                // Create an instance of the ContractRequirement
                requirement = (ContractRequirement)Activator.CreateInstance(requirementTypes[type]);
            }

            // Set attributes
            requirement.contractType = contractType;
            requirement.dataNode = new DataNode(name, parent != null ? parent.dataNode : contractType.dataNode, requirement);

            // Load config
            valid &= requirement.LoadFromConfig(configNode);

            // Override the needsTitle if we have a parent node with hideChildren
            ContractRequirement parentRequirement = parent as ContractRequirement;
            if (parentRequirement != null)
            {
                if (parentRequirement.hideChildren)
                {
                    requirement.hideChildren = true;
                    requirement.needsTitle = false;
                }
            }

            // Check for unexpected values - always do this last
            if (requirement.GetType() != typeof(InvalidContractRequirement))
            {
                valid &= ConfigNodeUtil.ValidateUnexpectedValues(configNode, requirement);
            }

            // Load child nodes
            foreach (ConfigNode childNode in ConfigNodeUtil.GetChildNodes(configNode, "REQUIREMENT"))
            {
                ContractRequirement child = null;
                valid &= ContractRequirement.GenerateRequirement(childNode, contractType, out child, requirement);
                if (child != null)
                {
                    requirement.childNodes.Add(child);
                    if (child.hasWarnings)
                    {
                        requirement.hasWarnings = true;
                    }
                }
            }

            // Error for missing title
            if (requirement.needsTitle && string.IsNullOrEmpty(requirement.title))
            {
                valid = contractType.minVersion < ContractConfigurator.ENHANCED_UI_VERSION;
                LoggingUtil.Log(contractType.minVersion >= ContractConfigurator.ENHANCED_UI_VERSION ? LoggingUtil.LogLevel.ERROR : LoggingUtil.LogLevel.WARNING,
                    requirement, requirement.ErrorPrefix(configNode) + ": missing required attribute 'title'.");
            }

            requirement.enabled = valid;
            requirement.log = LoggingUtil.capturedLog;
            LoggingUtil.CaptureLog = false;

            return valid;
        }
Example #21
0
        protected override void OnLoad(ConfigNode node)
        {
            try
            {
                subType          = node.GetValue("subtype");
                contractType     = ContractType.GetContractType(subType);
                title            = ConfigNodeUtil.ParseValue <string>(node, "title", contractType != null ? contractType.title : subType);
                description      = ConfigNodeUtil.ParseValue <string>(node, "description", contractType != null ? contractType.description : "");
                synopsis         = ConfigNodeUtil.ParseValue <string>(node, "synopsis", contractType != null ? contractType.synopsis : "");
                completedMessage = ConfigNodeUtil.ParseValue <string>(node, "completedMessage", contractType != null ? contractType.completedMessage : "");
                notes            = ConfigNodeUtil.ParseValue <string>(node, "notes", contractType != null ? contractType.notes : "");
                hash             = ConfigNodeUtil.ParseValue <int>(node, "hash", contractType != null ? contractType.hash : 0);
                targetBody       = ConfigNodeUtil.ParseValue <CelestialBody>(node, "targetBody", null);

                // Load the unique data
                ConfigNode dataNode = node.GetNode("UNIQUE_DATA");
                if (dataNode != null)
                {
                    // Handle individual values
                    foreach (ConfigNode.Value pair in dataNode.values)
                    {
                        string typeName = pair.value.Remove(pair.value.IndexOf(":"));
                        string value    = pair.value.Substring(typeName.Length + 1);
                        Type   type     = ConfigNodeUtil.ParseTypeValue(typeName);

                        // Prevents issues with vessels not getting loaded in some scenes (ie. VAB)
                        if (type == typeof(Vessel))
                        {
                            type = typeof(Guid);
                        }

                        if (type == typeof(string))
                        {
                            uniqueData[pair.name] = value;
                        }
                        else
                        {
                            // Get the ParseValue method
                            MethodInfo parseValueMethod = typeof(ConfigNodeUtil).GetMethods().Where(m => m.Name == "ParseSingleValue").Single();
                            parseValueMethod = parseValueMethod.MakeGenericMethod(new Type[] { type });

                            // Invoke the ParseValue method
                            uniqueData[pair.name] = parseValueMethod.Invoke(null, new object[] { pair.name, value, false });
                        }
                    }
                }

                foreach (ConfigNode child in node.GetNodes("BEHAVIOUR"))
                {
                    ContractBehaviour behaviour = ContractBehaviour.LoadBehaviour(child, this);
                    behaviours.Add(behaviour);
                }

                foreach (ConfigNode child in node.GetNodes("REQUIREMENT"))
                {
                    ContractRequirement requirement = ContractRequirement.LoadRequirement(child);
                    requirements.Add(requirement);
                }

                // If the contract type is null, then it likely means that it was uninstalled
                if (contractType == null)
                {
                    LoggingUtil.LogWarning(this, "Error loading contract for contract type '" + subType +
                                           "'.  The contract type either failed to load or was uninstalled.");
                    try
                    {
                        if (ContractState == State.Active || ContractState == State.Offered)
                        {
                            SetState(ContractState == State.Active ? State.Failed : State.Withdrawn);
                        }
                    }
                    catch { }
                    return;
                }

                OnContractLoaded.Fire(this);
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error loading contract from persistance file!");
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.CONTRACT_LOAD, e, this);

                try
                {
                    SetState(State.Failed);
                }
                catch { }
            }
        }
Example #22
0
        public bool Initialize(ContractType contractType)
        {
            LoggingUtil.LogLevel origLogLevel = LoggingUtil.logLevel;
            try
            {
                this.contractType = contractType;
                if (contractType.trace)
                {
                    LoggingUtil.logLevel = LoggingUtil.LogLevel.VERBOSE;
                }

                LoggingUtil.LogDebug(this, "Initializing contract: " + contractType);

                // Set stuff from contract type
                subType    = contractType.name;
                hash       = contractType.hash;
                AutoAccept = contractType.autoAccept;

                // Set the contract expiry
                if (contractType.maxExpiry == 0.0f)
                {
                    LoggingUtil.LogDebug(this, contractType.name + ": Setting expirty to none");
                    SetExpiry();
                    expiryType = DeadlineType.None;
                }
                else
                {
                    SetExpiry(contractType.minExpiry, contractType.maxExpiry);
                    // Force set the expiry, in stock this is normally done on Contract.Offer()
                    dateExpire = GameTime + TimeExpiry;
                }

                // Set the contract deadline
                if (contractType.deadline == 0.0f)
                {
                    deadlineType = Contract.DeadlineType.None;
                }
                else
                {
                    SetDeadlineDays(contractType.deadline, null);
                }

                // Set rewards
                SetScience(contractType.rewardScience, contractType.targetBody);
                SetReputation(contractType.rewardReputation, contractType.failureReputation, contractType.targetBody);
                SetFunds(contractType.advanceFunds, contractType.rewardFunds, contractType.advanceFunds + contractType.failureFunds, contractType.targetBody);

                // Copy text from contract type
                title            = contractType.title;
                synopsis         = contractType.synopsis;
                completedMessage = contractType.completedMessage;
                notes            = contractType.notes;

                // Set the agent
                if (contractType.agent != null)
                {
                    agent = contractType.agent;
                }
                else
                {
                    agent = AgentList.Instance.GetSuitableAgentForContract(this);
                }

                // Set description
                if (string.IsNullOrEmpty(contractType.description) && agent != null)
                {
                    // Generate the contract description
                    description = TextGen.GenerateBackStories("ConfiguredContract", agent.Name, contractType.topic, contractType.subject, random.Next(), true, true, true);
                }
                else
                {
                    description = contractType.description;
                }

                // Generate behaviours
                behaviours = new List <ContractBehaviour>();
                if (!contractType.GenerateBehaviours(this))
                {
                    return(false);
                }

                // Generate parameters
                bool paramsGenerated = contractType.GenerateParameters(this);
                bodiesLoaded = false;
                contractType.contractBodies = ContractBodies;
                if (!paramsGenerated)
                {
                    return(false);
                }

                // Do a very late research bodies check
                try
                {
                    contractType.ResearchBodiesCheck(this);
                }
                catch (ContractRequirementException)
                {
                    return(false);
                }

                // Copy in the requirement nodes
                requirements = new List <ContractRequirement>();
                foreach (ContractRequirement requirement in contractType.Requirements)
                {
                    requirements.Add(requirement);
                }

                LoggingUtil.LogDebug(this, "Initialized contract: " + contractType);
                return(true);
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error initializing contract " + contractType);
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.CONTRACT_GENERATION, e,
                                                         contractType == null ? "unknown" : contractType.FullName);

                return(false);
            }
            finally
            {
                LoggingUtil.logLevel = origLogLevel;
            }
        }
Example #23
0
        private bool SelectContractType()
        {
            if (!lastSpecificGenerationFailure.ContainsKey(prestige))
            {
                lastSpecificGenerationFailure[prestige] = 0;
            }

            LoggingUtil.LogVerbose(this, "Generating a contract for prestige = " + prestige);

            // Loop through all the contract groups
            IEnumerable <ContractGroup> groups = ContractGroup.AllGroups;

            foreach (ContractGroup group in groups.Skip(nextGroup).Concat(groups.Take(nextGroup)))
            {
                LoggingUtil.LogVerbose(this, "Looking at group " + group);
                nextGroup = (nextGroup + 1) % groups.Count();

                // Build a weighted list of ContractTypes to choose from
                Dictionary <ContractType, double> validContractTypes = new Dictionary <ContractType, double>();
                double totalWeight = 0.0;
                foreach (ContractType ct in ContractType.AllValidContractTypes.Where(ct => ct.group == group))
                {
                    LoggingUtil.LogVerbose(this, "Checking ContractType = " + ct.name);
                    // KSP tries to generate new contracts *incessantly*, to the point where this becomes
                    // a real performance problem.  So if we run into a situation where we did not
                    // generate a contract and we are asked AGAIN after a very short time, then do
                    // some logic to prevent re-checking uselessly.

                    // If there was any generation failure within the last 100 frames, only look at
                    // contracts specific to that prestige level
                    if (lastGenerationFailure + 100 > Time.frameCount)
                    {
                        // If there was a generation failure for this specific prestige level in
                        // the last 100 frames, then just skip the checks entirely
                        if (lastSpecificGenerationFailure[prestige] + 100 > Time.frameCount)
                        {
                            return(false);
                        }
                    }

                    // Only select contracts with the correct prestige level
                    if (ct.prestige.Count == 0 || ct.prestige.Contains(prestige))
                    {
                        validContractTypes.Add(ct, ct.weight);
                        totalWeight += ct.weight;
                    }
                }

                // Loop until we either run out of contracts in our list or make a selection
                System.Random generator = new System.Random(this.MissionSeed);
                while (validContractTypes.Count > 0)
                {
                    ContractType selectedContractType = null;
                    // Pick one of the contract types based on their weight
                    double value = generator.NextDouble() * totalWeight;
                    foreach (KeyValuePair <ContractType, double> pair in validContractTypes)
                    {
                        value -= pair.Value;
                        if (value <= 0.0)
                        {
                            selectedContractType = pair.Key;
                            break;
                        }
                    }

                    // Shouldn't happen, but floating point rounding could put us here
                    if (selectedContractType == null)
                    {
                        selectedContractType = validContractTypes.First().Key;
                    }

                    // Try to refresh non-deterministic values before we check requirements
                    currentContract = this;
                    LoggingUtil.LogVerbose(this, "Refresh non-deterministic values for CONTRACT_TYPE = " + selectedContractType.name);
                    if (!ConfigNodeUtil.UpdateNonDeterministicValues(selectedContractType.dataNode))
                    {
                        LoggingUtil.LogVerbose(this, selectedContractType.name + " was not generated: non-deterministic expression failure.");
                        validContractTypes.Remove(selectedContractType);
                        totalWeight -= selectedContractType.weight;
                    }
                    currentContract = null;

                    // Check the requirements for our selection
                    if (selectedContractType.MeetRequirements(this))
                    {
                        contractType = selectedContractType;
                        subType      = contractType.name;
                        return(true);
                    }
                    // Remove the selection, and try again
                    else
                    {
                        LoggingUtil.LogVerbose(this, selectedContractType.name + " was not generated: requirement not met.");
                        validContractTypes.Remove(selectedContractType);
                        totalWeight -= selectedContractType.weight;
                    }
                }
            }

            // Set our failure markers
            lastGenerationFailure = Time.frameCount;
            lastSpecificGenerationFailure[prestige] = Time.frameCount;

            return(false);
        }
Example #24
0
 /// <summary>
 /// Clears the contract configuration.
 /// </summary>
 void ClearContractConfig()
 {
     ContractGroup.contractGroups.Clear();
     ContractType.ClearContractTypes();
     totalContracts = successContracts = attemptedContracts = 0;
 }
        /// <summary>
        /// Generates a new ParameterFactory from the given ConfigNode.
        /// </summary>
        /// <param name="parameterConfig">ConfigNode to use in the generation.</param>
        /// <param name="contractType">ContractType that this parameter factory falls under</param>
        /// <param name="paramFactory">The ParameterFactory object.</param>
        /// <param name="parent">ParameterFactory to use as the parent</param>
        /// <returns>Whether the load was successful</returns>
        public static bool GenerateParameterFactory(ConfigNode parameterConfig, ContractType contractType, out ParameterFactory paramFactory, ParameterFactory parent = null)
        {
            // Logging on
            LoggingUtil.CaptureLog = true;
            bool valid = true;

            // Get the type
            string type = parameterConfig.GetValue("type");
            string name = parameterConfig.HasValue("name") ? parameterConfig.GetValue("name") : type;
            if (string.IsNullOrEmpty(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                    "PARAMETER '" + parameterConfig.GetValue("name") + "' does not specify the mandatory 'type' attribute.");
                paramFactory = new InvalidParameterFactory();
                valid = false;
            }
            else if (!factories.ContainsKey(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                    "PARAMETER '" + parameterConfig.GetValue("name") + "' of type '" + parameterConfig.GetValue("type") + "': " +
                    "Unknown parameter '" + type + "'.");
                paramFactory = new InvalidParameterFactory();
                valid = false;
            }
            else
            {
                // Create an instance of the factory
                paramFactory = (ParameterFactory)Activator.CreateInstance(factories[type]);
            }

            // Set attributes
            paramFactory.parent = parent;
            paramFactory.contractType = contractType;
            paramFactory.dataNode = new DataNode(name, parent != null ? parent.dataNode : contractType.dataNode, paramFactory);

            // Load child requirements
            foreach (ConfigNode childNode in ConfigNodeUtil.GetChildNodes(parameterConfig, "REQUIREMENT"))
            {
                ContractRequirement req = null;
                valid &= ContractRequirement.GenerateRequirement(childNode, contractType, out req, paramFactory);
                if (req != null)
                {
                    paramFactory.requirements.Add(req);
                    if (req.hasWarnings)
                    {
                        paramFactory.hasWarnings = true;
                    }
                }
            }

            // Load config
            if (!paramFactory.Load(parameterConfig))
            {
                // If there was a load failure, check if there are requirements
                if (paramFactory.requirements.Count > 0)
                {
                    LoggingUtil.LogWarning(paramFactory, "Ignoring failed parameter with child requirements.");
                }
                else
                {
                    valid = false;
                }
            }

            // Check for unexpected values - always do this last
            if (paramFactory.GetType() != typeof(InvalidParameterFactory))
            {
                valid &= ConfigNodeUtil.ValidateUnexpectedValues(parameterConfig, paramFactory);
            }

            paramFactory.log = LoggingUtil.capturedLog;
            LoggingUtil.CaptureLog = false;

            // Load child nodes
            foreach (ConfigNode childNode in ConfigNodeUtil.GetChildNodes(parameterConfig, "PARAMETER"))
            {
                ParameterFactory child = null;
                valid &= ParameterFactory.GenerateParameterFactory(childNode, contractType, out child, paramFactory);
                if (child != null)
                {
                    paramFactory.childNodes.Add(child);
                    if (child.hasWarnings)
                    {
                        paramFactory.hasWarnings = true;
                    }
                }
            }

            paramFactory.enabled = valid;

            return valid;
        }
        /// <summary>
        /// Checks if the given contract type belongs to the given group
        /// </summary>
        /// <param name="contractType">The contract type to check</param>
        /// <returns>True if the contract type is a part of this group</returns>
        public bool BelongsToGroup(ContractType contractType)
        {
            if (contractType == null)
            {
                return false;
            }

            ContractGroup group = contractType.group;
            while (group != null)
            {
                if (group.name == name)
                {
                    return true;
                }
                group = group.parent;
            }

            return false;
        }
        /// <summary>
        /// Loads all the contact type nodes and creates ContractType objects.
        /// </summary>
        private IEnumerator <YieldInstruction> LoadContractTypeConfig()
        {
            LoggingUtil.LogDebug(this, "Loading CONTRACT_TYPE nodes.");
            ConfigNode[] contractConfigs = GameDatabase.Instance.GetConfigNodes("CONTRACT_TYPE");
            totalContracts = contractConfigs.Count();

            // First pass - create all the ContractType objects
            foreach (ConfigNode contractConfig in contractConfigs)
            {
                // Create the initial contract type
                LoggingUtil.LogVerbose(this, "Pre-load for node: '" + contractConfig.GetValue("name") + "'");
                try
                {
                    ContractType contractType = new ContractType(contractConfig.GetValue("name"));
                }
                catch (ArgumentException)
                {
                    LoggingUtil.LogError(this, "Couldn't load CONTRACT_TYPE '" + contractConfig.GetValue("name") + "' due to a duplicate name.");
                }
            }

            // Second pass - do the actual loading of details
            foreach (ConfigNode contractConfig in contractConfigs)
            {
                attemptedContracts++;
                if (reloading)
                {
                    yield return(new WaitForEndOfFrame());
                }

                // Fetch the contractType
                string       name         = contractConfig.GetValue("name");
                ContractType contractType = ContractType.GetContractType(name);
                if (contractType != null && !contractType.loaded)
                {
                    // Perform the load
                    try
                    {
                        contractType.Load(contractConfig);
                        if (contractType.enabled)
                        {
                            successContracts++;
                        }
                    }
                    catch (Exception e)
                    {
                        LoggingUtil.LogException(e);
                    }
                }
            }

            LoggingUtil.LogInfo(this, "Loaded " + successContracts + " out of " + totalContracts + " CONTRACT_TYPE nodes.");

            // Check for empty groups and warn
            foreach (ContractGroup group in ContractGroup.contractGroups.Values.Where(g => g != null))
            {
                group.CheckEmpty();
            }

            // Load other things
            MissionControlUI.GroupContainer.LoadConfig();

            if (!reloading && LoggingUtil.logLevel == LoggingUtil.LogLevel.DEBUG || LoggingUtil.logLevel == LoggingUtil.LogLevel.VERBOSE)
            {
                ScreenMessages.PostScreenMessage("Contract Configurator: Loaded " + successContracts + " out of " + totalContracts
                                                 + " contracts successfully.", 5, ScreenMessageStyle.UPPER_CENTER);
            }
        }
Example #28
0
        /*
         * Generates a new ParameterFactory from the given ConfigNode.
         */
        public static ParameterFactory GenerateParameterFactory(ConfigNode parameterConfig, ContractType contractType)
        {
            // Get the type
            string type = parameterConfig.GetValue("type");

            if (!factories.ContainsKey(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                                     "PARAMETER '" + parameterConfig.GetValue("name") + "' of type '" + parameterConfig.GetValue("type") + "': " +
                                     "No ParameterFactory has been registered for type '" + type + "'.");
                return(null);
            }

            // Create an instance of the factory
            ParameterFactory paramFactory = (ParameterFactory)Activator.CreateInstance(factories[type]);

            // Set attributes
            paramFactory.contractType = contractType;

            // Load config
            bool valid = paramFactory.Load(parameterConfig);

            // Check for unexpected values - always do this last
            valid &= ConfigNodeUtil.ValidateUnexpectedValues(parameterConfig, paramFactory);

            return(valid ? paramFactory : null);
        }
        /// <summary>
        /// Checks if all the given ContractRequirement meet the requirement.
        /// </summary>
        /// <param name="contract">Contract to check</param>
        /// <param name="contractType">Contract type of the contract (in case the contract type has not yet been assigned).</param>
        /// <param name="contractRequirements">The list of requirements to check</param>
        /// <returns>Whether the requirement is met or not.</returns>
        public static bool RequirementsMet(ConfiguredContract contract, ContractType contractType, IEnumerable<ContractRequirement> contractRequirements)
        {
            bool allReqMet = true;
            try
            {
                LoggingUtil.LogVerbose(typeof(ContractRequirement), "Checking requirements for contract '" + contractType.name);
                foreach (ContractRequirement requirement in contractRequirements)
                {
                    if (requirement.enabled)
                    {
                        if (requirement.checkOnActiveContract || contract.ContractState != Contract.State.Active)
                        {
                            allReqMet = allReqMet && requirement.CheckRequirement(contract);

                            if (!allReqMet)
                            {
                                LoggingUtil.Log(contract.ContractState == Contract.State.Active ? LoggingUtil.LogLevel.INFO : LoggingUtil.LogLevel.VERBOSE,
                                    requirement.GetType(), "Contract " + contractType.name + ": requirement " + requirement.name + " was not met.");
                                break;
                            }
                        }
                    }
                }

                // Force fail the contract if a requirement becomes unmet
                if (contract.ContractState == Contract.State.Active && !allReqMet)
                {
                    // Fail the contract - unfortunately, the player won't know why. :(
                    contract.Fail();

                    // Force the stock contracts window to refresh
                    GameEvents.Contract.onContractsLoaded.Fire();
                }
            }
            catch (Exception e)
            {
                LoggingUtil.LogException(new Exception("ContractConfigurator: Exception checking requirements!", e));
                return false;
            }
            return allReqMet;
        }
Example #30
0
        /// <summary>
        /// Generates a ContractRequirement from a configuration node.
        /// </summary>
        /// <param name="configNode">ConfigNode to use in the generation.</param>
        /// <param name="contractType">ContractType that this requirement falls under</param>
        /// <param name="requirement">The ContractRequirement object.</param>
        /// <returns>Whether the load was successful</returns>
        public static bool GenerateRequirement(ConfigNode configNode, ContractType contractType, out ContractRequirement requirement,
                                               IContractConfiguratorFactory parent = null)
        {
            // Logging on
            LoggingUtil.CaptureLog = true;
            bool valid = true;

            // Get the type
            string type = configNode.GetValue("type");
            string name = configNode.HasValue("name") ? configNode.GetValue("name") : type;

            if (string.IsNullOrEmpty(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '{0}', REQUIREMENT '{1}' does not specify the mandatory 'type' attribute.",
                                     contractType.name, configNode.GetValue("name"));
                requirement = new InvalidContractRequirement();
                valid       = false;
            }
            else if (!requirementTypes.ContainsKey(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '{0}', REQUIREMENT '{1}' of type '{2}': Unknown requirement '{3}'.",
                                     contractType.name, configNode.GetValue("name"), configNode.GetValue("type"), type);
                requirement = new InvalidContractRequirement();
                valid       = false;
            }
            else
            {
                // Create an instance of the ContractRequirement
                requirement = (ContractRequirement)Activator.CreateInstance(requirementTypes[type]);
            }

            // Set attributes
            requirement.contractType = contractType;
            requirement.dataNode     = new DataNode(name, parent != null ? parent.dataNode : contractType.dataNode, requirement);

            // Load config
            valid &= requirement.LoadFromConfig(configNode);

            // Override the needsTitle if we have a parent node with hideChildren
            ContractRequirement parentRequirement = parent as ContractRequirement;

            if (parentRequirement != null)
            {
                if (parentRequirement.hideChildren)
                {
                    requirement.hideChildren = true;
                    requirement.needsTitle   = false;
                }
            }

            // Check for unexpected values - always do this last
            if (requirement.GetType() != typeof(InvalidContractRequirement))
            {
                valid &= ConfigNodeUtil.ValidateUnexpectedValues(configNode, requirement);
            }

            // Load child nodes
            foreach (ConfigNode childNode in ConfigNodeUtil.GetChildNodes(configNode, "REQUIREMENT"))
            {
                ContractRequirement child = null;
                valid &= ContractRequirement.GenerateRequirement(childNode, contractType, out child, requirement);
                if (child != null)
                {
                    requirement.childNodes.Add(child);
                    if (child.hasWarnings)
                    {
                        requirement.hasWarnings = true;
                    }
                }
            }

            // Error for missing title
            if (requirement.needsTitle && string.IsNullOrEmpty(requirement.title))
            {
                valid = contractType.minVersion < ContractConfigurator.ENHANCED_UI_VERSION;
                LoggingUtil.Log(contractType.minVersion >= ContractConfigurator.ENHANCED_UI_VERSION ? LoggingUtil.LogLevel.ERROR : LoggingUtil.LogLevel.WARNING,
                                requirement, "{0}: missing required attribute 'title'.", requirement.ErrorPrefix(configNode));
            }

            requirement.enabled    = valid;
            requirement.log        = LoggingUtil.capturedLog;
            LoggingUtil.CaptureLog = false;

            return(valid);
        }
        public IEnumerable<ConfiguredContract> PendingContracts(ContractType type, Contract.ContractPrestige? prestige = null)
        {
            if (type == null)
            {
                return Enumerable.Empty<ConfiguredContract>();
            }

            return contractDetails.SelectMany(p => p.Value.contracts).Union(priorityContracts).
                Where(c => c.contractType == type && (prestige == null || prestige == c.Prestige));
        }
Example #32
0
        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);
            }
        }
Example #33
0
        /// <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;
            }
        }
Example #34
0
        /// <summary>
        /// Generates a ContractRequirement from a configuration node.
        /// </summary>
        /// <param name="configNode">ConfigNode to use in the generation.</param>
        /// <param name="contractType">ContractType that this requirement falls under</param>
        /// <param name="requirement">The ContractRequirement object.</param>
        /// <returns>Whether the load was successful</returns>
        public static bool GenerateRequirement(ConfigNode configNode, ContractType contractType, out ContractRequirement requirement,
                                               IContractConfiguratorFactory parent = null)
        {
            // Logging on
            LoggingUtil.CaptureLog = true;
            bool valid = true;

            // Get the type
            string type = configNode.GetValue("type");
            string name = configNode.HasValue("name") ? configNode.GetValue("name") : type;

            if (string.IsNullOrEmpty(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                                     "REQUIREMENT '" + configNode.GetValue("name") + "' does not specify the mandatory 'type' attribute.");
                requirement = new InvalidContractRequirement();
                valid       = false;
            }
            else if (!requirementTypes.ContainsKey(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                                     "REQUIREMENT '" + configNode.GetValue("name") + "' of type '" + configNode.GetValue("type") + "': " +
                                     "No ContractRequirement has been registered for type '" + type + "'.");
                requirement = new InvalidContractRequirement();
                valid       = false;
            }
            else
            {
                // Create an instance of the ContractRequirement
                requirement = (ContractRequirement)Activator.CreateInstance(requirementTypes[type]);
            }

            // Set attributes
            requirement.contractType = contractType;
            requirement.dataNode     = new DataNode(name, parent != null ? parent.dataNode : contractType.dataNode, requirement);

            // Load config
            valid &= requirement.Load(configNode);

            // Check for unexpected values - always do this last
            if (requirement.GetType() != typeof(InvalidContractRequirement))
            {
                valid &= ConfigNodeUtil.ValidateUnexpectedValues(configNode, requirement);
            }

            // Load child nodes
            foreach (ConfigNode childNode in ConfigNodeUtil.GetChildNodes(configNode, "REQUIREMENT"))
            {
                ContractRequirement child = null;
                valid &= ContractRequirement.GenerateRequirement(childNode, contractType, out child, requirement);
                if (child != null)
                {
                    requirement.childNodes.Add(child);
                    if (child.hasWarnings)
                    {
                        requirement.hasWarnings = true;
                    }
                }
            }

            requirement.enabled    = valid;
            requirement.log        = LoggingUtil.capturedLog;
            LoggingUtil.CaptureLog = false;

            return(valid);
        }
        /// <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 special values are not null
                if (contract.contractType == null)
                {
                    foreach (KeyValuePair<string, bool> pair in dataValues)
                    {
                        // Only check if it is a required value
                        if (pair.Value)
                        {
                            string name = pair.Key;

                            if (!dataNode.IsInitialized(name))
                            {
                                throw new ContractRequirementException("'" + name + "' was not initialized.");
                            }

                            object o = dataNode[name];
                            if (o == null)
                            {
                                throw new ContractRequirementException("'" + name + "' was null.");
                            }
                            else if (o == typeof(List<>))
                            {
                                PropertyInfo prop = o.GetType().GetProperty("Count");
                                int count = (int)prop.GetValue(o, null);
                                if (count == 0)
                                {
                                    throw new ContractRequirementException("'" + name + "' had zero count.");
                                }
                            }
                            else if (o == typeof(Vessel))
                            {
                                Vessel v = (Vessel)o;

                                if (v.state == Vessel.State.DEAD)
                                {
                                    throw new ContractRequirementException("Vessel '" + v.vesselName + "' is dead.");
                                }
                            }
                        }
                    }
                }

                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 = ContractSystem.Instance.Contracts.OfType<ConfiguredContract>().
                            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));
                        }

                        // Special case for pre-loader contracts
                        if (contract.ContractState == Contract.State.Withdrawn)
                        {
                            contractList = contractList.Union(ContractPreLoader.Instance.PendingContracts(this, contract.Prestige).
                                Where(c => c != null && c != contract && c.contractType != null));
                        }

                        // Fileter 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, 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 : LoggingUtil.LogLevel.VERBOSE;
                string prefix = contract.contractType != null ? "Cancelling contract of type " + name + " (" + contract.Title + "): " :
                    "Didn't generate contract 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;
            }
        }
 private static void BehaviourGui(ContractType contractType, IEnumerable<BehaviourFactory> behaviourList, int indent)
 {
     foreach (BehaviourFactory behaviour in behaviourList)
     {
         GUILayout.BeginHorizontal(GUILayout.ExpandWidth(false));
         GUILayout.Space(28);
         GUILayout.Label(new GUIContent(new string(' ', indent * 4) + behaviour, DebugInfo(behaviour)),
             behaviour.enabled ? behaviour.hasWarnings ? yellowLabel : GUI.skin.label : redLabel);
         if (contractType.enabled)
         {
             if (GUILayout.Button(behaviour.enabled ? check : cross, GUILayout.ExpandWidth(false)))
             {
                 behaviour.enabled = !behaviour.enabled;
             }
         }
         GUILayout.EndHorizontal();
     }
 }
Example #37
0
        /*
         * Generates a new BehaviourFactory from the given ConfigNode.
         */
        public static BehaviourFactory GenerateBehaviourFactory(ConfigNode behaviourConfig, ContractType contractType)
        {
            // Get the type
            string type = behaviourConfig.GetValue("type");

            if (!factories.ContainsKey(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                                     "BEHAVIOUR '" + behaviourConfig.GetValue("name") + "' of type '" + behaviourConfig.GetValue("type") + "': " +
                                     "No BehaviourFactory has been registered for type '" + type + "'.");
                return(null);
            }

            // Create an instance of the factory
            BehaviourFactory behaviourFactory = (BehaviourFactory)Activator.CreateInstance(factories[type]);

            // Set attributes
            behaviourFactory.contractType = contractType;
            behaviourFactory.targetBody   = contractType.targetBody;

            // Load config
            bool valid = behaviourFactory.Load(behaviourConfig);

            // Check for unexpected values - always do this last
            valid &= ConfigNodeUtil.ValidateUnexpectedValues(behaviourConfig, behaviourFactory);

            return(valid ? behaviourFactory : null);
        }
        static GUIContent CurrencyGUIContent(Currency currency, ContractType contractType, double baseValue)
        {
            // Figure out the multiplier
            double multiplier = 1.0;
            if (GameVariables.Instance != null && contractType.targetBody != null)
            {
                multiplier *= GameVariables.Instance.GetContractDestinationWeight(contractType.targetBody);
            }
            string multInfo = baseValue.ToString("N0") + " (base) * " + multiplier.ToString("F1") + " (body)";
            if (GameVariables.Instance != null && contractType.prestige.Count > 0)
            {
                double val = GameVariables.Instance.GetContractPrestigeFactor(contractType.prestige.First());
                multiplier *= val;
                multInfo += " * " + val.ToString("F2") + " (prestige)";
            }

            // Get the proper amount, add color
            double adjustedValue = multiplier * baseValue;
            string text = "<color=#";
            switch (currency)
            {
                case Currency.Funds:
                    text += "b4d455";
                    break;
                case Currency.Reputation:
                    text += "e0d503";
                    break;
                case Currency.Science:
                    text += "6dcff6";
                    break;
            }
            text += ">" + adjustedValue.ToString("N0")  + "</color>";

            // Return the gui content
            return new GUIContent(text, multInfo);
        }
        private static void ParamGui(ContractType contractType, IEnumerable<ParameterFactory> paramList, int indent)
        {
            foreach (ParameterFactory param in paramList)
            {
                GUILayout.BeginHorizontal(GUILayout.ExpandWidth(false));
                GUILayout.Space(28);
                GUILayout.Label(new GUIContent(new string(' ', indent * 4) + param, DebugInfo(param)),
                    param.enabled ? param.hasWarnings ? yellowLabel : GUI.skin.label : redLabel);
                if (contractType.enabled)
                {
                    if (GUILayout.Button(param.enabled ? check : cross, GUILayout.ExpandWidth(false)))
                    {
                        param.enabled = !param.enabled;
                    }
                }
                GUILayout.EndHorizontal();

                ParamGui(contractType, param.ChildParameters, indent + 1);
                RequirementGui(contractType, param.ChildRequirements, indent + 1);
            }
        }
        private static void RequirementGui(ContractType contractType, IEnumerable<ContractRequirement> requirementList, int indent)
        {
            foreach (ContractRequirement requirement in requirementList)
            {
                GUILayout.BeginHorizontal(GUILayout.ExpandWidth(false));
                GUILayout.Space(28);
                GUIStyle style = requirement.lastResult == null ? GUI.skin.label : requirement.lastResult.Value ? greenLabel : yellowLabel;
                GUILayout.Label(new GUIContent(new string(' ', indent * 4) + requirement, DebugInfo(requirement)),
                    requirement.enabled ? requirement.hasWarnings ? yellowLabel : style : redLabel);
                if (contractType.enabled)
                {
                    if (GUILayout.Button(requirement.enabled ? check : cross, GUILayout.ExpandWidth(false)))
                    {
                        requirement.enabled = !requirement.enabled;
                    }
                }
                GUILayout.EndHorizontal();

                RequirementGui(contractType, requirement.ChildRequirements, indent + 1);
            }
        }
        public bool Initialize(ContractType contractType)
        {
            LoggingUtil.LogLevel origLogLevel = LoggingUtil.logLevel;
            try
            {
                this.contractType = contractType;
                if (contractType.trace)
                {
                    LoggingUtil.logLevel = LoggingUtil.LogLevel.VERBOSE;
                }

                LoggingUtil.LogDebug(this.GetType(), "Initializing contract: " + contractType);

                // Set stuff from contract type
                subType = contractType.name;
                hash = contractType.hash;
                AutoAccept = contractType.autoAccept;

                // Set the contract expiry
                if (contractType.maxExpiry == 0.0f)
                {
                    SetExpiry();
                    expiryType = DeadlineType.None;
                }
                else
                {
                    SetExpiry(contractType.minExpiry, contractType.maxExpiry);
                }

                // Set the contract deadline
                if (contractType.deadline == 0.0f)
                {
                    deadlineType = Contract.DeadlineType.None;
                }
                else
                {
                    SetDeadlineDays(contractType.deadline, null);
                }

                // Set rewards
                SetScience(contractType.rewardScience, contractType.targetBody);
                SetReputation(contractType.rewardReputation, contractType.failureReputation, contractType.targetBody);
                SetFunds(contractType.advanceFunds, contractType.rewardFunds, contractType.failureFunds, contractType.targetBody);

                // Copy text from contract type
                title = contractType.title;
                synopsis = contractType.synopsis;
                completedMessage = contractType.completedMessage;
                notes = contractType.notes;

                // Set the agent
                if (contractType.agent != null)
                {
                    agent = contractType.agent;
                }
                else
                {
                    agent = AgentList.Instance.GetSuitableAgentForContract(this);
                }

                // Set description
                if (string.IsNullOrEmpty(contractType.description) && agent != null)
                {
                    // Generate the contract description
                    description = TextGen.GenerateBackStories(agent.Name, agent.GetMindsetString(),
                        contractType.topic, contractType.subject, contractType.motivation, random.Next());
                }
                else
                {
                    description = contractType.description;
                }

                // Generate behaviours
                behaviours = new List<ContractBehaviour>();
                if (!contractType.GenerateBehaviours(this))
                {
                    return false;
                }

                // Generate parameters
                if (!contractType.GenerateParameters(this))
                {
                    return false;
                }

                LoggingUtil.LogVerbose(this.GetType(), "Initialized contract: " + contractType);
                return true;
            }
            catch (Exception e)
            {
                LoggingUtil.LogError(this, "Error initializing contract " + contractType);
                LoggingUtil.LogException(e);
                ExceptionLogWindow.DisplayFatalException(ExceptionLogWindow.ExceptionSituation.CONTRACT_GENERATION, e,
                    contractType == null ? "unknown" : contractType.name);

                return false;
            }
            finally
            {
                LoggingUtil.logLevel = origLogLevel;
            }
        }
Example #42
0
        /// <summary>
        /// Loads all the contact configuration nodes and creates ContractType objects.
        /// </summary>
        private IEnumerator <YieldInstruction> LoadContractConfig()
        {
            // Load all the contract groups
            LoggingUtil.LogDebug(this.GetType(), "Loading CONTRACT_GROUP nodes.");
            ConfigNode[] contractGroups = GameDatabase.Instance.GetConfigNodes("CONTRACT_GROUP");

            foreach (ConfigNode groupConfig in contractGroups)
            {
                // Create the group
                string name = groupConfig.GetValue("name");
                LoggingUtil.LogInfo(this.GetType(), "Loading CONTRACT_GROUP: '" + name + "'");
                ContractGroup contractGroup = null;
                try
                {
                    contractGroup = new ContractGroup(name);
                }
                catch (ArgumentException)
                {
                    LoggingUtil.LogError(this.GetType(), "Couldn't load CONTRACT_GROUP '" + name + "' due to a duplicate name.");
                }

                // Peform the actual load
                if (contractGroup != null)
                {
                    bool success = false;
                    try
                    {
                        success = contractGroup.Load(groupConfig);
                    }
                    catch (Exception e)
                    {
                        Exception wrapper = new Exception("Error loading CONTRACT_GROUP '" + name + "'", e);
                        LoggingUtil.LogException(wrapper);
                    }
                    finally
                    {
                        if (!success)
                        {
                            ContractGroup.contractGroups.Remove(name);
                        }
                    }
                }
            }

            LoggingUtil.LogDebug(this.GetType(), "Loading CONTRACT_TYPE nodes.");
            ConfigNode[] contractConfigs = GameDatabase.Instance.GetConfigNodes("CONTRACT_TYPE");
            totalContracts = contractConfigs.Count();

            // First pass - create all the ContractType objects
            foreach (ConfigNode contractConfig in contractConfigs)
            {
                // Create the initial contract type
                LoggingUtil.LogVerbose(this.GetType(), "Pre-load for node: '" + contractConfig.GetValue("name") + "'");
                try
                {
                    ContractType contractType = new ContractType(contractConfig.GetValue("name"));
                }
                catch (ArgumentException)
                {
                    LoggingUtil.LogError(this.GetType(), "Couldn't load CONTRACT_TYPE '" + contractConfig.GetValue("name") + "' due to a duplicate name.");
                }
            }

            // Second pass - do the actual loading of details
            foreach (ConfigNode contractConfig in contractConfigs)
            {
                attemptedContracts++;
                yield return(new WaitForEndOfFrame());

                // Fetch the contractType
                string       name         = contractConfig.GetValue("name");
                ContractType contractType = ContractType.GetContractType(name);
                if (contractType != null)
                {
                    LoggingUtil.LogDebug(this.GetType(), "Loading CONTRACT_TYPE: '" + name + "'");
                    // Perform the load
                    try
                    {
                        contractType.Load(contractConfig);
                        if (contractType.enabled)
                        {
                            successContracts++;
                        }
                    }
                    catch (Exception e)
                    {
                        Exception wrapper = new Exception("Error loading CONTRACT_TYPE '" + name + "'", e);
                        LoggingUtil.LogException(wrapper);
                    }
                }
            }

            LoggingUtil.LogInfo(this.GetType(), "Loaded " + successContracts + " out of " + totalContracts + " CONTRACT_TYPE nodes.");

            if (!reloading && LoggingUtil.logLevel == LoggingUtil.LogLevel.DEBUG || LoggingUtil.logLevel == LoggingUtil.LogLevel.VERBOSE)
            {
                ScreenMessages.PostScreenMessage("Contract Configurator: Loaded " + successContracts + " out of " + totalContracts
                                                 + " contracts successfully.", 5, ScreenMessageStyle.UPPER_CENTER);
            }
        }
        /// <summary>
        /// Generates a new ParameterFactory from the given ConfigNode.
        /// </summary>
        /// <param name="parameterConfig">ConfigNode to use in the generation.</param>
        /// <param name="contractType">ContractType that this parameter factory falls under</param>
        /// <param name="paramFactory">The ParameterFactory object.</param>
        /// <param name="parent">ParameterFactory to use as the parent</param>
        /// <returns>Whether the load was successful</returns>
        public static bool GenerateParameterFactory(ConfigNode parameterConfig, ContractType contractType, out ParameterFactory paramFactory, ParameterFactory parent = null)
        {
            // Logging on
            LoggingUtil.CaptureLog = true;
            bool valid = true;

            // Get the type
            string type = parameterConfig.GetValue("type");
            string name = parameterConfig.HasValue("name") ? parameterConfig.GetValue("name") : type;

            if (string.IsNullOrEmpty(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                                     "PARAMETER '" + parameterConfig.GetValue("name") + "' does not specify the mandatory 'type' attribute.");
                paramFactory = new InvalidParameterFactory();
                valid        = false;
            }
            else if (!factories.ContainsKey(type))
            {
                LoggingUtil.LogError(typeof(ParameterFactory), "CONTRACT_TYPE '" + contractType.name + "'," +
                                     "PARAMETER '" + parameterConfig.GetValue("name") + "' of type '" + parameterConfig.GetValue("type") + "': " +
                                     "Unknown parameter '" + type + "'.");
                paramFactory = new InvalidParameterFactory();
                valid        = false;
            }
            else
            {
                // Create an instance of the factory
                paramFactory = (ParameterFactory)Activator.CreateInstance(factories[type]);
            }

            // Set attributes
            paramFactory.parent       = parent;
            paramFactory.contractType = contractType;
            paramFactory.dataNode     = new DataNode(name, parent != null ? parent.dataNode : contractType.dataNode, paramFactory);

            // Load child requirements
            foreach (ConfigNode childNode in ConfigNodeUtil.GetChildNodes(parameterConfig, "REQUIREMENT"))
            {
                ContractRequirement req = null;
                valid &= ContractRequirement.GenerateRequirement(childNode, contractType, out req, paramFactory);
                if (req != null)
                {
                    paramFactory.requirements.Add(req);
                    if (req.hasWarnings)
                    {
                        paramFactory.hasWarnings = true;
                    }
                }
            }

            // Load config
            if (!paramFactory.Load(parameterConfig))
            {
                // If there was a load failure, check if there are requirements
                if (paramFactory.requirements.Count > 0)
                {
                    LoggingUtil.LogWarning(paramFactory, "Ignoring failed parameter with child requirements.");
                }
                else
                {
                    valid = false;
                }
            }

            // Late initialize for iterator keys
            valid &= DataNode.InitializeIteratorKey(parameterConfig, paramFactory);

            // Check for unexpected values - always do this last
            if (paramFactory.GetType() != typeof(InvalidParameterFactory))
            {
                valid &= ConfigNodeUtil.ValidateUnexpectedValues(parameterConfig, paramFactory);
            }

            paramFactory.log       = LoggingUtil.capturedLog;
            LoggingUtil.CaptureLog = false;

            // Load child nodes
            foreach (ConfigNode childNode in ConfigNodeUtil.GetChildNodes(parameterConfig, "PARAMETER"))
            {
                ParameterFactory child = null;
                valid &= ParameterFactory.GenerateParameterFactory(childNode, contractType, out child, paramFactory);
                if (child != null)
                {
                    paramFactory.childNodes.Add(child);
                    if (child.hasWarnings)
                    {
                        paramFactory.hasWarnings = true;
                    }
                }
            }

            paramFactory.enabled = valid;

            return(valid);
        }
Example #44
0
        /*
         * Loads all the contact configuration nodes and creates ContractType objects.
         */
        void LoadContractConfig()
        {
            LoggingUtil.LogDebug(this.GetType(), "Loading CONTRACT_TYPE nodes.");
            ConfigNode[] contractConfigs = GameDatabase.Instance.GetConfigNodes("CONTRACT_TYPE");

            // First pass - create all the ContractType objects
            foreach (ConfigNode contractConfig in contractConfigs)
            {
                totalContracts++;
                LoggingUtil.LogVerbose(this.GetType(), "Pre-load for node: '" + contractConfig.GetValue("name") + "'");
                // Create the initial contract type
                try
                {
                    ContractType contractType = new ContractType(contractConfig.GetValue("name"));
                }
                catch (ArgumentException)
                {
                    LoggingUtil.LogError(this.GetType(), "Couldn't load CONTRACT_TYPE '" + contractConfig.GetValue("name") + "' due to a duplicate name.");

                    // BUG: The same contract will get loaded twice, but just decrement the success counter so one shows as failed
                    successContracts--;
                }
            }

            // Second pass - do the actual loading of details
            foreach (ConfigNode contractConfig in contractConfigs)
            {
                // Fetch the contractType
                string       name         = contractConfig.GetValue("name");
                ContractType contractType = ContractType.contractTypes[name];
                bool         success      = false;
                if (contractType != null)
                {
                    LoggingUtil.LogDebug(this.GetType(), "Loading CONTRACT_TYPE: '" + name + "'");
                    // Perform the load
                    try
                    {
                        if (contractType.Load(contractConfig))
                        {
                            successContracts++;
                            success = true;
                        }
                    }
                    catch (Exception e)
                    {
                        Exception wrapper = new Exception("Error loading CONTRACT_TYPE '" + name + "'", e);
                        Debug.LogException(wrapper);
                    }
                    finally
                    {
                        if (!success)
                        {
                            ContractType.contractTypes.Remove(name);
                        }
                    }
                }
            }

            LoggingUtil.LogInfo(this.GetType(), "Loaded " + successContracts + " out of " + totalContracts + " CONTRACT_TYPE nodes.");

            if (!reloading && LoggingUtil.logLevel == LoggingUtil.LogLevel.DEBUG || LoggingUtil.logLevel == LoggingUtil.LogLevel.VERBOSE)
            {
                ScreenMessages.PostScreenMessage("Contract Configurator: Loaded " + successContracts + " out of " + totalContracts
                                                 + " contracts successfully.", 5, ScreenMessageStyle.UPPER_CENTER);
            }
        }