using System; using KitsuneCafe.ItemSystem; using KitsuneCafe.System; using KitsuneCafe.System.Attributes; using UnityEngine; using UnityEngine.Events; namespace KitsuneCafe.Interaction { using Result = IInteractable.Result; public class Gate : MonoBehaviour, IInteractable { public enum Requirement { None, Key, Switch } [SerializeField] private bool isOpen; [SerializeField] private bool isLocked; [SerializeField, ShowIf("isLocked")] private Requirement requirement; [SerializeField, ShowIf("requirement", Requirement.Key)] private Item key; [SerializeField, ShowIf("requirement", Requirement.Key)] private bool consumeKey; [SerializeField] private UnityEvent opened = default; [SerializeField] private UnityEvent closed = default; public bool IsInteractable => true; public bool IsOpen => isOpen; public bool IsLocked => isLocked; public IResult Interact(IInteractor interactor) { return isOpen switch { true => TryClose(interactor), false => TryOpen(interactor), }; } private IResult TryClose(IInteractor interactor) { if (!isOpen) { return Result.Ok(); } return ForceClosed(); } private IResult TryOpen(IInteractor interactor) { return requirement switch { _ when isOpen => Result.Ok(), _ when !isLocked => ForceOpen(), Requirement.None => Result.Err(InteractionErrorCode.Locked), Requirement.Key => TryOpenWithKey(interactor), Requirement.Switch => Result.Err(InteractionErrorCode.RequiresSwitch), var x => throw new ArgumentException($"{gameObject.name} requested invalid requirement type {x}") }; } private IResult TryOpenWithKey(IInteractor interactor) { if (interactor.TryGetComponent>(out var inventory) && inventory.Has(key)) { if (consumeKey) { inventory.Remove(key); } isLocked = false; ForceOpen(); return Result.Ok(); } else { return Result.Err(InteractionErrorCode.MissingItem); } } public void ForceClosedAndForget() { isOpen = false; closed.Invoke(); } public IResult ForceClosed() { ForceClosedAndForget(); return Result.Ok(); } public void ForceOpenAndForget() { isOpen = true; opened.Invoke(); } public IResult ForceOpen() { ForceOpenAndForget(); return Result.Ok(); } } }