Kind of working booster packs

This commit is contained in:
Michal Adam Pikulski
2025-10-20 13:45:56 +02:00
parent 32f726d229
commit 83b5c8994d
12 changed files with 1244 additions and 299 deletions

View File

@@ -50,7 +50,27 @@ namespace AppleHills.Data.CardSystem
/// </summary>
public List<CardData> GetAllCards()
{
return new List<CardData>(collectedCards.Values);
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();
}
}
/// <summary>

View File

@@ -273,5 +273,79 @@ namespace Data.CardSystem
return (float)collectedInZone / totalInZone * 100f;
}
/// <summary>
/// Returns all available card definitions in the system
/// </summary>
public List<CardDefinition> GetAllCardDefinitions()
{
return new List<CardDefinition>(availableCards);
}
/// <summary>
/// Returns direct access to the player's card inventory
/// For advanced operations and testing
/// </summary>
public CardInventory GetCardInventory()
{
return playerInventory;
}
/// <summary>
/// Returns cards filtered by both zone and rarity
/// </summary>
public List<CardData> GetCardsByZoneAndRarity(CardZone zone, CardRarity rarity)
{
List<CardData> zoneCards = GetCardsByZone(zone);
return zoneCards.FindAll(c => c.Rarity == rarity);
}
/// <summary>
/// Returns the count of cards by rarity
/// </summary>
public int GetCardCountByRarity(CardRarity rarity)
{
return playerInventory.GetCardsByRarity(rarity).Count;
}
/// <summary>
/// Returns the count of cards by zone
/// </summary>
public int GetCardCountByZone(CardZone zone)
{
return playerInventory.GetCardsByZone(zone).Count;
}
/// <summary>
/// Gets the total number of card definitions available in the system
/// </summary>
public int GetTotalCardDefinitionsCount()
{
return availableCards.Count;
}
/// <summary>
/// Gets the total collection completion percentage (0-100)
/// </summary>
public float GetTotalCompletionPercentage()
{
if (availableCards.Count == 0) return 0;
return (float)GetUniqueCardCount() / availableCards.Count * 100f;
}
/// <summary>
/// Gets total completion percentage for a specific rarity (0-100)
/// </summary>
public float GetRarityCompletionPercentage(CardRarity rarity)
{
// Count available cards of this rarity
int totalOfRarity = availableCards.FindAll(c => c.Rarity == rarity).Count;
if (totalOfRarity == 0) return 0;
// Count collected cards of this rarity
int collectedOfRarity = playerInventory.GetCardsByRarity(rarity).Count;
return (float)collectedOfRarity / totalOfRarity * 100f;
}
}
}

View File

@@ -16,7 +16,6 @@ namespace AppleHills.Tests
public class CardSystemTester : MonoBehaviour
{
[Header("References")]
[SerializeField] private CardSystemManager cardSystemManager;
[SerializeField] private CardAlbumUI cardAlbumUI;
[Header("Test Settings")]
@@ -32,16 +31,10 @@ namespace AppleHills.Tests
private void Awake()
{
// Auto-find references if needed
if (cardSystemManager == null)
cardSystemManager = FindAnyObjectByType<CardSystemManager>();
if (cardAlbumUI == null)
cardAlbumUI = FindAnyObjectByType<CardAlbumUI>();
// Log missing references
if (cardSystemManager == null)
Debug.LogError("CardSystemTester: No CardSystemManager found in the scene!");
if (cardAlbumUI == null)
Debug.LogError("CardSystemTester: No CardAlbumUI found in the scene!");
}
@@ -54,10 +47,11 @@ namespace AppleHills.Tests
// Refresh the debug information displayed in the inspector
private void RefreshDebugInfo()
{
if (cardSystemManager != null)
// Access CardSystemManager through the singleton Instance
if (CardSystemManager.Instance != null)
{
currentBoosterCount = cardSystemManager.GetBoosterPackCount();
totalCardsInCollection = cardSystemManager.GetCardInventory().GetAllCards().Count;
currentBoosterCount = CardSystemManager.Instance.GetBoosterPackCount();
totalCardsInCollection = CardSystemManager.Instance.GetCardInventory().GetAllCards().Count;
}
}
@@ -65,9 +59,10 @@ namespace AppleHills.Tests
// Custom editor buttons for testing
public void AddBoosterPacks()
{
if (cardSystemManager != null)
// Access CardSystemManager through the singleton Instance
if (CardSystemManager.Instance != null)
{
cardSystemManager.AddBoosterPack(boosterPacksToAdd);
CardSystemManager.Instance.AddBoosterPack(boosterPacksToAdd);
lastActionMessage = $"Added {boosterPacksToAdd} booster pack(s)";
Logging.Debug($"[CardSystemTester] {lastActionMessage}");
RefreshDebugInfo();
@@ -135,10 +130,11 @@ namespace AppleHills.Tests
public void GenerateRandomCards()
{
if (cardSystemManager != null)
// Access CardSystemManager through the singleton Instance
if (CardSystemManager.Instance != null)
{
int cardsAdded = 0;
List<CardDefinition> allDefinitions = cardSystemManager.GetAllCardDefinitions();
List<CardDefinition> allDefinitions = CardSystemManager.Instance.GetAllCardDefinitions();
if (allDefinitions.Count == 0)
{
@@ -154,7 +150,7 @@ namespace AppleHills.Tests
// Create a card data instance and add it to inventory
CardData newCard = randomDef.CreateCardData();
cardSystemManager.GetCardInventory().AddCard(newCard);
CardSystemManager.Instance.GetCardInventory().AddCard(newCard);
cardsAdded++;
}
@@ -166,21 +162,17 @@ namespace AppleHills.Tests
public void ClearAllCards()
{
if (cardSystemManager != null)
// Access CardSystemManager through the singleton Instance
if (CardSystemManager.Instance != null)
{
int count = cardSystemManager.GetCardInventory().GetAllCards().Count;
cardSystemManager.GetCardInventory().ClearAllCards();
int count = CardSystemManager.Instance.GetCardInventory().GetAllCards().Count;
CardSystemManager.Instance.GetCardInventory().ClearAllCards();
lastActionMessage = $"Cleared {count} cards from inventory";
Logging.Debug($"[CardSystemTester] {lastActionMessage}");
RefreshDebugInfo();
}
}
#endif
// Update is called once per frame
void Update()
{
}
}
#if UNITY_EDITOR
@@ -196,6 +188,9 @@ namespace AppleHills.Tests
EditorGUILayout.Space();
EditorGUILayout.LabelField("Test Actions", EditorStyles.boldLabel);
// Only enable buttons when in play mode
GUI.enabled = Application.isPlaying;
if (GUILayout.Button("Add Booster Packs"))
{
tester.AddBoosterPacks();
@@ -227,6 +222,13 @@ namespace AppleHills.Tests
{
tester.ClearAllCards();
}
// If not in play mode, show a hint
if (!Application.isPlaying)
{
GUI.enabled = true;
EditorGUILayout.HelpBox("Enter Play Mode to use these testing functions.", MessageType.Info);
}
}
}
#endif

View File

@@ -77,158 +77,108 @@ namespace AppleHills.UI.CardSystem
if (collectedCards.Count > 0)
{
// Create card UI elements
CreateCardStack(collectedCards);
DisplayCards(collectedCards);
}
}
/// <summary>
/// Creates UI elements for the player's collected cards
/// </summary>
private void CreateCardStack(List<CardData> cards)
private void DisplayCards(List<CardData> cards)
{
if (albumGrid == null || cardPrefab == null) return;
// Stack offset for visual effect
Vector3 stackOffset = new Vector3(5f, -5f, 0f);
Vector3 basePosition = Vector3.zero;
// Sort cards by collection index
cards.Sort((a, b) => a.CollectionIndex.CompareTo(b.CollectionIndex));
// Create card UI elements
for (int i = 0; i < cards.Count; i++)
foreach (var cardData in cards)
{
GameObject cardObj = Instantiate(cardPrefab, albumGrid.transform);
CardUIElement cardUI = cardObj.GetComponent<CardUIElement>();
// Configure the card UI with the card data
CardUIElement cardUI = cardObj.GetComponent<CardUIElement>();
if (cardUI != null)
{
// Position in stack
cardObj.GetComponent<RectTransform>().anchoredPosition = basePosition + (stackOffset * i);
// Set up card data
cardUI.SetupCard(cards[i]);
// Add drag handlers
SetupCardDragHandlers(cardUI);
// Add to tracked cards
cardUI.SetupCard(cardData);
_displayedCards.Add(cardUI);
}
}
}
/// <summary>
/// Sets up drag and drop handlers for a card
/// </summary>
private void SetupCardDragHandlers(CardUIElement cardUI)
{
// Add click listener to handle card clicks
Button cardButton = cardUI.GetComponent<Button>();
if (cardButton != null)
{
cardButton.onClick.AddListener(() => OnCardClicked(cardUI));
}
// Subscribe to the card's own click event
cardUI.OnCardClicked += OnCardClicked;
}
/// <summary>
/// Handles when a card is clicked (simplistic alternative to drag and drop)
/// </summary>
private void OnCardClicked(CardUIElement cardUI)
{
CardData cardData = cardUI.GetCardData();
// Currently, clicking a card does not perform any action
// This can be expanded to show card details or other interactions
}
/// <summary>
/// Clears all cards from the album
/// Clears all card UI elements from the album
/// </summary>
private void ClearAlbum()
{
// Clear card UI elements
foreach (var card in _displayedCards)
{
if (card != null && card.gameObject != null)
{
Destroy(card.gameObject);
}
}
_displayedCards.Clear();
}
/// <summary>
/// Initialize filtering UI and set up listeners
/// Initializes filter dropdowns
/// </summary>
private void InitializeFilters()
{
// Setup zone filter
// Setup zone filter dropdown
if (zoneFilterDropdown != null)
{
zoneFilterDropdown.ClearOptions();
// Add "All Zones" option
List<string> zoneOptions = new List<string> { "All Zones" };
List<string> zoneOptions = new List<string>() { "All Zones" };
// Add each zone
// Add options for each zone
foreach (CardZone zone in System.Enum.GetValues(typeof(CardZone)))
{
zoneOptions.Add(zone.ToString());
}
zoneFilterDropdown.AddOptions(zoneOptions);
zoneFilterDropdown.onValueChanged.AddListener(OnZoneFilterChanged);
zoneFilterDropdown.onValueChanged.AddListener(OnFilterChanged);
}
// Setup rarity filter
// Setup rarity filter dropdown
if (rarityFilterDropdown != null)
{
rarityFilterDropdown.ClearOptions();
// Add "All Rarities" option
List<string> rarityOptions = new List<string> { "All Rarities" };
List<string> rarityOptions = new List<string>() { "All Rarities" };
// Add each rarity
// Add options for each rarity
foreach (CardRarity rarity in System.Enum.GetValues(typeof(CardRarity)))
{
rarityOptions.Add(rarity.ToString());
}
rarityFilterDropdown.AddOptions(rarityOptions);
rarityFilterDropdown.onValueChanged.AddListener(OnRarityFilterChanged);
rarityFilterDropdown.onValueChanged.AddListener(OnFilterChanged);
}
// Setup reset button
// Setup reset filters button
if (resetFiltersButton != null)
{
resetFiltersButton.onClick.AddListener(ResetFilters);
resetFiltersButton.onClick.AddListener(OnResetFiltersClicked);
}
}
/// <summary>
/// Called when zone filter dropdown changes
/// Handles changes to the filter dropdowns
/// </summary>
private void OnZoneFilterChanged(int index)
private void OnFilterChanged(int value)
{
ApplyFilters();
}
/// <summary>
/// Called when rarity filter dropdown changes
/// Resets all filters to their default values
/// </summary>
private void OnRarityFilterChanged(int index)
{
ApplyFilters();
}
/// <summary>
/// Reset all filters to default values
/// </summary>
private void ResetFilters()
private void OnResetFiltersClicked()
{
if (zoneFilterDropdown != null)
zoneFilterDropdown.value = 0;
@@ -240,97 +190,68 @@ namespace AppleHills.UI.CardSystem
}
/// <summary>
/// Apply current filter settings to the displayed cards
/// Applies the current filter selections to the displayed cards
/// </summary>
private void ApplyFilters()
{
if (_cardManager == null) return;
// Clear current cards
ClearAlbum();
// Get all cards
List<CardData> allCards = _cardManager.GetAllCollectedCards();
List<CardData> filteredCards = new List<CardData>(allCards);
// Get selected filters
CardZone? selectedZone = null;
CardRarity? selectedRarity = null;
// Apply zone filter
// Get zone filter value
if (zoneFilterDropdown != null && zoneFilterDropdown.value > 0)
{
CardZone selectedZone = (CardZone)(zoneFilterDropdown.value - 1);
filteredCards = filteredCards.FindAll(card => card.Zone == selectedZone);
selectedZone = (CardZone)(zoneFilterDropdown.value - 1);
}
// Apply rarity filter
// Get rarity filter value
if (rarityFilterDropdown != null && rarityFilterDropdown.value > 0)
{
CardRarity selectedRarity = (CardRarity)(rarityFilterDropdown.value - 1);
filteredCards = filteredCards.FindAll(card => card.Rarity == selectedRarity);
selectedRarity = (CardRarity)(rarityFilterDropdown.value - 1);
}
// Update the displayed cards
ClearAlbum();
CreateCardStack(filteredCards);
// Get filtered cards
List<CardData> filteredCards = GetFilteredCards(selectedZone, selectedRarity);
// Create card UI elements for the filtered cards
DisplayCards(filteredCards);
Logging.Debug($"[AlbumViewPage] Applied filters. Showing {filteredCards.Count} cards.");
}
// Override for transition animations
protected override void DoTransitionIn(System.Action onComplete)
/// <summary>
/// Gets cards filtered by zone and/or rarity
/// </summary>
private List<CardData> GetFilteredCards(CardZone? zone, CardRarity? rarity)
{
// Reset the canvas group
if (canvasGroup != null)
List<CardData> result;
// Get all collected cards
if (zone == null && rarity == null)
{
canvasGroup.alpha = 0f;
Tween.Value(0f, 1f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete);
// No filters, return all cards
result = _cardManager.GetAllCollectedCards();
}
else if (zone != null && rarity != null)
{
// Both filters, get cards by zone and rarity
result = _cardManager.GetCardsByZoneAndRarity(zone.Value, rarity.Value);
}
else if (zone != null)
{
// Only zone filter
result = _cardManager.GetCardsByZone(zone.Value);
}
else
{
// Simple scale animation if no canvas group
transform.localScale = Vector3.zero;
Tween.LocalScale(transform, Vector3.one, transitionDuration, 0f, Tween.EaseOutBack, Tween.LoopType.None, null, onComplete);
// Only rarity filter
result = _cardManager.GetCardsByRarity(rarity.Value);
}
}
protected override void DoTransitionOut(System.Action onComplete)
{
// Simple fade animation
if (canvasGroup != null)
{
Tween.Value(canvasGroup.alpha, 0f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete);
}
else
{
Tween.LocalScale(transform, Vector3.zero, transitionDuration, 0f, Tween.EaseInBack, Tween.LoopType.None, null, onComplete);
}
}
private void OnDestroy()
{
// Clean up filter listeners
if (zoneFilterDropdown != null)
zoneFilterDropdown.onValueChanged.RemoveListener(OnZoneFilterChanged);
if (rarityFilterDropdown != null)
rarityFilterDropdown.onValueChanged.RemoveListener(OnRarityFilterChanged);
if (resetFiltersButton != null)
resetFiltersButton.onClick.RemoveListener(ResetFilters);
// Clean up back button listener
if (backButton != null)
backButton.onClick.RemoveListener(OnBackButtonClicked);
// Clean up card listeners
foreach (var card in _displayedCards)
{
if (card != null)
{
// Unsubscribe from card events
card.OnCardClicked -= OnCardClicked;
// Remove button listeners
Button cardButton = card.GetComponent<Button>();
if (cardButton != null)
{
cardButton.onClick.RemoveAllListeners();
}
}
}
return result;
}
/// <summary>
@@ -345,5 +266,66 @@ namespace AppleHills.UI.CardSystem
pageController.PopPage();
}
}
protected override void DoTransitionIn(System.Action onComplete)
{
// Simple fade in animation
if (canvasGroup != null)
{
canvasGroup.alpha = 0f;
Tween.Value(0f, 1f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete);
}
else
{
// Fallback if no CanvasGroup
onComplete?.Invoke();
}
}
protected override void DoTransitionOut(System.Action onComplete)
{
// Simple fade out animation
if (canvasGroup != null)
{
Tween.Value(canvasGroup.alpha, 0f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete);
}
else
{
// Fallback if no CanvasGroup
onComplete?.Invoke();
}
}
private void OnDestroy()
{
// Clean up button listeners
if (backButton != null)
{
backButton.onClick.RemoveListener(OnBackButtonClicked);
}
if (zoneFilterDropdown != null)
{
zoneFilterDropdown.onValueChanged.RemoveListener(OnFilterChanged);
}
if (rarityFilterDropdown != null)
{
rarityFilterDropdown.onValueChanged.RemoveListener(OnFilterChanged);
}
if (resetFiltersButton != null)
{
resetFiltersButton.onClick.RemoveListener(OnResetFiltersClicked);
}
}
private void OnEnable()
{
if (_cardManager == null)
{
_cardManager = CardSystemManager.Instance;
}
}
}
}

View File

@@ -17,9 +17,8 @@ namespace AppleHills.UI.CardSystem
{
[Header("UI Elements")]
[SerializeField] private GameObject boosterPackObject;
[SerializeField] private RectTransform cardRevealContainer; // This should have a HorizontalLayoutGroup component
[SerializeField] private RectTransform cardRevealContainer; // This should have a HorizontalLayoutGroup component with pre-populated card backs
[SerializeField] private GameObject cardPrefab;
[SerializeField] private GameObject cardBackPrefab;
[SerializeField] private Button openBoosterButton;
[SerializeField] private Button continueButton;
[SerializeField] private CanvasGroup canvasGroup;
@@ -45,7 +44,7 @@ namespace AppleHills.UI.CardSystem
private OpeningState _currentState = OpeningState.BoosterReady;
private List<CardUIElement> _revealedCards = new List<CardUIElement>();
private List<GameObject> _cardBacks = new List<GameObject>();
private List<Button> _cardBackButtons = new List<Button>();
private List<CardData> _boosterCards = new List<CardData>();
private int _revealedCardCount = 0;
private CardSystemManager _cardManager;
@@ -80,6 +79,47 @@ namespace AppleHills.UI.CardSystem
canvasGroup = GetComponent<CanvasGroup>();
if (canvasGroup == null)
canvasGroup = gameObject.AddComponent<CanvasGroup>();
// Cache card back buttons from container
CacheCardBackButtons();
// Initially hide all card backs
HideAllCardBacks();
}
/// <summary>
/// Cache all card back buttons from the container
/// </summary>
private void CacheCardBackButtons()
{
_cardBackButtons.Clear();
if (cardRevealContainer != null)
{
// Get all buttons in the container (these are our card backs)
Button[] buttonsInContainer = cardRevealContainer.GetComponentsInChildren<Button>(true);
_cardBackButtons.AddRange(buttonsInContainer);
Debug.Log($"[BoosterOpeningPage] Found {_cardBackButtons.Count} card back buttons in container");
}
else
{
Debug.LogError("[BoosterOpeningPage] Card reveal container is null, can't find card backs!");
}
}
/// <summary>
/// Hides all card backs in the container
/// </summary>
private void HideAllCardBacks()
{
foreach (var cardBack in _cardBackButtons)
{
if (cardBack != null && cardBack.gameObject != null)
{
cardBack.gameObject.SetActive(false);
}
}
}
private void OnDestroy()
@@ -148,22 +188,31 @@ namespace AppleHills.UI.CardSystem
}
_revealedCards.Clear();
// Clear card backs
foreach (var cardBack in _cardBacks)
// Re-cache card backs in case they changed
CacheCardBackButtons();
// Reset all card backs - both visibility and scale
foreach (var cardBack in _cardBackButtons)
{
if (cardBack != null)
Destroy(cardBack);
if (cardBack != null && cardBack.gameObject != null)
{
cardBack.gameObject.SetActive(false);
cardBack.transform.localScale = Vector3.one; // Reset scale
cardBack.transform.localRotation = Quaternion.identity; // Reset rotation
}
}
_cardBacks.Clear();
// Reset state
_currentState = OpeningState.BoosterReady;
_revealedCardCount = 0;
_boosterCards.Clear();
// Show booster pack, show open button, hide continue button
if (boosterPackObject != null)
{
boosterPackObject.SetActive(true);
boosterPackObject.transform.localScale = Vector3.one; // Reset scale
boosterPackObject.transform.localRotation = Quaternion.identity; // Reset rotation
}
if (openBoosterButton != null)
@@ -174,6 +223,7 @@ namespace AppleHills.UI.CardSystem
if (continueButton != null)
{
continueButton.gameObject.SetActive(false);
continueButton.transform.localScale = Vector3.one; // Reset scale
}
// Make back button visible
@@ -181,6 +231,8 @@ namespace AppleHills.UI.CardSystem
{
backButton.gameObject.SetActive(true);
}
Debug.Log("[BoosterOpeningPage] State reset complete, all scales and rotations reset to defaults");
}
/// <summary>
@@ -229,32 +281,46 @@ namespace AppleHills.UI.CardSystem
// Wait a short delay before showing card backs
yield return new WaitForSeconds(0.5f);
// Create card backs for each position (usually 3)
for (int i = 0; i < Mathf.Min(_boosterCards.Count, cardRevealContainer.childCount); i++)
// Check if we have proper container setup
if (cardRevealContainer == null)
{
if (cardBackPrefab == null || cardRevealContainer.GetChild(i) == null) continue;
Debug.LogError("[BoosterOpeningPage] Card reveal container is null!");
yield break;
}
// Check if we found any card backs
if (_cardBackButtons.Count == 0)
{
Debug.LogError("[BoosterOpeningPage] No card back buttons found in container!");
yield break;
}
// Determine how many cards to show based on the booster cards and available card backs
int cardsToShow = Mathf.Min(_boosterCards.Count, _cardBackButtons.Count);
// Activate and animate the card backs
for (int i = 0; i < cardsToShow; i++)
{
Button cardBack = _cardBackButtons[i];
if (cardBack == null) continue;
// Instantiate card back object at the correct position
GameObject cardBackObj = Instantiate(cardBackPrefab, cardRevealContainer.GetChild(i));
cardBackObj.transform.localPosition = Vector3.zero;
_cardBacks.Add(cardBackObj);
GameObject cardBackObj = cardBack.gameObject;
// Ensure the card back is active
cardBackObj.SetActive(true);
// Store the index for later reference when clicked
int cardIndex = i;
// Add click handler to the card back
Button cardBackButton = cardBackObj.GetComponent<Button>();
if (cardBackButton == null)
{
cardBackButton = cardBackObj.AddComponent<Button>();
}
// Configure the button
cardBackButton.onClick.AddListener(() => OnCardBackClicked(cardIndex));
cardBack.onClick.RemoveAllListeners(); // Clear any previous listeners
cardBack.onClick.AddListener(() => OnCardBackClicked(cardIndex));
// Set initial scale to zero for animation
cardBackObj.transform.localScale = Vector3.zero;
Debug.Log($"[BoosterOpeningPage] Card back {i} activated");
// Play reveal animation using Pixelplacement.Tween
Tween.LocalScale(cardBackObj.transform, Vector3.one, 0.5f, 0f, Tween.EaseOutBack);
@@ -264,6 +330,7 @@ namespace AppleHills.UI.CardSystem
// Update state
_currentState = OpeningState.CardBacksVisible;
Debug.Log($"[BoosterOpeningPage] All {cardsToShow} card backs should now be visible");
}
/// <summary>
@@ -271,140 +338,213 @@ namespace AppleHills.UI.CardSystem
/// </summary>
private void OnCardBackClicked(int cardIndex)
{
Logging.Debug($"[BoosterOpeningPage] Card back clicked at index {cardIndex}");
// Only respond to clicks when in the appropriate state
if (_currentState != OpeningState.CardBacksVisible) return;
if (_currentState != OpeningState.CardBacksVisible)
{
Logging.Warning($"[BoosterOpeningPage] Card clicked in wrong state: {_currentState}");
return;
}
// Ensure the index is valid
if (cardIndex < 0 || cardIndex >= _boosterCards.Count || cardIndex >= _cardBacks.Count) return;
if (cardIndex < 0 || cardIndex >= _boosterCards.Count || cardIndex >= _cardBackButtons.Count)
{
Debug.LogError($"[BoosterOpeningPage] Invalid card index: {cardIndex}");
return;
}
// Get the card data and card back
CardData cardData = _boosterCards[cardIndex];
GameObject cardBack = _cardBacks[cardIndex];
Button cardBack = _cardBackButtons[cardIndex];
// Start the reveal animation for this specific card
StartCoroutine(RevealCard(cardIndex, cardData, cardBack));
StartCoroutine(RevealCard(cardIndex, cardData, cardBack.gameObject));
}
/// <summary>
/// Reveals an individual card with animation
/// </summary>
private IEnumerator RevealCard(int cardIndex, CardData cardData, GameObject cardBack)
{
if (cardBack == null || cardRevealContainer.GetChild(cardIndex) == null) yield break;
if (cardBack == null)
yield break;
// Start flip animation
Transform cardBackTransform = cardBack.transform;
// Step 1: Flip the card 90 degrees (showing the edge)
Tween.LocalRotation(cardBackTransform, new Vector3(0, 90, 0), flipAnimationDuration * 0.5f, 0);
// Wait for half the flip duration
yield return new WaitForSeconds(flipAnimationDuration * 0.5f);
// Step 2: Remove the card back and create the actual card
Destroy(cardBack);
_cardBacks[cardIndex] = null;
// Create the actual card at the same position
GameObject cardObj = Instantiate(cardPrefab, cardRevealContainer.GetChild(cardIndex));
cardObj.transform.localPosition = Vector3.zero;
cardObj.transform.localRotation = Quaternion.Euler(0, 90, 0); // Start at 90 degrees
// Set up the card data
CardUIElement cardUI = cardObj.GetComponent<CardUIElement>();
if (cardUI != null)
// Step 2: Hide the card back and show the actual card
cardBack.SetActive(false);
// Instantiate the card prefab at the same position
if (cardPrefab != null)
{
cardUI.SetupCard(cardData);
_revealedCards.Add(cardUI);
}
// Step 3: Complete the flip animation
Tween.LocalRotation(cardObj.transform, Vector3.zero, flipAnimationDuration * 0.5f, 0);
// Increment the revealed card count
_revealedCardCount++;
// If all cards have been revealed, show the continue button
if (_revealedCardCount >= _boosterCards.Count)
{
_currentState = OpeningState.CardsRevealed;
if (continueButton != null)
// Instantiate the card in the same parent as the card back and at the same position
GameObject cardObj = Instantiate(cardPrefab, cardBack.transform.parent);
cardObj.transform.SetSiblingIndex(cardBackTransform.GetSiblingIndex()); // Keep the same order in hierarchy
cardObj.transform.position = cardBackTransform.position; // Same world position
// Set initial rotation to continue the flip animation
cardObj.transform.localRotation = Quaternion.Euler(0, 90, 0);
// Configure the card UI with the card data
CardUIElement cardUI = cardObj.GetComponent<CardUIElement>();
if (cardUI != null)
{
continueButton.gameObject.SetActive(true);
// Animate button appearance
continueButton.transform.localScale = Vector3.zero;
Tween.LocalScale(continueButton.transform, Vector3.one, 0.3f, 0f, Tween.EaseOutBack);
cardUI.SetupCard(cardData);
_revealedCards.Add(cardUI);
// Play special effects based on card rarity
PlayRevealEffect(cardObj, cardData.Rarity);
}
// Step 3: Finish the flip animation (from 90 degrees to 0)
Tween.LocalRotation(cardObj.transform, Vector3.zero, flipAnimationDuration * 0.5f, 0);
// Increment counter of revealed cards
_revealedCardCount++;
// Update state if all cards are revealed
if (_revealedCardCount >= _boosterCards.Count)
{
_currentState = OpeningState.CardsRevealed;
// Show continue button after a short delay
StartCoroutine(ShowContinueButton());
}
}
}
/// <summary>
/// Handles click on the continue button after cards are revealed
/// Plays reveal effect for a card based on its rarity
/// </summary>
private void PlayRevealEffect(GameObject cardObject, CardRarity rarity)
{
// Add visual effect based on rarity
if (rarity >= CardRarity.Rare)
{
// For rare cards and above, add a particle effect
var particleSystem = cardObject.GetComponentInChildren<ParticleSystem>();
if (particleSystem != null)
{
particleSystem.Play();
}
// Scale up and down for emphasis
Transform cardTransform = cardObject.transform;
Vector3 originalScale = cardTransform.localScale;
// Sequence: Scale up slightly, then back to normal
Tween.LocalScale(cardTransform, originalScale * 1.2f, 0.2f, 0.1f, Tween.EaseOutBack);
Tween.LocalScale(cardTransform, originalScale, 0.15f, 0.3f, Tween.EaseIn);
// Play sound effect based on rarity (if available)
// This would require audio source components to be set up
}
}
/// <summary>
/// Shows the continue button after all cards are revealed
/// </summary>
private IEnumerator ShowContinueButton()
{
// Wait for a moment to let the user see all cards
yield return new WaitForSeconds(1.0f);
if (continueButton != null)
{
// Show the continue button with a nice animation
continueButton.gameObject.SetActive(true);
continueButton.transform.localScale = Vector3.zero;
Tween.LocalScale(continueButton.transform, Vector3.one, 0.3f, 0f, Tween.EaseOutBack);
}
}
/// <summary>
/// Handles click on the continue button
/// </summary>
private void OnContinueClicked()
{
if (_currentState != OpeningState.CardsRevealed) return;
_currentState = OpeningState.MovingToBackpack;
// Hide continue button
if (continueButton != null)
{
continueButton.gameObject.SetActive(false);
}
// Start moving cards to backpack animation
// Hide back button during transition
if (backButton != null)
{
backButton.gameObject.SetActive(false);
}
// Start animation to move cards to backpack
_moveToBackpackCoroutine = StartCoroutine(MoveCardsToBackpack());
}
/// <summary>
/// Animates cards moving to the backpack
/// Animates cards moving to the backpack icon
/// </summary>
private IEnumerator MoveCardsToBackpack()
{
// Use the backpackIcon from CardAlbumUI as the target
Vector3 targetPosition;
if (_cardAlbumUI != null && _cardAlbumUI.transform.Find("BackpackIcon") != null)
// Find the backpack icon position if available
Transform backpackTransform = null;
if (_cardAlbumUI != null && _cardAlbumUI.BackpackIcon != null)
{
// Get the world position of the backpack icon
targetPosition = _cardAlbumUI.transform.Find("BackpackIcon").position;
backpackTransform = _cardAlbumUI.BackpackIcon.transform;
}
else
if (backpackTransform == null)
{
// Fallback to a default position (lower-right corner)
targetPosition = new Vector3(Screen.width * 0.9f, Screen.height * 0.1f, 0f);
Logging.Warning("[BoosterOpeningPage] Couldn't find backpack icon, using default position.");
// If no backpack is found, just return to the menu
UIPageController.Instance.PopPage();
yield break;
}
// Move each card to backpack with animation
foreach (var cardUI in _revealedCards)
// Move each card to the backpack with slight delay between cards
for (int i = 0; i < _revealedCards.Count; i++)
{
if (cardUI != null)
CardUIElement card = _revealedCards[i];
if (card != null)
{
// Call card's move to backpack animation
cardUI.OnMoveToBackpackAnimation();
// Animate movement to backpack
Tween.Position(cardUI.transform, targetPosition, 0.5f, 0f, Tween.EaseInBack);
Tween.LocalScale(cardUI.transform, Vector3.zero, 0.5f, 0f, Tween.EaseInBack);
// Wait for delay between cards
yield return new WaitForSeconds(0.2f);
// Get the world position of the backpack
Vector3 backpackWorldPos = backpackTransform.position;
// Convert to local space of the card's parent for Tween
Vector3 targetPos = card.transform.parent.InverseTransformPoint(backpackWorldPos);
// Start the move animation
Tween.LocalPosition(card.transform, targetPos, 0.5f, cardMoveToBackpackDelay * i);
Tween.LocalScale(card.transform, Vector3.zero, 0.5f, cardMoveToBackpackDelay * i);
}
// Wait before starting the next card
yield return new WaitForSeconds(cardMoveToBackpackDelay);
}
// Wait for final animation
// Wait a bit after the last card
yield return new WaitForSeconds(0.5f);
// Update state to completed
// Update state
_currentState = OpeningState.Completed;
// Return to previous page
// Return to the menu
UIPageController.Instance.PopPage();
}
// Override for transition animations
/// <summary>
/// Override for transition in animation using Pixelplacement.Tween
/// </summary>
protected override void DoTransitionIn(System.Action onComplete)
{
// Simple fade in animation
@@ -415,10 +555,14 @@ namespace AppleHills.UI.CardSystem
}
else
{
// Fallback if no CanvasGroup
onComplete?.Invoke();
}
}
/// <summary>
/// Override for transition out animation using Pixelplacement.Tween
/// </summary>
protected override void DoTransitionOut(System.Action onComplete)
{
// Simple fade out animation
@@ -428,8 +572,29 @@ namespace AppleHills.UI.CardSystem
}
else
{
// Fallback if no CanvasGroup
onComplete?.Invoke();
}
}
/// <summary>
/// OnEnable override to ensure proper initialization
/// </summary>
private void OnEnable()
{
if (_cardManager == null)
{
_cardManager = CardSystemManager.Instance;
}
if (_cardAlbumUI == null)
{
_cardAlbumUI = FindObjectOfType<CardAlbumUI>();
}
// Re-cache card backs in case they changed while disabled
CacheCardBackButtons();
}
}
}

View File

@@ -154,7 +154,12 @@ namespace AppleHills.UI.CardSystem
if (_hasUnseenCards)
{
_hasUnseenCards = false;
UpdateBoosterVisibility();
}
// Hide the backpack button when entering menu
if (backpackButton != null)
{
backpackButton.gameObject.SetActive(false);
}
}
else if (_pageController.CurrentPage == mainMenuPage)
@@ -176,8 +181,8 @@ namespace AppleHills.UI.CardSystem
}
else
{
if (backpackIcon != null)
backpackIcon.SetActive(false);
if (backpackButton != null)
backpackButton.gameObject.SetActive(false);
}
// Update menu if it's the main menu page
@@ -193,13 +198,21 @@ namespace AppleHills.UI.CardSystem
/// </summary>
private void ShowOnlyBackpackIcon()
{
if (backpackIcon != null)
backpackIcon.SetActive(true);
if (backpackButton != null)
{
backpackButton.gameObject.SetActive(true);
// Update booster notification visibility
UpdateBoosterVisibility();
// Update notification visibility based on booster count
bool hasBooters = _cardManager != null && _cardManager.GetBoosterPackCount() > 0;
// Show notification dot if there are boosters or unseen cards
if (boosterNotificationDot != null)
{
boosterNotificationDot.gameObject.SetActive(hasBooters || _hasUnseenCards);
}
}
}
/// <summary>
/// Opens the album view page
/// </summary>