Missions/Quests - Best Way?

Hello,

I want to have a load of quests within my game (It’s a free roam game) - a quest can be from “Walk to the shop and pick some apples up”, to “Go visit your friend John”, etc…

Whats the best way to construct this? Will I just have a load of variables dedicated to these mission? :

var mission_ShopApples_Complete : boolean = false;
var mission_VisitJohn_Complete : boolean = false;

Then possible sub variables for that mission:

var mission_ShopApples_Title : String = "Apple Pickup";
var mission_ShopApples_Reward : String = "Money +100";

var mission_VisitJohn_Title : String = "Visit John";
var mission_VisitJohn_Reward : String = "XP +4";

Considering I could of 100’s of 1000’s of quests. Is this a decent way of doing it? Just having a long ass script holding all these mission statuses?

Thanks, Ollie

I doubt there is such a thing as a universal “best way” when it comes to game design questions. I have found that trying to uphold the OOP principles is a good idea. Especially quests are obviously single objects in the game world, so I contend that the OOP way is a very good way.

Abstract your quests. Have a class for the most abstract notion of a Quest. Determine what behavior and data each quest shares, then put that in the Quest class. Notce, that you will be handling all quests as this class, so unless it in here, you won’t have direct access to it. You could make it something like

public abstract class Quest{

    protected static List<Quest> questList = new ...;

    public static List<Quest> GetQuests(){ return new List<Quest>(questList); }

    /*
      The abstract keyword requires the extending class 
      to provide an implementation.
    */
    //gives the rewards
    public abstract bool FinishQuest();
    //Returns the quest giver's description
    public abstract string GetDescription();
    //returns the current objective
    public abstract string GetObjective();
}

Then move on to each sub type of Quest: you could have “FetchQuest”, “TalkQuest” etc. Each of these classes will extend Quest.

Notice, in the Quest class, there is no BeginQuest(). That is because each sub type of Quest will have their own static constructor.

public class FetchQuest : Quest{
    
    private string description;
    private string objective;
    
    public override bool FinishQuest(){ /*give rewards*/}
    public override string GetDescription(){ return description; }
    //every abstract method must be implemented here

    private FetchQuest(string newDescription, string newObjective){
        description = newDescription;
        objective = newObjective;
    }    

    public static FetchQuest GetApplesFromStore(){
        objective = "Walk into the store and get Apples."
        description = "I'm so hungry and need some apples. You look like a strong warrior, fetch me some apples from the nearby store.";
        questList.Add(new FetchQuest(description, objective));
    }
}

Now all you need to do to begin and store the quest is to call FetchQuest.GetApplesFromStore(); from your quest giver code. When you ever feel the need to see what quests are currently active, you cain gain acces to (a copy of; to prevent accidental changes) the quest list with Quest.GetQuests();

Someone could argue that this design is in violation of the Single Responsibility Principle, which states that an object should do only one thing. My Quest class obviously maintains the quest list and represents a quest. If you feel the need to abide by the SOLID principles, then by all means, use a singleton QuestManager which maintains all the ‘administrative’ quest stuff. You’ll also need a Factory to create the quests, because creating a new quest and representing one are two different behaviors, right? This all would add levels of complexity so I felt it better not to include it in these examples.