Exemplo n.º 1
0
 public Node(Node parent, List_GOAP_Worldstate required, GOAP_Action action, float estimatedPathCost)
 {
     this.parent            = parent;
     this.estimatedPathCost = estimatedPathCost;
     this.required          = required;
     this.action            = action;
 }
Exemplo n.º 2
0
    /// <summary>
    /// Tries to apply the action onto the activeNode to see if it results in a valid neighbor
    /// </summary>
    /// <param name="activeNode"></param>
    /// <param name="action"></param>
    /// <param name="planningWorldState">worldstate at the current stage of planning</param>
    /// <param name="agent">currently planning agent</param>
    /// <returns></returns>
    private static List <Node> GetValidNeighborNodeVariations(Node activeNode, GOAP_Action action, List_GOAP_Worldstate planningWorldState, GOAP_Agent agent)
    {
        if (action == null)
        {
            return(null);
        }

        List <Node> nodes = new List <Node>();

        if (action.HasVariations())
        {
            for (int i = 0; i < action.variations.Count; i++)
            {
                if (action.variations[i] != null)
                {
                    nodes.Add(GetValidNeighborNode(activeNode, action.GetVariation(i), planningWorldState, agent));
                }
            }
        }
        else
        {
            nodes.Add(GetValidNeighborNode(activeNode, action, planningWorldState, agent));
        }

        return(nodes);
    }
Exemplo n.º 3
0
 public void SaveQuestPlan(int questID)
 {
     questPlans.Add(questID, new Queue <GOAP_Action>(currentActions));
     Character.Log("<color=#0000cc>" + character.characterData.characterName + "</color> Saved a new QuestPlan. It includes " + questPlans.Last().Value.Count + " actions and starts with " + questPlans.Last().Value.Peek());
     currentActions.Clear();
     activeAction = null;
     activeGoal.Clear();
 }
Exemplo n.º 4
0
 /// <summary>
 ///Cancel the action queue but keep the goal/quest and try planning again immediately
 /// </summary>
 public void Replan()
 {
     activePlanInfo = null;
     activeAction   = null;
     currentActions.Clear();
     actionCompleted = true;
     ChangeState(FSM_State.PLANNING);
     return;
 }
    public static void ShowWindow(ref GOAP_Character.CharacterData characterData)
    {
        AvailableActionsEditorWindow window = (AvailableActionsEditorWindow)EditorWindow.GetWindow(typeof(AvailableActionsEditorWindow));

        window.characterData = characterData;

        //Add all actions to the list
        window.allActions = GOAP_Action.GetAllActionNames();
        characterData.InitBaseActions(window.allActions);
        characterData.RemoveWrongActions(window.allActions);
    }
Exemplo n.º 6
0
 private void InitWindow()
 {
     for (int i = 0; i < allActions.Length; i++)
     {
         string actionName = allActions[i].ToString();
         if (GOAP_Action.IsQuestActionID(actionName))
         {
             continue;
         }
         AvailableActionWindowPanel actionPanel = Instantiate(actionPanelPrefab, actionsParent).GetComponent <AvailableActionWindowPanel>();
         actionPanel.SetContent(actionName, characterData.availableActions.Contains(actionName));
     }
 }
Exemplo n.º 7
0
 private void Awake()
 {
     if (instance != null)
     {
         Destroy(this);
     }
     instance = this;
     if (allActions == null)
     {
         //Add all actions to the list
         allActions = GOAP_Action.GetAllActionNames();
     }
     InitWindow();
 }
Exemplo n.º 8
0
 public void VisualizeAction(GOAP_Action action)
 {
     if (action == null)
     {
         transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, 0);
     }
     else if (action.ActionID == "Sleep")
     {
         transform.eulerAngles = new Vector3(90, transform.eulerAngles.y, 0);
     }
     else
     {
     }
 }
Exemplo n.º 9
0
    private void UpdateWindowAndActions()
    {
        for (int i = 0; i < allActions.Length; i++)
        {
            string actionName = allActions[i].ToString();
            if (GOAP_Action.IsQuestActionID(actionName))
            {
                continue;
            }
            AvailableActionWindowPanel actionPanel = actionsParent.GetChild(i).GetComponent <AvailableActionWindowPanel>();
            actionPanel.SetContent(actionName, characterData.availableActions.Contains(actionName));

            if (GOAP_Action.baseActions.Contains(actionName))
            {
                actionPanel.buttonImage.GetComponent <Button>().interactable = false;
                actionPanel.buttonImage.color = Color.grey;
                actionPanel.buttonLabel.text  = "BASE";
                actionPanel.transform.SetAsFirstSibling();
                if (!characterData.availableActions.Contains(actionName))
                {
                    characterData.availableActions.Add(actionName);
                }
            }
            else
            {
                actionPanel.buttonImage.GetComponent <Button>().interactable = true;
            }
        }


        //remove all actions not on the list from available
        for (int i = characterData.availableActions.Count - 1; i >= 0; i--)
        {
            string action = characterData.availableActions[i];
            if (!allActions.Contains(action) || action == "Action_CompleteQuest" || action == "Action_WaitForQuest" || action == "Action_PostQuest")
            {
                characterData.availableActions.RemoveAt(i);
            }
        }
    }
Exemplo n.º 10
0
    /// <summary>
    /// Cancel the actionqueue and forget the plan
    /// </summary>
    public void CancelPlan()
    {
        if (activeQuest != null)
        {
            checkedQuestIds.Remove(activeQuest.id);
        }
        else
        {
            //if this was a personal goal, remove it from the checked list
            if (activeGoal.Count == 1)
            {
                checkedCharacterGoals.Remove(activeGoal[0]);
            }
        }
        activeQuest = null;
        activeGoal.Clear();

        activePlanInfo = null;
        activeAction   = null;
        currentActions.Clear();
        actionCompleted = true;
        ChangeState(FSM_State.IDLE);
        return;
    }
Exemplo n.º 11
0
 public SimulationStep(GOAP_StatesList worldState, GOAP_Action action, int depth)
 {
     this.worldState = worldState;
     this.action     = action;
     this.depth      = depth;
 }
Exemplo n.º 12
0
    private void Plan()
    {
        for (int i = 0; i < goals.Count; i++)
        {
            if (goals[i].isValid(this))
            {
                goal = goals[i];
                break;
            }
        }

        if (worldState.CompareState(goal.goalStates) == 0)
        {
            return;
        }

        currentPlan.Clear();
        Stack <SimulationStep> sim = new Stack <SimulationStep>();

        GOAP_Action[] simPlan = new GOAP_Action[maxPlanDepth];

        int minDepth = int.MaxValue;

        sim.Push(new SimulationStep(new GOAP_StatesList(worldState), null, 0));

        List <GOAP_States> targetStates = new List <GOAP_States>(goal.goalStates.states);

        while (sim.Count != 0)
        {
            currentSimData = sim.Pop();
            simPlan[currentSimData.depth] = currentSimData.action;

            if (currentSimData.depth > minDepth)
            {
                continue;
            }

            if (currentSimData.worldState.CompareState(goal.goalStates) == 0 || currentSimData.depth >= maxPlanDepth)
            {
                if (currentSimData.depth < minDepth)
                {
                    currentPlan.Clear();
                    for (int i = 0; i <= currentSimData.depth; i++)
                    {
                        if (simPlan[i] != null)
                        {
                            if (!currentPlan.Contains(simPlan[i]))
                            {
                                currentPlan.Enqueue(simPlan[i]);
                            }
                        }
                    }
                    minDepth = currentSimData.depth;
                }
            }
            else
            {
                for (int i = 0; i < actions.Count; i++)
                {
                    if (actions[i].isValid(this))
                    {
                        GOAP_StatesList newSimState = new GOAP_StatesList(currentSimData.worldState);
                        newSimState.AddStates(actions[i].resultStates);
                        sim.Push(new SimulationStep(newSimState, actions[i], (currentSimData.depth + 1)));
                    }
                }
            }
        }
    }
Exemplo n.º 13
0
 public void OnEnable()
 {
     character = (GOAP_Character)target;
     character.characterData.InitBaseActions(GOAP_Action.GetAllActionNames());
     character.characterData.RemoveWrongActions(GOAP_Action.GetAllActionNames());
 }
Exemplo n.º 14
0
    private void PerformUpdate(float deltaTime)
    {
        //Get the next currentAction
        if (actionCompleted)
        {
            if (currentActions.Count > 1 || (currentActions.Count > 0 && activeAction == null))
            {
                //Remove the old active action
                if (activeAction != null)
                {
                    currentActions.Dequeue();
                }
                //Get the new active action
                activeAction    = currentActions.Peek();
                actionCompleted = false;
            }
            else
            {
                activeAction = null;
            }
        }

        if (activeAction != null)
        {
            if (activeQuest != null)
            {
                if (!GOAP_QuestBoard.instance.quests.ContainsKey(activeQuest.id))
                {
                    Character.Log("<color=#0000cc>" + Character.characterData.characterName + "</color> can't complete quest, already finished");
                    CancelPlan();
                    return;
                }
            }
            if (activeAction.CheckRequirements(this))
            {
                if (activeAction.SatisfyWorldstates.Count > 0 && IsSatisfiedInCurrentWorldstate(activeAction.SatisfyWorldstates))
                {
                    actionCompleted = true;
                    Character.Log("<color=#0000cc>" + character.characterData.characterName + "</color> didn't need to perform <color=#cc0000>" + activeAction.ActionID + "</color> anymore.");
                }
                else
                {
                    if (!activeAction.IsInRange(this))
                    {
                        View.PrintMessage("MoveTo " + activeAction.ActionID);
                        ChangeState(FSM_State.MOVETO);
                        return;
                    }
                    else
                    {
                        actionCompleted = activeAction.Perform(this, deltaTime);
                        View.VisualizeAction(activeAction);
                    }
                }
            }
            else
            {
                Character.Log("<color=#0000cc>" + character.characterData.characterName + "</color> cannot perform <color=#cc0000>" + activeAction.ActionID + "</color> anymore.");
                Replan();
            }
        }
        else
        {
            //if this was a personal goal, remove it from the checked list
            if (activeQuest != null)
            {
                activeQuest = null;
            }
            else
            {
                if (activeGoal.Count == 1)
                {
                    checkedCharacterGoals.Remove(activeGoal[0]);
                }
            }
            Character.Log("<color=#0000cc>" + character.characterData.characterName + "</color> has completed his action queue for Goal " + planMemory[(int)activePlanInfo].goalInfo);
            activeGoal.Clear();
            activePlanInfo = null;
            ChangeState(FSM_State.IDLE);
            return;
        }
    }
Exemplo n.º 15
0
    private static Node GetValidNeighborNode(Node activeNode, GOAP_Action action, List_GOAP_Worldstate planningWorldState, GOAP_Agent agent)
    {
        bool isUsefulAction = false;

        List_GOAP_Worldstate newRequired = new List_GOAP_Worldstate(activeNode.required);

        //Actions need to fulfill at least one required Worldstate to result in a valid neighbor
        foreach (GOAP_Worldstate state in activeNode.required)
        {
            if (action.SatisfyWorldstates.ContainsExactly(state))
            {
                if (state.key == WorldStateKey.bWasFieldTended && state.value == 0)
                {
                    Debug.LogError(action.SatisfyWorldstates.ToString());
                }
                newRequired.Remove(state);
                isUsefulAction = true;
            }
        }

        //if this action does not help the plan, return null
        if (!isUsefulAction)
        {
            return(null);
        }

        //If the actions proceduralConditions are not met, we can't perform it anyways
        //if (!action.CheckProceduralConditions(agent)) return null;

        //add the actions own required worldstates to the Node
        foreach (GOAP_Worldstate state in action.RequiredWorldstates)
        {
            if (!planningWorldState.ContainsExactly(state))
            {
                //If the state is an observable one and the agent does not have any memory of it, they just assume that it is in their favor
                if (state.IsObservableState && !agent.currentWorldstates.ContainsKey(state))
                {
                    Debug.Log("<color=#cc00cc>" + agent.Character.characterData.characterName + "</color> assumes state:" + state.ToString());
                    agent.ChangeCurrentWorldState(state);
                }
                else
                {
                    newRequired.Add(state);
                }
            }
        }

        //Apply skillmodification onto the neighbor if it is valid
        float skillModifier = 1f;

        if (action.BenefitingSkill != Skills.None)
        {
            GOAP_Skill skill = agent.Character.characterData.skills.Find(x => x.id == action.BenefitingSkill);
            if (skill != null)
            {
                //If the character is actually skilled in this action, adjust the skillmodifier
                skillModifier /= skill.level;
            }
            else
            {
                //If the character is not skilled in this action, the skillmodifier is set to 5. This only comes into play, when global knowledge planning is used.
                skillModifier = 1f;
            }
        }

        //Change the skillmodifier on the action
        action.ApplySkillModifier(skillModifier);

        return(new Node(activeNode, newRequired, action, newRequired.Count * heuristicFactor + action.ActionCost + activeNode.estimatedPathCost));
    }