Update minigame switcher to only unlock when all puzzles completed

This commit is contained in:
Michal Pikulski
2025-10-29 11:19:17 +01:00
parent bda645dcc3
commit c24c5df881
7 changed files with 598 additions and 94 deletions

File diff suppressed because one or more lines are too long

View File

@@ -472060,7 +472060,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 1101f6c4eb04423b89dc78dc7c9f1aae, type: 3}
m_Name:
m_EditorClassIdentifier: AppleHillsScripts::PuzzleS.ObjectiveStepBehaviour
stepData: {fileID: 11400000, guid: 9c10f3091037ee4489cc15d0a91559f5, type: 2}
stepData: {fileID: 11400000, guid: 37409d749a15970438d761d1d658d7a6, type: 2}
puzzleIndicator: {fileID: 1671495207}
drawPromptRangeGizmo: 1
--- !u!1001 &2024588806

View File

@@ -9,6 +9,9 @@ namespace Core.SaveLoad
// Snapshot of the player's card collection (MVP)
public CardCollectionState cardCollection;
// List of unlocked minigames by name
public List<string> unlockedMinigames = new List<string>();
}
// Minimal DTOs for card persistence

View File

@@ -28,7 +28,7 @@ public class SoundGenerator : MonoBehaviour
if (!playerInside && other.CompareTag("Player"))
{
playerInside = true;
Logging.Debug("Player entered SoundGenerator trigger!");
// Logging.Debug("Player entered SoundGenerator trigger!");
if (spriteRenderer != null && enterSprite != null)
{
spriteRenderer.sprite = enterSprite;
@@ -50,7 +50,7 @@ public class SoundGenerator : MonoBehaviour
if (playerInside && other.CompareTag("Player"))
{
playerInside = false;
Logging.Debug("Player exited SoundGenerator trigger!");
// Logging.Debug("Player exited SoundGenerator trigger!");
if (spriteRenderer != null && exitSprite != null)
{
spriteRenderer.sprite = exitSprite;

View File

@@ -2,6 +2,8 @@
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using Core.SaveLoad;
using Unity.Android.Gradle;
namespace Levels
{
@@ -41,23 +43,41 @@ namespace Levels
_onMinigameConfirm = onMinigameConfirm;
_onCancel = onCancel;
_onRestart = onRestart;
if (iconImage) iconImage.sprite = switchData?.menuSprite ?? switchData?.mapSprite;
if (levelNameText) levelNameText.text = switchData?.targetLevelSceneName ?? "";
if(switchData != null)
{
if (iconImage)
{
iconImage.sprite = switchData.menuSprite != null
? switchData.menuSprite
: switchData.mapSprite;
}
if (levelNameText) levelNameText.text = switchData?.targetLevelSceneName ?? "";
}
else
{
Logging.LogWarning("[LevelSwitchMenu] No level data is assigned!");
}
if (confirmButton) confirmButton.onClick.AddListener(OnConfirmClicked);
if (cancelButton) cancelButton.onClick.AddListener(OnCancelClicked);
if (minigameButton)
{
minigameButton.onClick.AddListener(OnMinigameClicked);
bool minigameUnlocked = true;
minigameButton.interactable = minigameUnlocked;
padlockIcon.SetActive(!minigameUnlocked);
}
if (minigameButton) minigameButton.onClick.AddListener(OnMinigameClicked);
if (restartButton) restartButton.onClick.AddListener(OnRestartClicked);
if (popupConfirmMenu) popupConfirmMenu.SetActive(false);
if (tintTargetImage) _originalTintColor = tintTargetImage.color;
if (popupConfirmButton) popupConfirmButton.onClick.AddListener(OnPopupConfirmClicked);
if (popupCancelButton) popupCancelButton.onClick.AddListener(OnPopupCancelClicked);
// --- Minigame unlock state logic ---
if (SaveLoadManager.Instance != null)
{
if (SaveLoadManager.Instance.IsSaveDataLoaded)
{
ApplyMinigameUnlockStateIfAvailable();
}
else
{
SaveLoadManager.Instance.OnLoadCompleted += OnSaveDataLoadedHandler;
}
}
}
private void OnDestroy()
@@ -68,6 +88,10 @@ namespace Levels
if (restartButton) restartButton.onClick.RemoveListener(OnRestartClicked);
if (popupConfirmButton) popupConfirmButton.onClick.RemoveListener(OnPopupConfirmClicked);
if (popupCancelButton) popupCancelButton.onClick.RemoveListener(OnPopupCancelClicked);
if (SaveLoadManager.Instance != null)
{
SaveLoadManager.Instance.OnLoadCompleted -= OnSaveDataLoadedHandler;
}
}
private void OnConfirmClicked()
@@ -106,5 +130,25 @@ namespace Levels
if (popupConfirmMenu) popupConfirmMenu.SetActive(false);
if (tintTargetImage) tintTargetImage.color = _originalTintColor;
}
private void ApplyMinigameUnlockStateIfAvailable()
{
if (minigameButton == null || padlockIcon == null || _switchData == null)
return;
var data = SaveLoadManager.Instance?.currentSaveData;
string minigameName = _switchData.targetMinigameSceneName;
bool unlocked = data?.unlockedMinigames != null && !string.IsNullOrEmpty(minigameName) && data.unlockedMinigames.Contains(minigameName);
minigameButton.interactable = unlocked;
padlockIcon.SetActive(!unlocked);
}
private void OnSaveDataLoadedHandler(string slot)
{
ApplyMinigameUnlockStateIfAvailable();
if (SaveLoadManager.Instance != null)
{
SaveLoadManager.Instance.OnLoadCompleted -= OnSaveDataLoadedHandler;
}
}
}
}

View File

@@ -4,7 +4,10 @@ using Core;
using Input;
using Interactions;
using System.Threading.Tasks;
using Bootstrap;
using PuzzleS;
using UnityEngine;
using Core.SaveLoad;
// Added for IInteractionSettings
@@ -32,6 +35,9 @@ namespace Levels
/// </summary>
void Awake()
{
gameObject.SetActive(false); // Start inactive
BootCompletionService.RegisterInitAction(InitializePostBoot);
_isActive = true;
if (_iconRenderer == null)
_iconRenderer = GetComponent<SpriteRenderer>();
@@ -40,22 +46,71 @@ namespace Levels
{
_interactable.characterArrived.AddListener(OnCharacterArrived);
}
// Initialize settings reference
_interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
ApplySwitchData();
// --- Save state loading logic ---
if (SaveLoadManager.Instance != null)
{
if (SaveLoadManager.Instance.IsSaveDataLoaded)
{
ApplySavedMinigameStateIfAvailable();
}
else
{
SaveLoadManager.Instance.OnLoadCompleted += OnSaveDataLoadedHandler;
}
}
}
/// <summary>
/// Unity OnDestroy callback. Cleans up event handlers.
/// </summary>
void OnDestroy()
private void OnDestroy()
{
PuzzleManager.Instance.OnAllPuzzlesComplete -= HandleAllPuzzlesComplete;
if (_interactable != null)
{
_interactable.characterArrived.RemoveListener(OnCharacterArrived);
}
if (SaveLoadManager.Instance != null)
{
SaveLoadManager.Instance.OnLoadCompleted -= OnSaveDataLoadedHandler;
}
}
// Apply saved state if present in the SaveLoadManager
private void ApplySavedMinigameStateIfAvailable()
{
var data = SaveLoadManager.Instance?.currentSaveData;
if (data?.unlockedMinigames != null && switchData != null &&
data.unlockedMinigames.Contains(switchData.targetLevelSceneName))
{
gameObject.SetActive(true);
}
}
// Event handler for when save data load completes
private void OnSaveDataLoadedHandler(string slot)
{
ApplySavedMinigameStateIfAvailable();
if (SaveLoadManager.Instance != null)
{
SaveLoadManager.Instance.OnLoadCompleted -= OnSaveDataLoadedHandler;
}
}
private void HandleAllPuzzlesComplete(PuzzleS.PuzzleLevelDataSO _)
{
// Unlock and save
if (switchData != null)
{
var unlocked = SaveLoadManager.Instance.currentSaveData.unlockedMinigames;
string minigameName = switchData.targetLevelSceneName;
if (!unlocked.Contains(minigameName))
{
unlocked.Add(minigameName);
}
}
gameObject.SetActive(true);
}
#if UNITY_EDITOR
@@ -131,5 +186,10 @@ namespace Levels
_isActive = true; // Allow interaction again if cancelled
InputManager.Instance.SetInputMode(InputMode.GameAndUI);
}
private void InitializePostBoot()
{
PuzzleManager.Instance.OnAllPuzzlesComplete += HandleAllPuzzlesComplete;
}
}
}

View File

@@ -197,11 +197,11 @@ namespace UI
// pass obeyTimescale = false so this tween runs even when Time.timeScale == 0
Tween.Value(0f, 1f, (v) =>
{
Logging.Debug($"[PauseMenu] Tweening pause menu alpha: {v}");
// Logging.Debug($"[PauseMenu] Tweening pause menu alpha: {v}");
canvasGroup.alpha = v;
}, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, () =>
{
Logging.Debug("[PauseMenu] Finished tweening pause menu in.");
// Logging.Debug("[PauseMenu] Finished tweening pause menu in.");
onComplete?.Invoke();
}, false);
}