2025-08-28 03:43:32 +00:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
2025-08-06 08:43:41 +00:00
|
|
|
using UnityEngine;
|
|
|
|
using UnityEngine.InputSystem;
|
|
|
|
|
2025-08-27 07:52:34 +00:00
|
|
|
namespace DDD.Restaurant
|
2025-08-06 08:43:41 +00:00
|
|
|
{
|
2025-08-27 08:25:11 +00:00
|
|
|
public class PlayerInteraction : CharacterInteraction
|
2025-08-06 08:43:41 +00:00
|
|
|
{
|
2025-08-18 10:48:36 +00:00
|
|
|
private RestaurantPlayerData _restaurantPlayerDataSo;
|
2025-08-06 08:43:41 +00:00
|
|
|
|
2025-08-27 07:52:34 +00:00
|
|
|
private float _interactHeldTime;
|
|
|
|
private bool _isInteracting;
|
2025-09-02 06:12:31 +00:00
|
|
|
private float _interactionStartTime = -1f;
|
2025-08-27 07:52:34 +00:00
|
|
|
|
2025-08-06 08:43:41 +00:00
|
|
|
protected override void Start()
|
|
|
|
{
|
|
|
|
base.Start();
|
|
|
|
|
2025-08-29 09:59:46 +00:00
|
|
|
Initialize();
|
2025-08-06 08:43:41 +00:00
|
|
|
}
|
|
|
|
|
2025-08-29 09:59:46 +00:00
|
|
|
private void Initialize()
|
2025-08-06 08:43:41 +00:00
|
|
|
{
|
2025-08-19 04:51:42 +00:00
|
|
|
_restaurantPlayerDataSo = RestaurantData.Instance.PlayerData;
|
2025-08-29 09:59:46 +00:00
|
|
|
_restaurantPlayerDataSo.InteractAction = InputManager.Instance.GetAction(InputActionMaps.Restaurant, nameof(RestaurantActions.Interact));
|
2025-08-06 08:43:41 +00:00
|
|
|
_restaurantPlayerDataSo.InteractAction.performed += OnInteractPerformed;
|
|
|
|
_restaurantPlayerDataSo.InteractAction.canceled += OnInteractCanceled;
|
|
|
|
|
|
|
|
_interactionRadius = _restaurantPlayerDataSo.InteractionRadius;
|
|
|
|
_interactionLayerMask = _restaurantPlayerDataSo.InteractionLayerMask;
|
|
|
|
|
|
|
|
EventBus.Register<RestaurantInteractionEvent>(this);
|
|
|
|
}
|
|
|
|
|
2025-08-28 03:43:32 +00:00
|
|
|
public override void InitializeSolvers()
|
|
|
|
{
|
|
|
|
var playerSolver = RestaurantInteractionEventSolvers.TypeToPlayerSolver;
|
2025-08-28 05:52:21 +00:00
|
|
|
Dictionary<InteractionType, Type> typesToSolver = new();
|
|
|
|
foreach (var typeToSolver in RestaurantInteractionEventSolvers.TypeToSolver)
|
2025-08-28 03:43:32 +00:00
|
|
|
{
|
2025-08-28 05:52:21 +00:00
|
|
|
typesToSolver.Add(typeToSolver.Key, typeToSolver.Value);
|
|
|
|
}
|
|
|
|
foreach (var typeToSolver in playerSolver)
|
|
|
|
{
|
|
|
|
typesToSolver[typeToSolver.Key] = typeToSolver.Value;
|
2025-08-28 03:43:32 +00:00
|
|
|
}
|
|
|
|
InitializeInteractionSolvers(typesToSolver);
|
|
|
|
}
|
|
|
|
|
2025-08-06 08:43:41 +00:00
|
|
|
protected override void OnDestroy()
|
|
|
|
{
|
|
|
|
base.OnDestroy();
|
|
|
|
|
|
|
|
if (_restaurantPlayerDataSo != null)
|
|
|
|
{
|
|
|
|
_restaurantPlayerDataSo.InteractAction.performed -= OnInteractPerformed;
|
|
|
|
_restaurantPlayerDataSo.InteractAction.canceled -= OnInteractCanceled;
|
|
|
|
}
|
|
|
|
|
|
|
|
EventBus.Unregister<RestaurantInteractionEvent>(this);
|
|
|
|
}
|
2025-08-27 07:52:34 +00:00
|
|
|
|
|
|
|
protected virtual void Update()
|
|
|
|
{
|
|
|
|
_nearestInteractable = GetNearestInteractable();
|
|
|
|
|
|
|
|
if (_nearestInteractable != _previousInteractable)
|
|
|
|
{
|
|
|
|
_previousInteractable = _nearestInteractable;
|
2025-09-02 06:12:31 +00:00
|
|
|
BroadcastInteractionUi(_nearestInteractable, CanInteractTo(_nearestInteractable), 0f);
|
2025-08-27 07:52:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (_isInteracting)
|
|
|
|
{
|
|
|
|
if (_nearestInteractable != _interactingTarget || CanInteractTo(_interactingTarget) == false)
|
|
|
|
{
|
|
|
|
ResetInteractionState();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_interactHeldTime += Time.deltaTime;
|
|
|
|
|
|
|
|
float requiredHoldTime = _interactingTarget.GetExecutionParameters().HoldTime;
|
|
|
|
float ratio = Mathf.Clamp01(_interactHeldTime / requiredHoldTime);
|
2025-08-27 08:05:54 +00:00
|
|
|
|
2025-08-27 07:52:34 +00:00
|
|
|
if (_interactHeldTime >= requiredHoldTime)
|
|
|
|
{
|
2025-08-27 08:05:54 +00:00
|
|
|
TryInteraction(_nearestInteractable);
|
|
|
|
OnInteractionCompleted();
|
2025-08-27 07:52:34 +00:00
|
|
|
|
|
|
|
ResetInteractionState();
|
2025-09-02 06:12:31 +00:00
|
|
|
BroadcastInteractionUi(_nearestInteractable, CanInteractTo(_nearestInteractable), 0f);
|
2025-08-27 08:05:54 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2025-09-02 06:12:31 +00:00
|
|
|
BroadcastInteractionUi(_nearestInteractable, CanInteractTo(_nearestInteractable), ratio);
|
2025-08-27 07:52:34 +00:00
|
|
|
}
|
|
|
|
}
|
2025-09-02 06:12:31 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
BroadcastInteractionUi(_nearestInteractable, CanInteractTo(_nearestInteractable), 0f);
|
|
|
|
}
|
2025-08-27 07:52:34 +00:00
|
|
|
}
|
|
|
|
|
2025-08-06 08:43:41 +00:00
|
|
|
|
|
|
|
private void OnInteractPerformed(InputAction.CallbackContext context)
|
|
|
|
{
|
2025-08-14 04:46:36 +00:00
|
|
|
if (_nearestInteractable == null || CanInteractTo(_nearestInteractable) == false) return;
|
2025-08-06 08:43:41 +00:00
|
|
|
|
2025-08-20 05:07:33 +00:00
|
|
|
float requiredHoldTime = _nearestInteractable.GetExecutionParameters().HoldTime;
|
2025-08-06 08:43:41 +00:00
|
|
|
|
|
|
|
if (requiredHoldTime <= 0f)
|
|
|
|
{
|
2025-08-27 08:05:54 +00:00
|
|
|
TryInteraction(_nearestInteractable);
|
2025-08-06 08:43:41 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_isInteracting = true;
|
|
|
|
_interactHeldTime = 0f;
|
|
|
|
_interactingTarget = _nearestInteractable;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OnInteractCanceled(InputAction.CallbackContext context)
|
|
|
|
{
|
2025-09-02 06:12:31 +00:00
|
|
|
BroadcastInteractionUi(_nearestInteractable, CanInteractTo(_nearestInteractable), 0f);
|
2025-08-06 08:43:41 +00:00
|
|
|
ResetInteractionState();
|
2025-09-02 06:12:31 +00:00
|
|
|
_interactionStartTime = -1f;
|
2025-08-06 08:43:41 +00:00
|
|
|
}
|
|
|
|
|
2025-09-02 06:12:31 +00:00
|
|
|
protected override void OnInteractionCompleted()
|
2025-08-06 08:43:41 +00:00
|
|
|
{
|
2025-09-02 06:12:31 +00:00
|
|
|
|
2025-08-06 08:43:41 +00:00
|
|
|
}
|
|
|
|
|
2025-09-02 06:12:31 +00:00
|
|
|
private void BroadcastInteractionUi(IInteractable interactable, bool canInteract, float ratio)
|
2025-08-06 08:43:41 +00:00
|
|
|
{
|
2025-09-02 06:12:31 +00:00
|
|
|
if (interactable == null)
|
2025-08-06 08:43:41 +00:00
|
|
|
{
|
2025-09-02 06:12:31 +00:00
|
|
|
EventBus.Broadcast(GameEvents.HideInteractionUiEvent);
|
|
|
|
return;
|
2025-08-06 08:43:41 +00:00
|
|
|
}
|
|
|
|
|
2025-08-28 10:06:38 +00:00
|
|
|
var displayParameters = interactable.GetDisplayParameters();
|
2025-08-06 08:43:41 +00:00
|
|
|
var evt = GameEvents.ShowInteractionUiEvent;
|
2025-08-13 09:31:34 +00:00
|
|
|
evt.CanInteract = canInteract;
|
2025-08-28 10:06:38 +00:00
|
|
|
evt.TextKey = canInteract ? displayParameters.DefaultMessageKey : displayParameters.ConditionalMessageKey;
|
2025-08-06 08:43:41 +00:00
|
|
|
evt.HoldProgress = ratio;
|
|
|
|
EventBus.Broadcast(evt);
|
|
|
|
}
|
2025-08-27 07:52:34 +00:00
|
|
|
|
|
|
|
protected void ResetInteractionState()
|
|
|
|
{
|
|
|
|
_interactingTarget = null;
|
|
|
|
|
|
|
|
// Hold Progress
|
|
|
|
_isInteracting = false;
|
|
|
|
_interactingTarget = null;
|
|
|
|
_interactHeldTime = 0f;
|
2025-09-02 06:12:31 +00:00
|
|
|
BroadcastInteractionUi(_nearestInteractable, CanInteractTo(_nearestInteractable), 0f);
|
2025-08-27 07:52:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected IInteractable GetNearestInteractable()
|
|
|
|
{
|
|
|
|
int colliderCount = Physics.OverlapSphereNonAlloc(transform.position, _interactionRadius, _nearColliders, _interactionLayerMask, QueryTriggerInteraction.Collide);
|
|
|
|
float closestDistance = float.MaxValue;
|
|
|
|
IInteractable closest = null;
|
|
|
|
|
|
|
|
for (int i = 0; i < colliderCount; i++)
|
|
|
|
{
|
|
|
|
var col = _nearColliders[i];
|
|
|
|
if (col.TryGetComponent<IInteractable>(out var interactable) == false) continue;
|
|
|
|
|
|
|
|
var type = interactable.GetInteractionType();
|
2025-08-28 09:16:46 +00:00
|
|
|
if (!interactable.IsInteractionAvailable()) continue;
|
2025-08-27 07:52:34 +00:00
|
|
|
if (CanSolveInteractionType(type) == false) continue;
|
2025-08-28 09:16:46 +00:00
|
|
|
if (IsInteractionHidden(interactable)) continue;
|
2025-08-27 07:52:34 +00:00
|
|
|
|
|
|
|
float distance = Vector3.Distance(transform.position, col.transform.position);
|
|
|
|
if (distance < closestDistance)
|
|
|
|
{
|
|
|
|
closestDistance = distance;
|
|
|
|
closest = interactable;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return closest;
|
|
|
|
}
|
2025-08-28 07:52:18 +00:00
|
|
|
|
2025-08-29 07:50:54 +00:00
|
|
|
public override bool FetchSolverTypeForInteraction(InteractionType type, out Type solverType)
|
2025-08-28 07:52:18 +00:00
|
|
|
{
|
|
|
|
if (RestaurantInteractionEventSolvers.TypeToPlayerSolver.TryGetValue(type, out solverType))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return base.FetchSolverTypeForInteraction(type, out solverType);
|
|
|
|
}
|
2025-09-02 06:49:34 +00:00
|
|
|
|
|
|
|
public override bool IsInteracting()
|
|
|
|
{
|
|
|
|
if (base.IsInteracting() == false) return false;
|
|
|
|
|
|
|
|
return _isInteracting;
|
|
|
|
}
|
2025-09-02 06:12:31 +00:00
|
|
|
|
|
|
|
public override float GetMovementSpeedMultiplier()
|
|
|
|
{
|
|
|
|
if (_isInteracting == false)
|
|
|
|
{
|
|
|
|
_interactionStartTime = -1f;
|
|
|
|
return 1f;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_interactionStartTime < 0f)
|
|
|
|
{
|
|
|
|
_interactionStartTime = Time.time;
|
|
|
|
}
|
|
|
|
|
|
|
|
float elapsed = Time.time - _interactionStartTime;
|
|
|
|
float normalizedTime = Mathf.Clamp01(elapsed / _restaurantPlayerDataSo.DecelerationTime);
|
|
|
|
|
|
|
|
return Mathf.Clamp01(_restaurantPlayerDataSo.InteractionDecelerationCurve.Evaluate(normalizedTime));
|
|
|
|
}
|
2025-08-06 08:43:41 +00:00
|
|
|
}
|
|
|
|
}
|