Pilgrimage 4.2.0

dotnet add package Pilgrimage --version 4.2.0
                    
NuGet\Install-Package Pilgrimage -Version 4.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Pilgrimage" Version="4.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Pilgrimage" Version="4.2.0" />
                    
Directory.Packages.props
<PackageReference Include="Pilgrimage" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Pilgrimage --version 4.2.0
                    
#r "nuget: Pilgrimage, 4.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Pilgrimage@4.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Pilgrimage&version=4.2.0
                    
Install as a Cake Addin
#tool nuget:?package=Pilgrimage&version=4.2.0
                    
Install as a Cake Tool

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");
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
4.2.0 83 9/1/2025
4.1.0 58 8/22/2025
4.0.0 96 8/22/2025
3.1.0 140 9/5/2024
3.0.0 142 8/31/2024
2.2.0 135 8/29/2024
2.1.0 133 8/27/2024
2.0.1-alpha.0.1 100 8/18/2024
2.0.0 193 8/18/2024
1.4.1-alpha.0.2 95 8/18/2024
1.4.1-alpha.0.1 105 8/16/2024
1.4.0 157 8/16/2024
1.3.1-alpha.0.2 106 8/16/2024

Version 4.2.0: Added quest objectives.