diff --git a/CardSets/ExampleSet/cards.txt b/CardSets/ExampleSet/cards.txt
deleted file mode 100644
index 9330b1b..0000000
--- a/CardSets/ExampleSet/cards.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-# Example Card Set - Trading Card Mod for Escape from Duckov
-# Format: CardName | SetName | SetNumber | ImageFile | Rarity | Weight | Value | Description (optional)
-#
-# Fields:
-# CardName - Display name of the card
-# SetName - Name of the card collection
-# SetNumber - Number within the set (for sorting)
-# ImageFile - Filename of the card image (must be in images/ subfolder)
-# Rarity - Card rarity. Valid values: Common, Uncommon, Rare, Very Rare, Ultra Rare, Legendary
-# Weight - Physical weight in game units
-# Value - In-game currency value
-# Description - (Optional) Custom tooltip text. If omitted, auto-generates as "SetName #SetNumber - Rarity"
-#
-# Add your own cards below! Just follow the format above.
-# Place corresponding images in the images/ subfolder.
-
-Duck Hero | Example Set | 001 | duck_hero.png | Rare | 0.05 | 500 | The brave defender of all ponds
-Golden Quacker | Example Set | 002 | golden_quacker.png | Ultra Rare | 0.05 | 12500 | A legendary duck made of pure gold
-Pond Guardian | Example Set | 003 | pond_guardian.png | Uncommon | 0.05 | 100
-Bread Seeker | Example Set | 004 | bread_seeker.png | Common | 0.05 | 25
-Feathered Fury | Example Set | 005 | feathered_fury.png | Rare | 0.05 | 500 | Known for its fierce battle cry
diff --git a/CardSets/ExampleSet/images/bread_seeker.png b/CardSets/ExampleSet/images/bread_seeker.png
deleted file mode 100644
index e2548c5..0000000
Binary files a/CardSets/ExampleSet/images/bread_seeker.png and /dev/null differ
diff --git a/CardSets/ExampleSet/images/duck_hero.png b/CardSets/ExampleSet/images/duck_hero.png
deleted file mode 100644
index 2b05e33..0000000
Binary files a/CardSets/ExampleSet/images/duck_hero.png and /dev/null differ
diff --git a/CardSets/ExampleSet/images/feathered_fury.png b/CardSets/ExampleSet/images/feathered_fury.png
deleted file mode 100644
index 9fc5e6d..0000000
Binary files a/CardSets/ExampleSet/images/feathered_fury.png and /dev/null differ
diff --git a/CardSets/ExampleSet/images/golden_quacker.png b/CardSets/ExampleSet/images/golden_quacker.png
deleted file mode 100644
index daf13f6..0000000
Binary files a/CardSets/ExampleSet/images/golden_quacker.png and /dev/null differ
diff --git a/CardSets/ExampleSet/images/pack.png b/CardSets/ExampleSet/images/pack.png
deleted file mode 100644
index b343c3f..0000000
Binary files a/CardSets/ExampleSet/images/pack.png and /dev/null differ
diff --git a/CardSets/ExampleSet/images/pond_guardian.png b/CardSets/ExampleSet/images/pond_guardian.png
deleted file mode 100644
index 082ac9f..0000000
Binary files a/CardSets/ExampleSet/images/pond_guardian.png and /dev/null differ
diff --git a/TradingCardMod.csproj b/TradingCardMod.csproj
index f41943c..3cbf532 100644
--- a/TradingCardMod.csproj
+++ b/TradingCardMod.csproj
@@ -50,6 +50,9 @@
$(DuckovPath)$(SubPath)UnityEngine.InputLegacyModule.dll
+
+ $(DuckovPath)$(SubPath)UnityEngine.IMGUIModule.dll
+
$(DuckovPath)$(SubPath)UniTask.dll
diff --git a/src/ModBehaviour.cs b/src/ModBehaviour.cs
index 498005c..76999fc 100644
--- a/src/ModBehaviour.cs
+++ b/src/ModBehaviour.cs
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Collections.Generic;
+using System.Linq;
using UnityEngine;
using ItemStatsSystem;
using SodaCraft.Localizations;
@@ -72,6 +73,7 @@ namespace TradingCardMod
private List _createdGameObjects = new List();
private Tag? _tradingCardTag;
private Tag? _binderSheetTag;
+ private Tag? _cardBinderContentTag;
private Item? _binderItem;
private Item? _cardBoxItem;
@@ -84,9 +86,10 @@ namespace TradingCardMod
// Store pack definitions for runtime lookup (key = "SetName|PackName")
private Dictionary _packDefinitions = new Dictionary();
- // Debug: track spawn cycling
- private int _debugSpawnIndex = 0;
- private List- _allSpawnableItems = new List
- ();
+ // Debug spawn window
+ private bool _showSpawnWindow = false;
+ private Rect _spawnWindowRect = new Rect(20, 250, 350, 450);
+ private System.Random _random = new System.Random();
///
/// Called when the GameObject is created. Initialize early to register items before saves load.
@@ -112,6 +115,7 @@ namespace TradingCardMod
// Create our custom tags first
_tradingCardTag = TagHelper.GetOrCreateTradingCardTag();
_binderSheetTag = TagHelper.GetOrCreateBinderSheetTag();
+ _cardBinderContentTag = TagHelper.GetOrCreateCardBinderContentTag();
// Load and register cards - do this early so saves can load them
LoadCardSets();
@@ -122,12 +126,6 @@ namespace TradingCardMod
// Create card packs
CreateCardPacks();
- // Build spawnable items list (cards + storage + packs)
- _allSpawnableItems.AddRange(_registeredItems);
- if (_binderItem != null) _allSpawnableItems.Add(_binderItem);
- if (_cardBoxItem != null) _allSpawnableItems.Add(_cardBoxItem);
- _allSpawnableItems.AddRange(_registeredPacks);
-
Debug.Log("[TradingCardMod] Mod initialized successfully!");
}
catch (Exception ex)
@@ -299,7 +297,7 @@ namespace TradingCardMod
Debug.Log($"[TradingCardMod] Total cards loaded: {_loadedCards.Count}");
Debug.Log($"[TradingCardMod] Total items registered: {_registeredItems.Count}");
- Debug.Log("[TradingCardMod] DEBUG: Press F9 to spawn items (cycles through cards, then binder, then box)");
+ Debug.Log("[TradingCardMod] DEBUG: Press F10 to open spawn menu (storage items & random cards by rarity)");
// Clear the search cache so our items can be found
ClearSearchCache();
@@ -335,7 +333,7 @@ namespace TradingCardMod
///
private void CreateStorageItems()
{
- if (_tradingCardTag == null || _binderSheetTag == null)
+ if (_tradingCardTag == null || _binderSheetTag == null || _cardBinderContentTag == null)
{
Debug.LogError("[TradingCardMod] Cannot create storage items - Required tags not created!");
return;
@@ -352,14 +350,17 @@ namespace TradingCardMod
new List { _tradingCardTag } // Only trading cards allowed
);
- // Add BinderSheet tag to the binder sheet item itself so it can be stored in Card Binders
+ // Add BinderSheet and CardBinderContent tags to the binder sheet item itself
+ // so it can be stored in Card Binders
if (_binderItem != null)
{
_binderItem.Tags.Add(_binderSheetTag);
- Debug.Log("[TradingCardMod] Added BinderSheet tag to Binder Sheet item");
+ _binderItem.Tags.Add(_cardBinderContentTag);
+ Debug.Log("[TradingCardMod] Added BinderSheet and CardBinderContent tags to Binder Sheet item");
}
- // Create Card Binder (12 slots, stores cards AND binder sheets)
+ // Create Card Binder (12 slots, stores items with CardBinderContent tag)
+ // This allows both cards and binder sheets (which both have CardBinderContent tag)
_cardBoxItem = StorageHelper.CreateCardStorage(
CARD_BINDER_ITEM_ID,
"Card Binder",
@@ -367,7 +368,7 @@ namespace TradingCardMod
12,
1.5f, // weight
12500, // value
- new List { _tradingCardTag, _binderSheetTag } // Cards and binder sheets allowed
+ new List { _cardBinderContentTag } // Only CardBinderContent tag required
);
}
@@ -431,46 +432,158 @@ namespace TradingCardMod
///
void Update()
{
- // Debug: Press F9 to spawn an item
- if (Input.GetKeyDown(KeyCode.F9))
+ // Debug: Press F10 to toggle spawn menu
+ if (Input.GetKeyDown(KeyCode.F10))
{
- SpawnDebugItem();
+ _showSpawnWindow = !_showSpawnWindow;
+ Debug.Log($"[TradingCardMod] Spawn window {(_showSpawnWindow ? "opened" : "closed")}");
}
}
///
- /// Spawns items for testing - cycles through cards, then storage items.
+ /// OnGUI is called for rendering and handling GUI events.
///
- private void SpawnDebugItem()
+ void OnGUI()
{
- if (_allSpawnableItems.Count == 0)
+ if (!_showSpawnWindow)
+ return;
+
+ // Set depth to ensure window is on top
+ UnityEngine.GUI.depth = -1000;
+
+ // Draw window and bring to front
+ _spawnWindowRect = UnityEngine.GUI.Window(12345, _spawnWindowRect, DrawSpawnWindow, "Spawn Items (F10 to close)");
+ UnityEngine.GUI.BringWindowToFront(12345);
+ }
+
+ ///
+ /// Draws the spawn window contents.
+ ///
+ private void DrawSpawnWindow(int windowID)
+ {
+ UnityEngine.GUILayout.BeginVertical();
+
+ // Storage items
+ UnityEngine.GUILayout.Label("Storage Items:", UnityEngine.GUI.skin.box);
+
+ if (UnityEngine.GUILayout.Button("Card Binder"))
{
- Debug.LogWarning("[TradingCardMod] No items registered to spawn!");
+ SpawnStorageItem(_cardBoxItem, "Card Binder");
+ }
+
+ if (UnityEngine.GUILayout.Button("Binder Sheet"))
+ {
+ SpawnStorageItem(_binderItem, "Binder Sheet");
+ }
+
+ UnityEngine.GUILayout.Space(10);
+
+ // Random cards by rarity
+ UnityEngine.GUILayout.Label("Spawn Random Card:", UnityEngine.GUI.skin.box);
+
+ if (UnityEngine.GUILayout.Button("Random Common Card"))
+ {
+ SpawnRandomCardByRarity("Common");
+ }
+
+ if (UnityEngine.GUILayout.Button("Random Uncommon Card"))
+ {
+ SpawnRandomCardByRarity("Uncommon");
+ }
+
+ if (UnityEngine.GUILayout.Button("Random Rare Card"))
+ {
+ SpawnRandomCardByRarity("Rare");
+ }
+
+ if (UnityEngine.GUILayout.Button("Random Very Rare Card"))
+ {
+ SpawnRandomCardByRarity("Very Rare");
+ }
+
+ if (UnityEngine.GUILayout.Button("Random Ultra Rare Card"))
+ {
+ SpawnRandomCardByRarity("Ultra Rare");
+ }
+
+ UnityEngine.GUILayout.EndVertical();
+
+ // Make window draggable
+ UnityEngine.GUI.DragWindow();
+ }
+
+ ///
+ /// Spawns a storage item (binder or binder sheet).
+ ///
+ private void SpawnStorageItem(Item? prefab, string itemName)
+ {
+ if (prefab == null)
+ {
+ Debug.LogWarning($"[TradingCardMod] {itemName} not available!");
return;
}
- // Cycle through all spawnable items
- Item prefab = _allSpawnableItems[_debugSpawnIndex % _allSpawnableItems.Count];
- _debugSpawnIndex++;
-
try
{
- // Instantiate a fresh copy of the item (don't send prefab directly)
Item instance = ItemAssetsCollection.InstantiateSync(prefab.TypeID);
if (instance != null)
{
- // Use game's utility to give item to player
ItemUtilities.SendToPlayer(instance);
- Debug.Log($"[TradingCardMod] Spawned: {instance.DisplayName} (ID: {instance.TypeID})");
+ Debug.Log($"[TradingCardMod] Spawned: {itemName}");
}
else
{
- Debug.LogError($"[TradingCardMod] Failed to instantiate {prefab.DisplayName} (ID: {prefab.TypeID})");
+ Debug.LogError($"[TradingCardMod] Failed to instantiate {itemName}");
}
}
catch (Exception ex)
{
- Debug.LogError($"[TradingCardMod] Failed to spawn item: {ex.Message}");
+ Debug.LogError($"[TradingCardMod] Failed to spawn {itemName}: {ex.Message}");
+ }
+ }
+
+ ///
+ /// Spawns a random card of the specified rarity.
+ ///
+ private void SpawnRandomCardByRarity(string rarity)
+ {
+ // Find all cards of this rarity
+ var matchingCards = _loadedCards
+ .Where(c => c.Rarity.Equals(rarity, StringComparison.OrdinalIgnoreCase))
+ .ToList();
+
+ if (matchingCards.Count == 0)
+ {
+ Debug.LogWarning($"[TradingCardMod] No {rarity} cards found!");
+ return;
+ }
+
+ // Pick a random card
+ TradingCard randomCard = matchingCards[_random.Next(matchingCards.Count)];
+
+ // Get the item ID for this card
+ if (!_cardNameToTypeId.TryGetValue(randomCard.CardName, out int typeId))
+ {
+ Debug.LogError($"[TradingCardMod] Card '{randomCard.CardName}' not registered!");
+ return;
+ }
+
+ try
+ {
+ Item instance = ItemAssetsCollection.InstantiateSync(typeId);
+ if (instance != null)
+ {
+ ItemUtilities.SendToPlayer(instance);
+ Debug.Log($"[TradingCardMod] Spawned random {rarity}: {randomCard.CardName}");
+ }
+ else
+ {
+ Debug.LogError($"[TradingCardMod] Failed to instantiate card: {randomCard.CardName}");
+ }
+ }
+ catch (Exception ex)
+ {
+ Debug.LogError($"[TradingCardMod] Failed to spawn card: {ex.Message}");
}
}
@@ -604,6 +717,12 @@ namespace TradingCardMod
item.Tags.Add(_tradingCardTag);
}
+ // Add CardBinderContent tag so cards can be stored in Card Binders
+ if (_cardBinderContentTag != null)
+ {
+ item.Tags.Add(_cardBinderContentTag);
+ }
+
// Load and set icon
Sprite? cardSprite = LoadSpriteFromFile(card.ImagePath, typeId);
if (cardSprite != null)
@@ -793,7 +912,6 @@ namespace TradingCardMod
_cardNameToTypeId.Clear();
_registeredPacks.Clear();
_packDefinitions.Clear();
- _allSpawnableItems.Clear();
Debug.Log("[TradingCardMod] Cleanup complete.");
}
diff --git a/src/TagHelper.cs b/src/TagHelper.cs
index c640369..537010d 100644
--- a/src/TagHelper.cs
+++ b/src/TagHelper.cs
@@ -92,6 +92,16 @@ namespace TradingCardMod
return CreateOrCloneTag("BinderSheet", "Binder Sheet");
}
+ ///
+ /// Gets the "CardBinderContent" tag, creating it if it doesn't exist.
+ /// This is a parent tag shared by both cards and binder sheets, allowing both to be stored in card binders.
+ ///
+ /// The CardBinderContent tag.
+ public static Tag GetOrCreateCardBinderContentTag()
+ {
+ return CreateOrCloneTag("CardBinderContent", "Card Binder Content");
+ }
+
///
/// Gets all tags created by this mod.
///