Pulver trash maze sequence
This commit is contained in:
@@ -3,9 +3,6 @@ using System.Collections;
|
||||
using Core;
|
||||
using Input;
|
||||
using Interactions;
|
||||
using Minigames.TrashMaze.Core;
|
||||
using Minigames.TrashMaze.Data;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
@@ -20,61 +17,27 @@ namespace Items
|
||||
public bool hasBeenUsed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Camera switching mode for controller switch items
|
||||
/// </summary>
|
||||
public enum CameraSwitchMode
|
||||
{
|
||||
/// <summary>
|
||||
/// No camera switching - controller switch only
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// Use a direct reference to a Cinemachine camera
|
||||
/// </summary>
|
||||
DirectReference,
|
||||
|
||||
/// <summary>
|
||||
/// Use TrashMazeCameraController state manager API
|
||||
/// </summary>
|
||||
TrashMazeCameraState
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An interactable item that switches control from one character controller to another.
|
||||
/// When clicked:
|
||||
/// 1. The selected character moves to this item's position
|
||||
/// 2. Upon arrival, the current controller is disabled
|
||||
/// 3. Camera blends to the target camera (based on camera mode)
|
||||
/// 4. Once the blend completes, control switches to the target controller
|
||||
/// Base interactable item that switches control from one character controller to another.
|
||||
/// Level-agnostic - handles only controller switching logic.
|
||||
/// Derive from this class for level-specific behavior (camera switching, teleportation, etc.)
|
||||
/// </summary>
|
||||
public class ControllerSwitchItem : SaveableInteractable
|
||||
{
|
||||
[Header("Controller Switch Settings")]
|
||||
[Tooltip("Name of the controller to switch to (must match GameObject name of the controller)")]
|
||||
[SerializeField] private string targetControllerName;
|
||||
|
||||
[Header("Camera Settings")]
|
||||
[Tooltip("How to switch the camera when changing controllers")]
|
||||
[SerializeField] private CameraSwitchMode cameraSwitchMode = CameraSwitchMode.None;
|
||||
|
||||
[Tooltip("Direct camera reference (only used if Camera Switch Mode is DirectReference)")]
|
||||
[SerializeField] private CinemachineCamera targetVirtualCamera;
|
||||
|
||||
[Tooltip("Target camera state (only used if Camera Switch Mode is TrashMazeCameraState)")]
|
||||
[SerializeField] private TrashMazeCameraState targetCameraState;
|
||||
[Tooltip("Name of the controller to switch to (must match registration name in InputManager)")]
|
||||
[SerializeField] protected string targetControllerName;
|
||||
|
||||
[Header("Visual Feedback")]
|
||||
[Tooltip("Visual representation to hide after use (optional)")]
|
||||
[SerializeField] private GameObject visualRepresentation;
|
||||
[SerializeField] protected GameObject visualRepresentation;
|
||||
|
||||
public UnityEvent OnCharacterSwitch;
|
||||
|
||||
// State
|
||||
private bool _hasBeenUsed;
|
||||
private PlayerTouchController _currentPlayerController;
|
||||
private bool _isSwitching;
|
||||
protected bool _hasBeenUsed;
|
||||
protected bool _isSwitching;
|
||||
|
||||
public override string SaveId => $"{gameObject.scene.name}/ControllerSwitchItem/{gameObject.name}";
|
||||
|
||||
@@ -123,68 +86,50 @@ namespace Items
|
||||
if (_isSwitching)
|
||||
return false;
|
||||
|
||||
// By the time this is called, the interacting character has already arrived at this item
|
||||
// We just need to perform the controller/camera switch
|
||||
|
||||
Logging.Debug("[ControllerSwitchItem] Starting controller switch sequence");
|
||||
|
||||
// Start the async switch sequence (camera blend + controller switch)
|
||||
StartCoroutine(SwitchControllerSequence());
|
||||
|
||||
// Return true immediately - interaction is considered successful
|
||||
// The coroutine will handle the actual switching asynchronously
|
||||
return true;
|
||||
}
|
||||
|
||||
private IEnumerator SwitchControllerSequence()
|
||||
protected virtual IEnumerator SwitchControllerSequence()
|
||||
{
|
||||
_isSwitching = true;
|
||||
|
||||
// Step 1: Get current player controller (the one we're switching FROM)
|
||||
_currentPlayerController = FindFirstObjectByType<PlayerTouchController>();
|
||||
if (_currentPlayerController == null)
|
||||
// Step 1: Get controllers
|
||||
var currentController = InputManager.Instance.GetActiveController();
|
||||
var targetController = InputManager.Instance.GetController(targetControllerName);
|
||||
|
||||
if (currentController == null || targetController == null)
|
||||
{
|
||||
Debug.LogError("[ControllerSwitchItem] Could not find PlayerTouchController in scene!");
|
||||
Debug.LogError($"[ControllerSwitchItem] Failed to get controllers! Current: {currentController}, Target: {targetController} (name: {targetControllerName})");
|
||||
_isSwitching = false;
|
||||
yield break;
|
||||
}
|
||||
|
||||
GameObject currentGameObject = (currentController as MonoBehaviour)?.gameObject;
|
||||
GameObject targetGameObject = (targetController as MonoBehaviour)?.gameObject;
|
||||
|
||||
Logging.Debug($"[ControllerSwitchItem] Switching from {currentGameObject?.name} to {targetGameObject?.name}");
|
||||
|
||||
Logging.Debug("[ControllerSwitchItem] Character has arrived, beginning switch");
|
||||
// Step 2: Deactivate current controller
|
||||
DeactivateCurrentController(currentController, currentGameObject);
|
||||
|
||||
// Step 2: Disable current player controller
|
||||
_currentPlayerController.enabled = false;
|
||||
Logging.Debug("[ControllerSwitchItem] Disabled current player controller");
|
||||
// Step 3: Activate target controller
|
||||
ActivateTargetController(targetController, targetGameObject);
|
||||
|
||||
// Step 3: Blend to target camera based on mode
|
||||
yield return SwitchCamera();
|
||||
|
||||
// Step 4: Switch to target controller
|
||||
ITouchInputConsumer targetController = InputManager.Instance.GetController(targetControllerName);
|
||||
if (targetController != null)
|
||||
// Step 4: Switch InputManager to target controller
|
||||
bool switchSuccess = InputManager.Instance.SwitchToController(targetControllerName);
|
||||
|
||||
if (switchSuccess)
|
||||
{
|
||||
// Enable the target controller if it's a MonoBehaviour
|
||||
if (targetController is MonoBehaviour targetMono)
|
||||
{
|
||||
targetMono.enabled = true;
|
||||
Logging.Debug($"[ControllerSwitchItem] Enabled target controller: {targetControllerName}");
|
||||
}
|
||||
|
||||
// Switch input control to the target controller
|
||||
bool switchSuccess = InputManager.Instance.SwitchToController(targetControllerName);
|
||||
|
||||
if (switchSuccess)
|
||||
{
|
||||
Logging.Debug($"[ControllerSwitchItem] Successfully switched input to controller: {targetControllerName}");
|
||||
OnCharacterSwitch.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"[ControllerSwitchItem] Failed to switch to controller: {targetControllerName}");
|
||||
}
|
||||
Logging.Debug($"[ControllerSwitchItem] Successfully switched input to controller: {targetControllerName}");
|
||||
OnCharacterSwitch.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"[ControllerSwitchItem] Target controller '{targetControllerName}' not found!");
|
||||
Debug.LogError($"[ControllerSwitchItem] Failed to switch to controller: {targetControllerName}");
|
||||
}
|
||||
|
||||
// Step 5: Mark as used if one-time use
|
||||
@@ -197,79 +142,65 @@ namespace Items
|
||||
_isSwitching = false;
|
||||
}
|
||||
|
||||
private IEnumerator SwitchCamera()
|
||||
protected virtual void DeactivateCurrentController(ITouchInputConsumer currentController, GameObject currentGameObject)
|
||||
{
|
||||
switch (cameraSwitchMode)
|
||||
// If current is a player controller, deactivate it
|
||||
if (currentController is BasePlayerMovementController currentPlayerController)
|
||||
{
|
||||
case CameraSwitchMode.None:
|
||||
// No camera switching
|
||||
Logging.Debug("[ControllerSwitchItem] No camera switching configured");
|
||||
break;
|
||||
|
||||
case CameraSwitchMode.DirectReference:
|
||||
if (targetVirtualCamera != null)
|
||||
{
|
||||
Logging.Debug($"[ControllerSwitchItem] Blending to camera: {targetVirtualCamera.name}");
|
||||
|
||||
// Set the target camera as highest priority
|
||||
targetVirtualCamera.Priority = 100;
|
||||
|
||||
// Wait for camera blend to complete
|
||||
yield return WaitForCameraBlend();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[ControllerSwitchItem] DirectReference mode selected but no camera assigned!");
|
||||
}
|
||||
break;
|
||||
|
||||
case CameraSwitchMode.TrashMazeCameraState:
|
||||
if (TrashMazeCameraController.Instance != null)
|
||||
{
|
||||
Logging.Debug($"[ControllerSwitchItem] Switching to camera state: {targetCameraState}");
|
||||
|
||||
// Use the state manager API
|
||||
if (targetCameraState == TrashMazeCameraState.Gameplay)
|
||||
{
|
||||
TrashMazeCameraController.Instance.SwitchToGameplay();
|
||||
}
|
||||
else if (targetCameraState == TrashMazeCameraState.Maze)
|
||||
{
|
||||
TrashMazeCameraController.Instance.SwitchToMaze();
|
||||
}
|
||||
|
||||
// Wait for camera blend to complete
|
||||
yield return WaitForCameraBlend();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("[ControllerSwitchItem] TrashMazeCameraController instance not found in scene!");
|
||||
}
|
||||
break;
|
||||
currentPlayerController.DeactivateController();
|
||||
}
|
||||
|
||||
// If switching FROM follower mode, deactivate follower
|
||||
if (currentGameObject != null)
|
||||
{
|
||||
var currentFollower = currentGameObject.GetComponent<FollowerController>();
|
||||
if (currentFollower != null && currentFollower.IsFollowerActive)
|
||||
{
|
||||
currentFollower.DeactivateFollower();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator WaitForCameraBlend()
|
||||
protected virtual void ActivateTargetController(ITouchInputConsumer targetController, GameObject targetGameObject)
|
||||
{
|
||||
CinemachineBrain brain = Camera.main?.GetComponent<CinemachineBrain>();
|
||||
if (brain != null)
|
||||
// Check if target GameObject has FollowerController component
|
||||
FollowerController targetFollower = null;
|
||||
if (targetGameObject != null)
|
||||
{
|
||||
// Wait until blend is not active
|
||||
while (brain.IsBlending)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
targetFollower = targetGameObject.GetComponent<FollowerController>();
|
||||
}
|
||||
|
||||
// If switching TO a GameObject with FollowerController, we need special handling
|
||||
if (targetFollower != null)
|
||||
{
|
||||
// Switching TO Pulver player control (Pulver has both FollowerController and PulverController)
|
||||
// Deactivate follower mode, activate player control
|
||||
targetFollower.DeactivateFollower();
|
||||
|
||||
Logging.Debug("[ControllerSwitchItem] Camera blend completed");
|
||||
if (targetController is BasePlayerMovementController targetPlayerController)
|
||||
{
|
||||
targetPlayerController.ActivateController();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no brain, just wait a brief moment
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
// Switching TO Trafalgar (no FollowerController on Trafalgar)
|
||||
// If there's a Pulver in the scene, activate its follower mode
|
||||
var pulverFollower = FindFirstObjectByType<FollowerController>();
|
||||
if (pulverFollower != null)
|
||||
{
|
||||
pulverFollower.ActivateFollower();
|
||||
}
|
||||
|
||||
// Activate the target player controller
|
||||
if (targetController is BasePlayerMovementController targetPlayerController)
|
||||
{
|
||||
targetPlayerController.ActivateController();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DisableVisual()
|
||||
protected void DisableVisual()
|
||||
{
|
||||
if (visualRepresentation != null)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user