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_Script: {fileID: 11500000, guid: 1101f6c4eb04423b89dc78dc7c9f1aae, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: AppleHillsScripts::PuzzleS.ObjectiveStepBehaviour m_EditorClassIdentifier: AppleHillsScripts::PuzzleS.ObjectiveStepBehaviour
stepData: {fileID: 11400000, guid: 9c10f3091037ee4489cc15d0a91559f5, type: 2} stepData: {fileID: 11400000, guid: 37409d749a15970438d761d1d658d7a6, type: 2}
puzzleIndicator: {fileID: 1671495207} puzzleIndicator: {fileID: 1671495207}
drawPromptRangeGizmo: 1 drawPromptRangeGizmo: 1
--- !u!1001 &2024588806 --- !u!1001 &2024588806

View File

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

View File

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

View File

@@ -2,6 +2,8 @@
using TMPro; using TMPro;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using Core.SaveLoad;
using Unity.Android.Gradle;
namespace Levels namespace Levels
{ {
@@ -41,23 +43,41 @@ namespace Levels
_onMinigameConfirm = onMinigameConfirm; _onMinigameConfirm = onMinigameConfirm;
_onCancel = onCancel; _onCancel = onCancel;
_onRestart = onRestart; _onRestart = onRestart;
if (iconImage) iconImage.sprite = switchData?.menuSprite ?? switchData?.mapSprite; if(switchData != null)
if (levelNameText) levelNameText.text = switchData?.targetLevelSceneName ?? ""; {
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 (confirmButton) confirmButton.onClick.AddListener(OnConfirmClicked);
if (cancelButton) cancelButton.onClick.AddListener(OnCancelClicked); if (cancelButton) cancelButton.onClick.AddListener(OnCancelClicked);
if (minigameButton) if (minigameButton) minigameButton.onClick.AddListener(OnMinigameClicked);
{
minigameButton.onClick.AddListener(OnMinigameClicked);
bool minigameUnlocked = true;
minigameButton.interactable = minigameUnlocked;
padlockIcon.SetActive(!minigameUnlocked);
}
if (restartButton) restartButton.onClick.AddListener(OnRestartClicked); if (restartButton) restartButton.onClick.AddListener(OnRestartClicked);
if (popupConfirmMenu) popupConfirmMenu.SetActive(false); if (popupConfirmMenu) popupConfirmMenu.SetActive(false);
if (tintTargetImage) _originalTintColor = tintTargetImage.color; if (tintTargetImage) _originalTintColor = tintTargetImage.color;
if (popupConfirmButton) popupConfirmButton.onClick.AddListener(OnPopupConfirmClicked); if (popupConfirmButton) popupConfirmButton.onClick.AddListener(OnPopupConfirmClicked);
if (popupCancelButton) popupCancelButton.onClick.AddListener(OnPopupCancelClicked); 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() private void OnDestroy()
@@ -68,6 +88,10 @@ namespace Levels
if (restartButton) restartButton.onClick.RemoveListener(OnRestartClicked); if (restartButton) restartButton.onClick.RemoveListener(OnRestartClicked);
if (popupConfirmButton) popupConfirmButton.onClick.RemoveListener(OnPopupConfirmClicked); if (popupConfirmButton) popupConfirmButton.onClick.RemoveListener(OnPopupConfirmClicked);
if (popupCancelButton) popupCancelButton.onClick.RemoveListener(OnPopupCancelClicked); if (popupCancelButton) popupCancelButton.onClick.RemoveListener(OnPopupCancelClicked);
if (SaveLoadManager.Instance != null)
{
SaveLoadManager.Instance.OnLoadCompleted -= OnSaveDataLoadedHandler;
}
} }
private void OnConfirmClicked() private void OnConfirmClicked()
@@ -106,5 +130,25 @@ namespace Levels
if (popupConfirmMenu) popupConfirmMenu.SetActive(false); if (popupConfirmMenu) popupConfirmMenu.SetActive(false);
if (tintTargetImage) tintTargetImage.color = _originalTintColor; 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 Input;
using Interactions; using Interactions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Bootstrap;
using PuzzleS;
using UnityEngine; using UnityEngine;
using Core.SaveLoad;
// Added for IInteractionSettings // Added for IInteractionSettings
@@ -32,6 +35,9 @@ namespace Levels
/// </summary> /// </summary>
void Awake() void Awake()
{ {
gameObject.SetActive(false); // Start inactive
BootCompletionService.RegisterInitAction(InitializePostBoot);
_isActive = true; _isActive = true;
if (_iconRenderer == null) if (_iconRenderer == null)
_iconRenderer = GetComponent<SpriteRenderer>(); _iconRenderer = GetComponent<SpriteRenderer>();
@@ -40,22 +46,71 @@ namespace Levels
{ {
_interactable.characterArrived.AddListener(OnCharacterArrived); _interactable.characterArrived.AddListener(OnCharacterArrived);
} }
// Initialize settings reference // Initialize settings reference
_interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>(); _interactionSettings = GameManager.GetSettingsObject<IInteractionSettings>();
ApplySwitchData(); ApplySwitchData();
// --- Save state loading logic ---
if (SaveLoadManager.Instance != null)
{
if (SaveLoadManager.Instance.IsSaveDataLoaded)
{
ApplySavedMinigameStateIfAvailable();
}
else
{
SaveLoadManager.Instance.OnLoadCompleted += OnSaveDataLoadedHandler;
}
}
} }
/// <summary> private void OnDestroy()
/// Unity OnDestroy callback. Cleans up event handlers.
/// </summary>
void OnDestroy()
{ {
PuzzleManager.Instance.OnAllPuzzlesComplete -= HandleAllPuzzlesComplete;
if (_interactable != null) if (_interactable != null)
{ {
_interactable.characterArrived.RemoveListener(OnCharacterArrived); _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 #if UNITY_EDITOR
@@ -131,5 +186,10 @@ namespace Levels
_isActive = true; // Allow interaction again if cancelled _isActive = true; // Allow interaction again if cancelled
InputManager.Instance.SetInputMode(InputMode.GameAndUI); 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 // pass obeyTimescale = false so this tween runs even when Time.timeScale == 0
Tween.Value(0f, 1f, (v) => Tween.Value(0f, 1f, (v) =>
{ {
Logging.Debug($"[PauseMenu] Tweening pause menu alpha: {v}"); // Logging.Debug($"[PauseMenu] Tweening pause menu alpha: {v}");
canvasGroup.alpha = v; canvasGroup.alpha = v;
}, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, () => }, 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(); onComplete?.Invoke();
}, false); }, false);
} }