Files
AppleHillsProduction/Assets/Scripts/CardSystem/Data/CardInventory.cs

236 lines
7.6 KiB
C#
Raw Normal View History

2025-10-14 14:57:50 +02:00
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace AppleHills.Data.CardSystem
{
/// <summary>
/// Manages the player's collection of cards and booster packs
/// </summary>
[Serializable]
public class CardInventory
{
2025-11-06 23:06:41 +01:00
// Dictionary of collected cards indexed by definition ID + rarity (e.g., "Pikachu_Normal", "Pikachu_Rare")
2025-10-14 14:57:50 +02:00
[SerializeField] private Dictionary<string, CardData> collectedCards = new Dictionary<string, CardData>();
2025-11-06 23:06:41 +01:00
/// <summary>
/// Generate a unique key for a card based on definition ID and rarity
/// </summary>
private string GetCardKey(string definitionId, CardRarity rarity)
{
return $"{definitionId}_{rarity}";
}
2025-10-14 14:57:50 +02:00
// Number of unopened booster packs the player has
[SerializeField] private int boosterPackCount;
// Additional lookup dictionaries (not serialized)
[NonSerialized] private Dictionary<CardZone, List<CardData>> cardsByZone = new Dictionary<CardZone, List<CardData>>();
[NonSerialized] private Dictionary<CardRarity, List<CardData>> cardsByRarity = new Dictionary<CardRarity, List<CardData>>();
// Properties with public getters
public Dictionary<string, CardData> CollectedCards => collectedCards;
public int BoosterPackCount
{
get => boosterPackCount;
set => boosterPackCount = value;
}
// Constructor initializes empty dictionaries
public CardInventory()
{
// Initialize dictionaries for all enum values so we never have to check for null
foreach (CardZone zone in Enum.GetValues(typeof(CardZone)))
{
cardsByZone[zone] = new List<CardData>();
}
foreach (CardRarity rarity in Enum.GetValues(typeof(CardRarity)))
{
cardsByRarity[rarity] = new List<CardData>();
}
}
/// <summary>
/// Get all cards in the player's collection as a list
/// </summary>
public List<CardData> GetAllCards()
{
2025-10-20 13:45:56 +02:00
return collectedCards.Values.ToList();
}
/// <summary>
/// Clears all cards from the inventory
/// Primarily used for testing
/// </summary>
public void ClearAllCards()
{
collectedCards.Clear();
// Clear lookup dictionaries
foreach (var zone in cardsByZone.Keys)
{
cardsByZone[zone].Clear();
}
foreach (var rarity in cardsByRarity.Keys)
{
cardsByRarity[rarity].Clear();
}
2025-10-14 14:57:50 +02:00
}
/// <summary>
/// Get cards filtered by zone
/// </summary>
public List<CardData> GetCardsByZone(CardZone zone)
{
return new List<CardData>(cardsByZone[zone]);
}
/// <summary>
/// Get cards filtered by rarity
/// </summary>
public List<CardData> GetCardsByRarity(CardRarity rarity)
{
return new List<CardData>(cardsByRarity[rarity]);
}
/// <summary>
/// Add a card to the inventory (or increase the copies if already owned)
/// </summary>
public void AddCard(CardData card)
{
if (card == null) return;
2025-11-06 23:06:41 +01:00
string key = GetCardKey(card.DefinitionId, card.Rarity);
if (collectedCards.TryGetValue(key, out CardData existingCard))
2025-10-14 14:57:50 +02:00
{
// Increase copies of existing card
existingCard.CopiesOwned++;
}
else
{
// Add new card to collection
var newCard = new CardData(card);
2025-11-06 23:06:41 +01:00
collectedCards[key] = newCard;
2025-10-14 14:57:50 +02:00
// Add to lookup dictionaries
cardsByZone[newCard.Zone].Add(newCard);
cardsByRarity[newCard.Rarity].Add(newCard);
}
}
/// <summary>
/// Update card zone and rarity indexes when a card changes
/// </summary>
public void UpdateCardProperties(CardData card, CardZone oldZone, CardRarity oldRarity)
{
// Only needed if the card's zone or rarity actually changed
if (oldZone != card.Zone)
{
cardsByZone[oldZone].Remove(card);
cardsByZone[card.Zone].Add(card);
}
if (oldRarity != card.Rarity)
{
cardsByRarity[oldRarity].Remove(card);
cardsByRarity[card.Rarity].Add(card);
}
}
/// <summary>
2025-11-06 23:06:41 +01:00
/// Get a specific card from the collection by definition ID and rarity
2025-10-14 14:57:50 +02:00
/// </summary>
2025-11-06 23:06:41 +01:00
public CardData GetCard(string definitionId, CardRarity rarity)
2025-10-14 14:57:50 +02:00
{
2025-11-06 23:06:41 +01:00
string key = GetCardKey(definitionId, rarity);
return collectedCards.TryGetValue(key, out CardData card) ? card : null;
2025-10-14 14:57:50 +02:00
}
/// <summary>
2025-11-06 23:06:41 +01:00
/// Check if the player has a specific card at a specific rarity
2025-10-14 14:57:50 +02:00
/// </summary>
2025-11-06 23:06:41 +01:00
public bool HasCard(string definitionId, CardRarity rarity)
2025-10-14 14:57:50 +02:00
{
2025-11-06 23:06:41 +01:00
string key = GetCardKey(definitionId, rarity);
return collectedCards.ContainsKey(key);
2025-10-14 14:57:50 +02:00
}
/// <summary>
/// Get total number of unique cards in collection
/// </summary>
public int GetUniqueCardCount()
{
return collectedCards.Count;
}
/// <summary>
/// Get total number of cards including copies
/// </summary>
public int GetTotalCardCount()
{
return collectedCards.Values.Sum(card => card.CopiesOwned);
}
/// <summary>
/// Get number of cards in a specific zone
/// </summary>
public int GetZoneCardCount(CardZone zone)
{
return cardsByZone[zone].Count;
}
/// <summary>
/// Get number of cards of a specific rarity
/// </summary>
public int GetRarityCardCount(CardRarity rarity)
{
return cardsByRarity[rarity].Count;
}
/// <summary>
/// Get cards sorted by collection index (for album view)
/// </summary>
public List<CardData> GetCardsSortedByIndex()
{
return collectedCards.Values
.OrderBy(card => card.CollectionIndex)
.ToList();
}
/// <summary>
/// Check if there's a complete collection for a specific zone
/// </summary>
public bool IsZoneCollectionComplete(CardZone zone, List<CardDefinition> allAvailableCards)
{
int availableInZone = allAvailableCards.Count(card => card.Zone == zone);
int collectedInZone = cardsByZone[zone].Count;
return availableInZone > 0 && collectedInZone >= availableInZone;
}
/// <summary>
/// Adds booster packs to the inventory
/// </summary>
public void AddBoosterPacks(int count)
{
boosterPackCount += count;
}
/// <summary>
/// Use a single booster pack (returns true if successful)
/// </summary>
public bool UseBoosterPack()
{
if (boosterPackCount <= 0) return false;
boosterPackCount--;
return true;
}
}
}