Press "Enter" to skip to content

Lesson 06.1: Creating the Quest Factory

Now that the player can move around, let’s start working on building quests for the player to complete.

Step 1: Create a new ItemQuantity.cs class, in \Engine\Models.

To complete these quests, the player will need to turn in items. For example, a farmer might ask the player to kill rats in his field, and return five rat tails to complete the quest.

So, we need a way to store which items need to be turned in, and how many of them need to be turned it.

To allow for more complex quests, the player may need to turn in more than one type of item, to complete a quest. This requires another List property, because there may be one, or more, items.

Our first class is ItemQuantity. It will store an item ID, and a quantity. You can think of it like a shopping list:

Quantity Item

1 pizza

6 sodas

For this class, we won’t store a complete GameItem object. We can store the ID of the GameItem.

ItemQuantity.cs
namespace Engine.Models
{
    public class ItemQuantity
    {
        public int ItemID { get; set; }
        public int Quantity { get; set; }
        public ItemQuantity(int itemID, int quantity)
        {
            ItemID = itemID;
            Quantity = quantity;
        }
    }
}

Step 2: Create a new Quest.cs class, in \Engine\Models.

Next, we will create the Quest class.

This has string and int properties for the ID, Name, Description, RewardExperiencePoints, and RewardGold. The datatype of the ItemsToCompelte and RewardItems properties, will be List<ItemQuantity>, because they will hold a list of the new ItemQuantity objects.

Quest.cs
using System.Collections.Generic;
namespace Engine.Models
{
    public class Quest
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public List<ItemQuantity> ItemsToComplete { get; set; }
        public int RewardExperiencePoints { get; set; }
        public int RewardGold { get; set; }
        public List<ItemQuantity> RewardItems { get; set; }
        public Quest(int id, string name, string description, List<ItemQuantity> itemsToComplete,
                     int rewardExperiencePoints, int rewardGold, List<ItemQuantity> rewardItems)
        {
            ID = id;
            Name = name;
            Description = description;
            ItemsToComplete = itemsToComplete;
            RewardExperiencePoints = rewardExperiencePoints;
            RewardGold = rewardGold;
            RewardItems = rewardItems;
        }
    }
}

Step 3: Edit Engine\ItemFactory.cs

Before creating the quests, we’ll need to create some more game items, to turn in to complete the quests.

Our first quest will be to kill snakes, and return with five snake fangs. The reward for that quest will be 25 experience points, 10 gold, and a rusty sword.

Inside the “static ItemFactory” function, add two more items to the _standardGameItems list: Snake Fang and Snakeskin.

ItemFactory.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Engine.Models;
namespace Engine.Factories
{
    public static class ItemFactory
    {
        private static List<GameItem> _standardGameItems;
        static ItemFactory()
        {
            _standardGameItems = new List<GameItem>();
            _standardGameItems.Add(new Weapon(1001, "Pointy Stick", 1, 1, 2));
            _standardGameItems.Add(new Weapon(1002, "Rusty Sword", 5, 1, 3));
            _standardGameItems.Add(new GameItem(9001, "Snake fang", 1));
            _standardGameItems.Add(new GameItem(9002, "Snakeskin", 2));
        }
        public static GameItem CreateGameItem(int itemTypeID)
        {
            GameItem standardItem = _standardGameItems.FirstOrDefault(item => item.ItemTypeID == itemTypeID);
            if(standardItem != null)
            {
                return standardItem.Clone();
            }
            return null;
        }
    }
}

Step 4: Create a new QuestFactory.cs class, in \Engine\Factories.

Now we can build the factory that will create the Quest objects. Like the ItemFactory, we will have a static variable (_quests) that holds all the Quests, and a constructor-like function that populates _quests the first time someone uses the QuestFactory class. We’ll also create the GetQuestByID function, to return the Quest object, wherever the rest of the program needs it.

Because we need to pass a list of ItemQuantity objects into the Quest constructor (for the itemsToComplete and rewardItems parameters), we’ll create variables, add items to the variables, and pass them as the parameters. In the refactoring for the Quest classes, we will change this a little.

QuestFactory.cs
using System.Collections.Generic;
using System.Linq;
using Engine.Models;
namespace Engine.Factories
{
    internal static class QuestFactory
    {
        private static readonly List<Quest> _quests = new List<Quest>();
        static QuestFactory()
        {
            // Declare the items need to complete the quest, and its reward items
            List<ItemQuantity> itemsToComplete = new List<ItemQuantity>();
            List<ItemQuantity> rewardItems = new List<ItemQuantity>();
            itemsToComplete.Add(new ItemQuantity(9001, 5));
            rewardItems.Add(new ItemQuantity(1002, 1));
            // Create the quest
            _quests.Add(new Quest(1,
                                  "Clear the herb garden",
                                  "Defeat the snakes in the Herbalist's garden",
                                  itemsToComplete,
                                  25, 10,
                                  rewardItems));
        }
        internal static Quest GetQuestByID(int id)
        {
            return _quests.FirstOrDefault(quest => quest.ID == id);
        }
    }
}

NEXT LESSON: Lesson 06.2: Using Quests in the Game

PREVIOUS LESSON: Lesson 05.2: Creating the Player Inventory

2 Comments

  1. Sam Tudor
    Sam Tudor 2023-11-14

    When we actually create the quest on line 24 how does the quest know which element to use from the lists we pass? when we have multiple quests will we have to denote specifically which elements we want for the quests?

    • SOSCSRPG
      SOSCSRPG 2023-11-14

      Hi Sam,

      Which class has the line 24 you mentioned? I’m guessing your line numbers may be different from what I have, because of changes to Visual Studio and the default “using” directives at the top of the class.

      If you’re asking about the Quest.cs constructor, the code that calls that constructor will pass in the appropriate itemsToComplete and rewardItems for the Quest object it’s instantiating. You’ll see that happen in lesson 6.2, in the WorldFactory.CreateWorld() function.

      If that’s not the correct place, please let me know, so I can answer.

Leave a Reply

Your email address will not be published. Required fields are marked *