Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions S1API/Items/ItemCreator.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
using System;
using S1API.Internal.Utils;
using S1API.Leveling;
using UnityEngine;
#if (IL2CPPMELON)
using S1ItemFramework = Il2CppScheduleOne.ItemFramework;
using S1Registry = Il2CppScheduleOne.Registry;
#elif (MONOMELON || MONOBEPINEX || IL2CPPBEPINEX)
using S1ItemFramework = ScheduleOne.ItemFramework;
using S1Registry = ScheduleOne.Registry;
#endif

namespace S1API.Items
{
Expand Down Expand Up @@ -30,6 +40,44 @@ public static StorableItemDefinitionBuilder CreateBuilder()
return new StorableItemDefinitionBuilder();
}

/// <summary>
/// Creates a new storable item builder by cloning an existing item by ID.
/// </summary>
/// <param name="sourceItemId">The ID of the item to clone.</param>
/// <returns>A builder pre-configured with the source item properties.</returns>
/// <exception cref="ArgumentException">Thrown if the source item ID is not found or is not a storable item.</exception>
public static StorableItemDefinitionBuilder CloneFrom(string sourceItemId)
{
var sourceDefinition = S1Registry.GetItem(sourceItemId);
if (sourceDefinition == null)
{
throw new ArgumentException($"Source item with ID '{sourceItemId}' not found in registry", nameof(sourceItemId));
}

if (!CrossType.Is(sourceDefinition, out S1ItemFramework.StorableItemDefinition storableDef))
{
throw new ArgumentException($"Item '{sourceItemId}' is not an StorableItemDefinition", nameof(sourceItemId));
}

return new StorableItemDefinitionBuilder(storableDef);
}

/// <summary>
/// Creates a new storable item builder by cloning an existing storable item wrapper.
/// </summary>
/// <param name="source">The storable item definition to clone.</param>
/// <returns>A builder pre-configured with the source item properties.</returns>
/// <exception cref="ArgumentNullException">Thrown if the source definition is null.</exception>
public static StorableItemDefinitionBuilder CloneFrom(StorableItemDefinition source)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source), "Source storable item definition cannot be null");
}

return new StorableItemDefinitionBuilder(source.S1StorableItemDefinition);
}

/// <summary>
/// Creates an item with common parameters in a single call.
/// The item is automatically registered with the game's registry.
Expand All @@ -42,6 +90,8 @@ public static StorableItemDefinitionBuilder CreateBuilder()
/// <param name="basePurchasePrice">Base price when buying from shops (default: 10).</param>
/// <param name="resellMultiplier">Fraction of purchase price recovered when selling (default: 0.5).</param>
/// <param name="legalStatus">Whether the item is legal or illegal (default: Legal).</param>
/// <param name="requiresLevelToPurchase">Whether purchasing the item requires a certain player rank (default: false).</param>
/// <param name="requiredRank">The player rank required to purchase the item, if applicable (default: null).</param>
/// <param name="icon">Optional sprite to use as the item icon.</param>
/// <param name="equippable">Optional equippable component to attach.</param>
/// <returns>A wrapper around the created item definition.</returns>
Expand All @@ -66,13 +116,16 @@ public static StorableItemDefinition CreateItem(
float basePurchasePrice = 10f,
float resellMultiplier = 0.5f,
LegalStatus legalStatus = LegalStatus.Legal,
bool requiresLevelToPurchase = false,
FullRank? requiredRank = null,
Sprite icon = null,
Equippable equippable = null)
{
var builder = new StorableItemDefinitionBuilder()
.WithBasicInfo(id, name, description, category)
.WithStackLimit(stackLimit)
.WithPricing(basePurchasePrice, resellMultiplier)
.WithRequiredRank(requiredRank)
.WithLegalStatus(legalStatus);

if (icon != null)
Expand Down
4 changes: 4 additions & 0 deletions S1API/Items/ItemManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ public static ItemDefinition GetItemDefinition(string itemID)
out S1ItemFramework.AdditiveDefinition additiveDefinition))
return new AdditiveDefinition(additiveDefinition);

if (CrossType.Is(itemDefinition,
out S1ItemFramework.QualityItemDefinition qualityItemDefinition))
return new QualityItemDefinition(qualityItemDefinition);

if (CrossType.Is(itemDefinition,
out S1ItemFramework.StorableItemDefinition storableItemDefinition))
return new StorableItemDefinition(storableItemDefinition);
Expand Down
67 changes: 67 additions & 0 deletions S1API/Items/QualityItemCreator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#if (IL2CPPMELON)
using S1ItemFramework = Il2CppScheduleOne.ItemFramework;
using S1Registry = Il2CppScheduleOne.Registry;
#elif (MONOMELON || MONOBEPINEX || IL2CPPBEPINEX)
using S1ItemFramework = ScheduleOne.ItemFramework;
using S1Registry = ScheduleOne.Registry;
#endif
using System;
using S1API.Internal.Utils;

namespace S1API.Items
{
/// <summary>
/// Provides convenient static methods for creating custom quality items.
/// Use <see cref="CreateBuilder"/> for flexible configuration
/// or <see cref="CloneFrom"/> for quick variants based on existing items.
/// </summary>
public class QualityItemCreator
{
/// <summary>
/// Creates a new builder for composing a quality item definition with full flexibility.
/// Use fluent methods to configure the definition, then call Build() to register it.
/// </summary>
public static QualityItemDefinitionBuilder CreateBuilder()
{
return new QualityItemDefinitionBuilder();
}

/// <summary>
/// Creates a new quality item builder by cloning an existing quality item by ID.
/// </summary>
/// <param name="sourceItemId">The ID of the item to clone.</param>
/// <returns>A builder pre-configured with the source item properties.</returns>
/// <exception cref="ArgumentException">Thrown if the source item ID is not found or is not a quality item.</exception>
public static QualityItemDefinitionBuilder CloneFrom(string sourceItemId)
{
var sourceDefinition = S1Registry.GetItem(sourceItemId);
if (sourceDefinition == null)
{
throw new ArgumentException($"Source item with ID '{sourceItemId}' not found in registry", nameof(sourceItemId));
}

if (!CrossType.Is(sourceDefinition, out S1ItemFramework.QualityItemDefinition qualityDef))
{
throw new ArgumentException($"Item '{sourceItemId}' is not an QualityItemDefinition", nameof(sourceItemId));
}

return new QualityItemDefinitionBuilder(qualityDef);
}

/// <summary>
/// Creates a new quality item builder by cloning an existing quality item wrapper.
/// </summary>
/// <param name="source">The quality item definition to clone.</param>
/// <returns>A builder pre-configured with the source item properties.</returns>
/// <exception cref="ArgumentNullException">Thrown if the source definition is null.</exception>
public static QualityItemDefinitionBuilder CloneFrom(QualityItemDefinition source)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source), "Source storable item definition cannot be null");
}

return new QualityItemDefinitionBuilder(source.S1QualityDefinition);
}
}
}
67 changes: 67 additions & 0 deletions S1API/Items/QualityItemDefinition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#if (IL2CPPMELON)
using S1ItemFramework = Il2CppScheduleOne.ItemFramework;
#elif (MONOMELON || MONOBEPINEX || IL2CPPBEPINEX)
using S1ItemFramework = ScheduleOne.ItemFramework;
#endif
using S1API.Products;

namespace S1API.Items
{
/// <summary>
/// Represents a quality item definition that can be consumed or used in recipes
/// Extends <see cref="StorableItemDefinition"/> with quality-specific properties.
/// </summary>
/// <remarks>
/// Use <see cref="QualityItemCreator"/>
/// </remarks>
public class QualityItemDefinition : StorableItemDefinition
{
/// <summary>
/// INTERNAL: Wraps an existing native quality item definition.
/// </summary>
internal QualityItemDefinition(S1ItemFramework.QualityItemDefinition definition) : base(definition)
{
S1QualityDefinition = definition;
}

/// <summary>
/// INTERNAL: The underlying S1 quality item definition instance.
/// </summary>
internal S1ItemFramework.QualityItemDefinition S1QualityDefinition { get; }

/// <summary>
/// Creates a quality item instance from this definition using the default quality.
/// </summary>
/// <param name="quantity">The quantity to apply to the created instance.</param>
/// <returns>A quality item instance using this definition's default quality.</returns>
public override ItemInstance CreateInstance(int quantity = 1) => CreateInstance(quantity, DefaultQuality);

/// <summary>
/// Creates a quality item instance from this definition with the specified quality.
/// </summary>
/// <param name="quality">The quality to apply to the created instance.</param>
/// <returns>A quality item instance using the specified quality.</returns>
public QualityItemInstance CreateInstance(Quality quality) => CreateInstance(1, quality);

/// <summary>
/// Creates a quality item instance from this definition with the specified quantity and quality.
/// </summary>
/// <param name="quantity">The quantity to apply to the created instance.</param>
/// <param name="quality">The quality to apply to the created instance.</param>
/// <returns>A quality item instance using the specified quantity and quality.</returns>
public QualityItemInstance CreateInstance(int quantity, Quality quality) =>
new QualityItemInstance(new S1ItemFramework.QualityItemInstance(
S1QualityDefinition,
quantity,
(S1ItemFramework.EQuality)quality));
Comment thread
k073l marked this conversation as resolved.

/// <summary>
/// The default quality for this item.
/// </summary>
public Quality DefaultQuality
{
get => (Quality)S1QualityDefinition.DefaultQuality;
set => S1QualityDefinition.DefaultQuality = (S1ItemFramework.EQuality)value;
}
}
}
Loading
Loading