using System.Collections.Generic; using System.Threading; using BriarQueen.Data.Identifiers; using BriarQueen.Data.IO.Saves; using BriarQueen.Framework.Assets; using BriarQueen.Framework.Coordinators.Events; using BriarQueen.Framework.Events.Save; using BriarQueen.Framework.Events.UI; using BriarQueen.Framework.Managers.Audio; using BriarQueen.Framework.Managers.Interaction.Data; using BriarQueen.Framework.Managers.IO; using BriarQueen.Framework.Managers.Player; using BriarQueen.Framework.Managers.Player.Data; using BriarQueen.Framework.Managers.UI; using BriarQueen.Framework.Registries; using BriarQueen.Framework.Services.Destruction; using BriarQueen.Framework.Services.Settings; using BriarQueen.Framework.Services.Tutorials; using Cysharp.Threading.Tasks; using PrimeTween; using UnityEngine; using VContainer; namespace BriarQueen.Framework.Managers.Levels.Data { public class BaseItem : MonoBehaviour, IInteractable { [Header("Item Details")] [SerializeField] private ItemDataSo _itemData; [Tooltip("Used for custom tooltip. Defaults to Item Name")] [SerializeField] private string _interactableTooltip = string.Empty; [Header("Object Setup")] [SerializeField] protected CanvasGroup _canvasGroup; protected AddressableManager AddressableManager; protected AssetRegistry AssetRegistry; protected DestructionService DestructionService; protected EventCoordinator EventCoordinator; protected CancellationTokenSource PickupCts; protected Sequence PickupSequence; protected PlayerManager PlayerManager; protected SaveManager SaveManager; protected SettingsService SettingsService; protected TutorialService TutorialService; protected AudioManager AudioManager; public ItemDataSo ItemData => _itemData; public CanvasGroup CanvasGroup => _canvasGroup; protected string InteractableTooltip => _interactableTooltip; public GameObject GameObject => gameObject; private void Awake() { if (_canvasGroup == null) _canvasGroup = GetComponent(); } public virtual UICursorService.CursorStyle ApplicableCursorStyle => UICursorService.CursorStyle.Pickup; public virtual string InteractableName => !string.IsNullOrWhiteSpace(_interactableTooltip) ? _interactableTooltip : _itemData.ItemName; /// /// Called when the item is interacted with. Defaults to Pickup. /// /// public virtual async UniTask OnInteract(ItemDataSo item = null) { if (item != null) { EventCoordinator.Publish(new DisplayInteractEvent(InteractEventIDs.Get(ItemInteractKey.CantUseItem))); return; } CheckCyclingTutorial(); if (!CheckEmptyHands()) return; await Pickup(); await OnInteracted(); } public virtual UniTask EnterHover() { return UniTask.CompletedTask; } public virtual UniTask ExitHover() { return UniTask.CompletedTask; } /// /// Called when item is interacted with. /// /// protected virtual UniTask OnInteracted() { return UniTask.CompletedTask; } protected virtual bool CheckEmptyHands() { if (PlayerManager.GetEquippedTool() != ToolID.None) { EventCoordinator.Publish(new DisplayInteractEvent(InteractEventIDs.Get(ItemInteractKey.EmptyHands))); return false; } return true; } private void CheckCyclingTutorial() { TutorialService.DisplayTutorial(TutorialPopupID.ItemCycling); } [Inject] public void Construct(EventCoordinator eventCoordinator, SaveManager saveManager, PlayerManager playerManager, DestructionService destructionService, SettingsService settingsService, AddressableManager addressableManager, AssetRegistry assetRegistry, TutorialService tutorialService, AudioManager audioManager) { EventCoordinator = eventCoordinator; SaveManager = saveManager; PlayerManager = playerManager; DestructionService = destructionService; SettingsService = settingsService; AddressableManager = addressableManager; AssetRegistry = assetRegistry; TutorialService = tutorialService; AudioManager = audioManager; } protected virtual async UniTask Remove() { // TODO - Play Cut Vines SFX if (_canvasGroup == null) _canvasGroup = GetComponent(); if (PickupSequence.isAlive) { PickupSequence.Complete(); PickupCts?.Cancel(); PickupCts?.Dispose(); } PickupCts = new CancellationTokenSource(); PickupSequence = Sequence.Create().Group(Tween.Alpha(_canvasGroup, new TweenSettings { startValue = _canvasGroup.alpha, endValue = 0, settings = new TweenSettings { duration = 0.5f } })); try { await PickupSequence.ToUniTask(cancellationToken: PickupCts.Token); await OnRemoved(); } catch { } finally { UpdateSaveGameOnRemoval(); await DestructionService.Destroy(gameObject); } } private void UpdateSaveGameOnRemoval() { var save = SaveManager.CurrentSave; Debug.Log($"[Base Item] Found save - {save.SaveFileName}"); save.RemovedItems ??= new List(); save.RemovedItems.Add(new ItemSaveData { UniqueIdentifier = _itemData.UniqueID }); EventCoordinator.PublishImmediate(new RequestGameSaveEvent()); } protected virtual UniTask OnRemoved() { return UniTask.CompletedTask; } protected virtual async UniTask Pickup() { if (_canvasGroup == null) _canvasGroup = GetComponent(); if (PickupSequence.isAlive) { PickupSequence.Complete(); PickupCts?.Cancel(); PickupCts?.Dispose(); } PickupCts = new CancellationTokenSource(); PickupSequence = Sequence.Create().Group(Tween.Alpha(_canvasGroup, new TweenSettings { startValue = _canvasGroup.alpha, endValue = 0, settings = new TweenSettings { duration = 0.5f } })); try { await PickupSequence.ToUniTask(cancellationToken: PickupCts.Token); } catch { } finally { PlayerManager.CollectItem(_itemData); await DestructionService.Destroy(gameObject); } } } }