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. ///