Example #1
0
        private Motive ChooseBestMotive(Motive[] motives)
        {
            if (motives == null)
            {
                return(null);
            }
            Motive bestMotive    = null;
            float  bestAlignment = -Mathf.Infinity;

            for (int i = 0; i < motives.Length; i++)
            {
                var motive = motives[i];
                if (motive == null)
                {
                    continue;
                }
                var alignment = GetDriveAlignment(motive.driveValues);

                if (detailedDebug)
                {
                    Debug.Log("Quest Machine: [Generator] Motive Alignment: entity=" + ((entity != null) ? entity.name : "null") +
                              " motive=" + motive.text + " alignment=" + alignment, entity);
                }

                if (alignment > bestAlignment)
                {
                    bestAlignment = alignment;
                    bestMotive    = motive;
                }
            }
            return(bestMotive);
        }
Example #2
0
        /// <summary>
        /// Adds the quest's offer text .
        /// </summary>
        /// <param name="questBuilder">QuestBuilder.</param>
        /// <param name="mainTargetEntity">Target of the quest.</param>
        /// <param name="mainTargetDescriptor">Descriptor of the target (with count).</param>
        /// <param name="domainName">Domain where the target is located.</param>
        /// <param name="goal">Final step to complete quest.</param>
        /// <param name="motive">Motive for goal.</param>
        protected virtual void AddOfferText(QuestBuilder questBuilder, string mainTargetEntity, string mainTargetDescriptor, string domainName, PlanStep goal, Motive motive)
        {
            // Offer motive:
            var motiveText = (motive != null) ? StringField.GetStringValue(motive.text)
                : (goal.action.motives.Length > 0) ? StringField.GetStringValue(goal.action.motives[0].text)
                : StringField.GetStringValue(goal.action.actionText.activeText.dialogueText);

            motiveText = ReplaceStepTags(motiveText, mainTargetEntity, mainTargetDescriptor, domainName, string.Empty, 0);
            questBuilder.AddOfferContents(questBuilder.CreateTitleContent(), questBuilder.CreateBodyContent(motiveText));
        }
Example #3
0
        private IEnumerator DetermineGoal()
        {
            // Search world model for most urgent fact:
            Fact[] mostUrgentFacts;
            var    cumulativeUrgency = worldModel.ComputeUrgency(goalSelectionMode, out mostUrgentFacts, ignoreList, detailedDebug);
            var    mostUrgentFact    = ChooseWeightedMostUrgentFact(mostUrgentFacts);

            if (mostUrgentFact == null)
            {
                yield break;
            }
            if (cumulativeUrgency <= 0)
            {
                if (QuestMachine.debug || detailedDebug)
                {
                    Debug.Log("Quest Machine: [Generator] " + entity.displayName + ": No facts are currently urgent for " + entity.displayName + ". Not generating a new quest.", entity);
                }
                yield break;
            }
            if (QuestMachine.debug || detailedDebug)
            {
                Debug.Log("Quest Machine: [Generator] " + entity.displayName + ": Most urgent fact: " + mostUrgentFact.count + " " +
                          mostUrgentFact.entityType.name + " in " + mostUrgentFact.domainType.name, entity);
            }

            // Choose goal action to perform on that fact:
            float  bestUrgency = Mathf.Infinity;
            Action bestAction  = null;
            Motive bestMotive  = null;
            var    actions     = GetEntityActions(mostUrgentFact.entityType);

            if (actions == null)
            {
                yield break;
            }
            int numChecks = 0;

            for (int i = 0; i < actions.Count; i++)
            {
                numChecks++;
                if (numChecks > maxGoalActionChecksPerFrame)
                {
                    numChecks = 0;
                    yield return(null);
                }
                var action = actions[i];
                if (action == null)
                {
                    continue;
                }
                var wm = new WorldModel(worldModel);
                wm.ApplyAction(mostUrgentFact, action);
                Fact newMostUrgentFact;
                var  newUrgency          = wm.ComputeUrgency(out newMostUrgentFact);
                var  bestMotiveForAction = ChooseBestMotive(action.motives);
                var  weightedUrgency     = (bestMotiveForAction != null) ? (newUrgency - (GetDriveAlignment(bestMotiveForAction.driveValues) * newUrgency)) : newUrgency;
                if (weightedUrgency < bestUrgency) // Select goal action based on resulting urgency weighted by how well the motive aligns with the giver's drives.
                {
                    bestUrgency = weightedUrgency;
                    bestAction  = action;
                    bestMotive  = bestMotiveForAction;
                }
            }
            if (bestAction == null)
            {
                yield break;
            }
            motive = bestMotive;
            goal   = new PlanStep(mostUrgentFact, bestAction, Mathf.CeilToInt(mostUrgentFact.entityType.maxCountInAction.Evaluate(mostUrgentFact.count)));
            if (QuestMachine.debug || detailedDebug)
            {
                Debug.Log("Quest Machine: [Generator] " + entity.displayName + ": Goal: " + bestAction.name + " " +
                          mostUrgentFact.count + " " + mostUrgentFact.entityType.name, entity);
            }
        }
Example #4
0
        /// <summary>
        /// Converts a plan generated by QuestGenerator into a quest.
        /// </summary>
        /// <param name="entity">Entity generating the quest (e.g., QuestGiver).</param>
        /// <param name="group">Optional quest group under which to categorize this quest.</param>
        /// <param name="goal">Final step to accomplish quest.</param>
        /// <param name="motive">Motive for the goal.</param>
        /// <param name="plan">Steps required to complete the goal step.</param>
        /// <param name="requireReturnToComplete">If true, add a quest node that requires quester to return to entity.</param>
        /// <param name="rewardsUIContents">UI content to show in the rewards offer section.</param>
        /// <param name="rewardSystems">Reward systems to use to </param>
        /// <returns></returns>
        public virtual Quest ConvertPlanToQuest(QuestEntity entity, StringField group, PlanStep goal, Motive motive, Plan plan, bool requireReturnToComplete, List <QuestContent> rewardsUIContents, List <RewardSystem> rewardSystems)
        {
            // Build title:
            var mainTargetEntity     = goal.fact.entityType.name;
            var mainTargetDescriptor = goal.fact.entityType.GetDescriptor(goal.requiredCounterValue);
            var title      = goal.action.displayName + " " + mainTargetDescriptor;
            var questID    = title + " " + System.Guid.NewGuid();
            var domainName = StringField.GetStringValue(goal.fact.domainType.displayName);

            // Start QuestBuilder:
            var questBuilder = new QuestBuilder(title, questID, title);

            SetMainInfo(questBuilder, questID, title, group, goal);
            AddTagsToDictionary(questBuilder.quest.tagDictionary, goal);

            // Offer:
            AddOfferText(questBuilder, mainTargetEntity, mainTargetDescriptor, domainName, goal, motive);
            var rewardsContentIndex = questBuilder.quest.offerContentList.Count;

            AddRewards(questBuilder, entity, goal, rewardsUIContents, rewardSystems);

            // Quest headings:
            AddQuestHeadings(questBuilder, goal);

            // Successful text (shown in journal / when talking again about successful quest):
            AddSuccessfulText(questBuilder, mainTargetEntity, mainTargetDescriptor, domainName, goal);

            // Add steps:
            var previousNode = AddSteps(questBuilder, domainName, goal, plan);

            // Add "return to giver" node:
            if (requireReturnToComplete)
            {
                previousNode = AddReturnNode(questBuilder, previousNode, entity, mainTargetEntity, mainTargetDescriptor, domainName, goal, rewardsContentIndex);
            }

            // Success node:
            questBuilder.AddSuccessNode(previousNode);

            return(questBuilder.ToQuest());
        }