CapersProject/Assets/02.Scripts/Item/Item.cs
2024-09-24 19:35:49 +09:00

234 lines
7.1 KiB
C#

using System.Collections;
using BlueWater.Audios;
using BlueWater.Interfaces;
using BlueWater.Maps;
using BlueWater.Uis;
using BlueWater.Utility;
using Sirenix.OdinInspector;
using UnityEngine;
namespace BlueWater.Items
{
public class Item : MonoBehaviour, IPlayerInteraction
{
[field: Title("컴포넌트")]
public Transform CenterTransform { get; private set; }
[SerializeField]
protected Rigidbody Rigidbody;
[SerializeField]
protected Collider Collider;
[SerializeField]
protected Transform VisualLook;
[SerializeField]
protected SpriteRenderer SpriteRenderer;
[field: SerializeField]
public Canvas InteractionCanvas { get; private set; }
public Transform InteractionUi { get; private set; }
[field: Title("드랍 옵션")]
[field: SerializeField, Tooltip("키 입력을 통한 아이템 획득")]
public bool EnableInteraction { get; private set; } = true;
[field: SerializeField]
public float InteractionRadius { get; private set; } = 2f;
public string InteractionMessage { get; private set; }
[SerializeField]
protected bool UseAutoDestroy = true;
[SerializeField, ShowIf("@UseAutoDestroy")]
protected float AutoDestroyTime = 30f;
[SerializeField, ShowIf("@!EnableInteraction")]
protected bool DrawGizmos = true;
[SerializeField, ShowIf("@!EnableInteraction")]
protected float Radius = 5f;
[SerializeField, ShowIf("@!EnableInteraction")]
protected float AcquisitionTime = 1f;
[SerializeField, ShowIf("@!EnableInteraction")]
protected float DropWaitTime = 0.7f;
[SerializeField]
protected string AcquiredSfxName = "GetItem";
[Title("아이템 데이터")]
[SerializeField]
protected ItemData ItemData;
protected ItemSlot ItemSlot;
protected Collider TargetCollider;
protected Coroutine RootCoroutineInstance;
protected readonly WaitForSeconds LootCoroutineTime = new(0.5f);
private bool _isQuitting;
private void OnDrawGizmosSelected()
{
if (!DrawGizmos) return;
Gizmos.DrawWireSphere(transform.position, Radius);
}
private void Awake()
{
InitializeComponents();
}
private void Start()
{
MapManager.Instance.OnHardResetAllMap += DestroySelf;
if (UseAutoDestroy)
{
Destroy(gameObject, AutoDestroyTime);
}
if (EnableInteraction)
{
GameManager.Instance.CurrentCombatPlayer.CombatInput.RegisterPlayerInteraction(this);
}
else
{
Utils.StartUniqueCoroutine(this, ref RootCoroutineInstance, LootCoroutine());
}
}
private void OnApplicationQuit()
{
_isQuitting = true;
}
private void OnDestroy()
{
if (_isQuitting) return;
MapManager.Instance.OnHardResetAllMap -= DestroySelf;
if (EnableInteraction)
{
GameManager.Instance.CurrentCombatPlayer.CombatInput.UnregisterPlayerInteraction(this);
}
}
public void Initialize(ItemSlot itemSlot)
{
ItemSlot = itemSlot;
ItemData = ItemManager.Instance.ItemDataSo.GetDataByIdx(ItemSlot.Idx);
SpriteRenderer.sprite = ItemData.Sprite;
}
[Button("컴포넌트 초기화")]
private void InitializeComponents()
{
if (!CenterTransform)
{
CenterTransform = transform;
}
Rigidbody = GetComponent<Rigidbody>();
Collider = GetComponent<Collider>();
VisualLook = transform.Find("VisualLook");
SpriteRenderer = VisualLook.GetComponent<SpriteRenderer>();
InteractionCanvas = transform.Find("InteractionCanvas").GetComponent<Canvas>();
InteractionCanvas.GetComponent<Canvas>().worldCamera = CombatCameraManager.Instance.UiCamera;
InteractionUi = transform.Find("InteractionUi");
}
protected virtual void OnAcquired()
{
Destroy(gameObject);
AudioManager.Instance.PlaySfx(AcquiredSfxName);
DataManager.Instance.Inventory.AddItem(ItemSlot);
CombatUiManager.Instance.ItemLootUi.ShowLootInfoUi(ItemData, ItemSlot.Quantity);
}
private IEnumerator LootCoroutine()
{
yield return new WaitForSeconds(DropWaitTime);
while (true)
{
TargetCollider = GameManager.Instance.CurrentCombatPlayer.CharacterCollider;
if (TargetCollider == null)
{
yield return LootCoroutineTime;
continue;
}
var targetDistance = Vector3.Distance(TargetCollider.transform.position, transform.position);
if (targetDistance <= Radius) break;
yield return LootCoroutineTime;
}
if (Rigidbody)
{
Rigidbody.isKinematic = true;
Rigidbody.useGravity = false;
}
if (Collider)
{
Collider.enabled = false;
}
var startPosition = transform.position;
var elapsedTime = 0f;
while (elapsedTime < AcquisitionTime)
{
if (TargetCollider == null)
{
yield break;
}
elapsedTime += Time.deltaTime;
var t = elapsedTime / AcquisitionTime;
t = Mathf.SmoothStep(0f, 1f, t);
transform.position = Vector3.Lerp(startPosition, TargetCollider.bounds.center, t);
yield return null;
}
OnAcquired();
}
public void AddForce(Vector3 force, ForceMode forceMode) => Rigidbody.AddForce(force, forceMode);
public void Interaction()
{
OnAcquired();
}
public virtual void CancelInteraction() { }
public virtual bool CanInteraction() => true;
public void ShowInteractionUi()
{
InteractionMessage = $"{ItemData.Name} 줍기";
EventManager.OnShowInteractionUi?.Invoke(InteractionMessage);
// if (!InteractionCanvas) return;
//
// InteractionCanvas.gameObject.SetActive(true);
}
public void HideInteractionUi()
{
EventManager.OnHideInteractionUi?.Invoke();
// if (!InteractionCanvas) return;
//
// InteractionCanvas.gameObject.SetActive(false);
}
private void DestroySelf() => Destroy(gameObject);
}
}