Skip to content

A .NET 8 library for quest and inventory management systems in games and applications. This library provides a comprehensive framework for managing players, quests, inventories, and item systems.

Notifications You must be signed in to change notification settings

olivegamestudio/Pilgrimage

Repository files navigation

Pilgrimage

A .NET library for quest and inventory management systems in games and applications. This library provides a comprehensive framework for managing players, quests, inventories, and item systems.

Features

  • Quest System: Create and manage quests with dependencies, repeatability, rewards, and abandonment
  • Inventory System: Flexible slot-based inventory with weight limits and item stacking
  • Player Management: Unified player interface for quest and inventory operations
  • Requirement System: Extensible system for quest prerequisites

Installation

Install the package via NuGet Package Manager:

dotnet add package Pilgrimage

Or via Package Manager Console:

Install-Package Pilgrimage

Key Concepts

Inventory Management

  • Slot Containers: Each container has a fixed number of slots and optional weight limit
  • Item Stacking: Items stack up to their MaxQuantityPerSlot value
  • Weight System: Items can have weight, and containers can have weight limits
  • Multiple Containers: Players can have multiple containers for organization

Quest Flow

  1. Requirements Check: Quest dependencies must be met
  2. Start Quest: Player receives up-front items (if any)
  3. Complete Quest: Player receives reward items (if inventory has space)
  4. Abort Quest: Player can abandon quest, up-front items are removed, quest returns to Available state
  5. Repeatability: Some quests can be repeated with cooldowns and limits

Extensibility

  • RequirementBase: Create custom quest requirements by inheriting from this class
  • Item System: Extend the item system by inheriting from Item or WorldItem

License

This project is licensed under the MIT License.

Quick Start

using Pilgrimage;

// Create a player
Player player = new();

// Add inventory space (16 slots, max 100 weight)
player.AddSlotContainer(16, 100);

// Create a quest system
Quests questSystem = new();

// Create and add a quest
Quest welcomeQuest = new()
{
    Id = 1
};
questSystem.AddQuest(welcomeQuest);

// Start the quest
if (questSystem.CanStartQuest(player, welcomeQuest, DateTime.UtcNow))
{
    questSystem.StartQuest(player, welcomeQuest, DateTime.UtcNow);
}

Core Components

Player

The Player class is the main interface for managing a player's inventory and quest progress.

Player player = new();

// Inventory management
player.AddSlotContainer(maxSlots: 20, maxWeight: 150);
player.AddItem(sword, quantity: 1);
bool hasPotion = player.HasItem(healthPotion, quantity: 5);

// Quest management
bool canStart = player.CanStartQuest(quest, DateTime.UtcNow);
player.StartQuest(quest, DateTime.UtcNow);
bool hasCompleted = player.HasCompletedQuest(quest);
bool canComplete = player.CanCompleteQuest(quest);
player.CompleteQuest(quest, DateTime.UtcNow);

// Quest abortion
bool canAbort = player.CanAbortQuest(quest);
player.AbortQuest(quest, DateTime.UtcNow);

Inventory System

Creating Items

// Create a basic item
WorldItem sword = new()
{
    Id = 1,
    MaxQuantityPerSlot = 1,  // Only one sword per slot
    Weight = 5               // Each sword weighs 5 units
};

// Create a stackable item
WorldItem arrow = new()
{
    Id = 2,
    MaxQuantityPerSlot = 99, // Up to 99 arrows per slot
    Weight = 1               // Each arrow weighs 1 unit
};

Adding Inventory Space

Player player = new();

// Add a container with 16 slots and no weight limit
player.AddSlotContainer(16);

// Add a container with 8 slots and 50 weight limit
player.AddSlotContainer(8, 50);

// Add multiple containers for different purposes
player.AddSlotContainer(20);     // General inventory
player.AddSlotContainer(10, 25); // Equipment bag with weight limit

Managing Items

// Add items to inventory
bool success = player.AddItem(sword, 1);
player.AddItem(arrows, 50);

// Check if player has items
bool hasSword = player.HasItem(sword, 1);
bool hasEnoughArrows = player.HasItem(arrows, 30);

// Remove items from inventory
bool removed = player.RemoveItem(arrows, 10); // Remove 10 arrows
player.RemoveItem(sword, 1); // Remove the sword

// Quest items cannot be removed while quest is active
WorldItem questMap = new() { Id = 3, QuestId = 100 }; // Associated with quest 100
// This will fail if quest 100 is currently in progress
bool canRemove = player.RemoveItem(questMap, 1);

Quest System

Creating Quests

// Basic quest
Quest deliveryQuest = new()
{
    Id = 100
};

// Quest with rewards
Quest treasureHunt = new()
{
    Id = 101,
    Rewards = new List<RewardItem>
    {
        new() { WorldItem = goldCoin, Quantity = 50 },
        new() { WorldItem = magicRing, Quantity = 1 }
    }
};

// Repeatable quest
Quest dailyQuest = new()
{
    Id = 102,
    Repeatable = new QuestRepeatable
    {
        IsRepeatable = true,
        TimeBeforeRepeatable = TimeSpan.FromHours(24),
        MaxTimes = 10  // Can only be done 10 times total
    }
};

// Quest with quest items (items that can't be removed while quest is active)
Quest escortQuest = new()
{
    Id = 300,
    UpFrontItems = new List<UpFrontItem>
    {
        new() { WorldItem = new WorldItem { Id = 10, QuestId = 300 }, Quantity = 1 } // Quest item
    }
};

Quest Items

Quest items are special items that cannot be removed from inventory while their associated quest is active:

// Create a quest item by setting the QuestId property
WorldItem questMap = new()
{
    Id = 50,
    QuestId = 100, // Associated with quest ID 100
    MaxQuantityPerSlot = 1
};

// Quest items can be given as up-front items
Quest treasureHuntQuest = new()
{
    Id = 100,
    UpFrontItems = new List<UpFrontItem>
    {
        new() { WorldItem = questMap, Quantity = 1 }
    }
};

// Start the quest (player receives quest map)
questSystem.StartQuest(player, treasureHuntQuest, DateTime.UtcNow);

// This will fail because quest is active
bool canRemove = player.RemoveItem(questMap, 1); // Returns false

// Complete the quest first
questSystem.CompleteQuest(player, treasureHuntQuest, DateTime.UtcNow);

// Now the quest item can be removed
canRemove = player.RemoveItem(questMap, 1); // Returns true

Quest Abortion

Players can abandon quests that are in progress. When a quest is aborted:

  • The quest state returns to Available (can be started again)
  • All up-front items are removed from the player's inventory
  • The quest does not count as completed
  • QuestAborted event is fired
// Create a quest with up-front items
Quest deliveryQuest = new()
{
    Id = 150,
    UpFrontItems = new List<UpFrontItem>
    {
        new() { WorldItem = new WorldItem { Id = 20 }, Quantity = 1 }, // Delivery package
        new() { WorldItem = new WorldItem { Id = 21 }, Quantity = 5 }  // Travel supplies
    }
};

// Subscribe to abortion event
questSystem.QuestAborted += (sender, e) => 
{
    Console.WriteLine($"Quest {e.Quest.Id} was aborted at {e.AbortedAt}");
};

// Start the quest (player receives up-front items)
if (questSystem.CanStartQuest(player, deliveryQuest, DateTime.UtcNow))
{
    questSystem.StartQuest(player, deliveryQuest, DateTime.UtcNow);
}

// Player decides to abandon the quest
if (questSystem.CanAbortQuest(player, deliveryQuest))
{
    bool aborted = questSystem.AbortQuest(player, deliveryQuest, DateTime.UtcNow);
    if (aborted)
    {
        Console.WriteLine("Quest aborted! Up-front items have been removed.");
        
        // Quest can now be started again
        bool canRestart = questSystem.CanStartQuest(player, deliveryQuest, DateTime.UtcNow);
        Console.WriteLine($"Can restart quest: {canRestart}"); // True
    }
    else
    {
        Console.WriteLine("Quest abortion failed! Some up-front items could not be removed.");
        Console.WriteLine("Quest remains in progress. Check ItemRemoveFailed events for details.");
    }
}

Handling Quest Operation Failures

The quest system uses events to notify about failures during quest operations. This is particularly useful for debugging and providing user feedback:

// Subscribe to item operation events for better error handling
player.ItemAddFailed += (sender, e) =>
{
    Console.WriteLine($"Failed to add {e.RequestedQuantity} of item {e.WorldItem.Id}. " +
                     $"Only {e.AddedQuantity} were added. Reason: Insufficient inventory space.");
};

player.ItemRemoveFailed += (sender, e) =>
{
    Console.WriteLine($"Failed to remove {e.RequestedQuantity} of item {e.WorldItem.Id}. " +
                     $"Only {e.RemovedQuantity} were removed. Item may have been consumed or removed.");
};

// Create a quest with up-front items that might not fit
Quest challengingQuest = new()
{
    Id = 300,
    UpFrontItems = new List<UpFrontItem>
    {
        new() { WorldItem = new WorldItem { Id = 30 }, Quantity = 10 }, // Lots of items
        new() { WorldItem = new WorldItem { Id = 31 }, Quantity = 5 }
    }
};

// Start quest with limited inventory - events will fire for failures
player.AddSlotContainer(2); // Only 2 slots available
questSystem.StartQuest(player, challengingQuest, DateTime.UtcNow);
// ItemAddFailed events will fire for items that don't fit

// Later, when aborting, some items might not be removable
questSystem.AbortQuest(player, challengingQuest, DateTime.UtcNow);
// ItemRemoveFailed events will fire for items that couldn't be removed

Quest Dependencies

// Quest with completion requirements
Quest advancedQuest = new()
{
    Id = 200,
    Requirements = new List<RequirementBase>
    {
        new QuestCompletionRequirement { Id = 100 }, // Must complete quest 100 first
        new QuestCompletionRequirement { Id = 101 }  // Must complete quest 101 first
    }
};

// Quest with level requirement
Quest expertQuest = new()
{
    Id = 300,
    MinPlayerLevel = 10 // Must be at least level 10
};

// Quest with multiple requirement types
Quest masterQuest = new()
{
    Id = 400,
    MinPlayerLevel = 25, // Must be at least level 25
    Requirements = new List<RequirementBase>
    {
        new QuestCompletionRequirement { Id = 200 } // Must complete advanced quest
    }
};

Managing Quests

Quests questSystem = new();

// Add quests to the system
questSystem.AddQuest(deliveryQuest);
questSystem.AddQuest(treasureHunt);
questSystem.AddQuest(dailyQuest);

// Check if player can start a quest
if (questSystem.CanStartQuest(player, deliveryQuest, DateTime.UtcNow))
{
    questSystem.StartQuest(player, deliveryQuest, DateTime.UtcNow);
}

// Complete a quest
if (questSystem.CanCompleteQuest(player, deliveryQuest))
{
    bool completed = questSystem.CompleteQuest(player, deliveryQuest, DateTime.UtcNow);
    if (completed)
    {
        Console.WriteLine("Quest completed! Rewards added to inventory.");
    }
    else
    {
        Console.WriteLine("Quest completion failed - not enough inventory space for rewards.");
    }
}

Advanced Quest Features

Up-Front Items

Up-front items are given to players when they start a quest (like quest items or tools):

Quest escortQuest = new()
{
    Id = 300,
    UpFrontItems = new List<UpFrontItem>
    {
        new() { WorldItem = questMap, Quantity = 1 },
        new() { WorldItem = specialKey, Quantity = 1 }
    }
};

Quest Repeatability

// Daily quest that can be repeated indefinitely
Quest dailyChallenge = new()
{
    Id = 400,
    Repeatable = new QuestRepeatable
    {
        IsRepeatable = true,
        TimeBeforeRepeatable = TimeSpan.FromDays(1)
    }
};

// Weekly quest with limited repetitions
Quest weeklyRaid = new()
{
    Id = 401,
    Repeatable = new QuestRepeatable
    {
        IsRepeatable = true,
        TimeBeforeRepeatable = TimeSpan.FromDays(7),
        MaxTimes = 4  // Can only be done 4 times total
    }
};

Complete Example

Here's a complete example showing how to set up a simple quest and inventory system:

using Pilgrimage;

// Create items
WorldItem sword = new() { Id = 1, MaxQuantityPerSlot = 1, Weight = 5 };
WorldItem potion = new() { Id = 2, MaxQuantityPerSlot = 10, Weight = 1 };
WorldItem gold = new() { Id = 3, MaxQuantityPerSlot = 100, Weight = 0 };

// Create a player with inventory
Player player = new();
player.AddSlotContainer(20, 100); // 20 slots, 100 weight limit

// Add some starting items
player.AddItem(sword, 1);
player.AddItem(potion, 5);

// Create quest system
Quests questSystem = new();

// Create a simple quest with rewards
Quest firstQuest = new()
{
    Id = 1,
    Rewards = new List<RewardItem>
    {
        new() { WorldItem = gold, Quantity = 100 },
        new() { WorldItem = potion, Quantity = 3 }
    }
};

// Create a follow-up quest that requires the first quest
Quest secondQuest = new()
{
    Id = 2,
    Requirements = new List<RequirementBase>
    {
        new QuestCompletionRequirement { Id = 1 } // Must complete quest 1 first
    },
    Rewards = new List<RewardItem>
    {
        new() { WorldItem = gold, Quantity = 250 }
    }
};

// Add quests to system
questSystem.AddQuest(firstQuest);
questSystem.AddQuest(secondQuest);

// Player completes first quest
if (questSystem.CanStartQuest(player, firstQuest, DateTime.UtcNow))
{
    questSystem.StartQuest(player, firstQuest, DateTime.UtcNow);
    
    // Simulate quest completion
    if (questSystem.CanCompleteQuest(player, firstQuest))
    {
        questSystem.CompleteQuest(player, firstQuest, DateTime.UtcNow);
        Console.WriteLine("First quest completed!");
    }
}

// Player can now start second quest
if (questSystem.CanStartQuest(player, secondQuest, DateTime.UtcNow))
{
    questSystem.StartQuest(player, secondQuest, DateTime.UtcNow);
    Console.WriteLine("Second quest started!");
}

// Check inventory
Console.WriteLine($"Player has {(player.HasItem(gold, 100) ? "at least 100" : "less than 100")} gold");
Console.WriteLine($"Player has {(player.HasItem(potion, 8) ? "at least 8" : "less than 8")} potions");

About

A .NET 8 library for quest and inventory management systems in games and applications. This library provides a comprehensive framework for managing players, quests, inventories, and item systems.

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages