CapersProject/Assets/02.Scripts/Item/ItemManager.cs
2024-09-10 16:26:29 +09:00

140 lines
5.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Serialization;
using Random = UnityEngine.Random;
namespace BlueWater.Items
{
public class ItemManager : Singleton<ItemManager>
{
[SerializeField, Required]
private Item _defaultItemPrefab;
[SerializeField, Required]
private ItemDataSo _itemDataSo;
private Dictionary<string, ItemData> _itemDatas;
[SerializeField, Required]
private ItemDropTableSo _itemDropTableSo;
private Dictionary<string, ItemDropTable> _itemDropTables;
[SerializeField, Required]
private FoodDataSo _foodDataSo;
private Dictionary<string, FoodData> _foodDatas;
[SerializeField, Required]
private CocktailDataSo _cocktailDataSo;
private Dictionary<string, CocktailData> _cocktailDatas;
[FormerlySerializedAs("_drinkDataSo")] [SerializeField, Required]
private LiquidDataSo liquidDataSo;
private Dictionary<string, LiquidData> _liquidDatas;
[field: SerializeField, Required]
public ItemSlotDataSo ItemSlotDataSo { get; private set; }
[Title("드롭 아이템 설정")]
[SerializeField]
private float _randomDropRadius = 3f;
[SerializeField]
private float _minSeparationDistance = 1.5f;
private const int MaxAttempts = 1000;
protected override void OnAwake()
{
base.OnAwake();
Initialize();
}
private void Initialize()
{
_itemDatas = InitializeDictionary(_itemDataSo.Datas, data => data.Idx);
_itemDropTables = InitializeDictionary(_itemDropTableSo.ItemDropTables, table => table.CharacterData.CharacterIdx);
_foodDatas = InitializeDictionary(_foodDataSo.Datas, data => data.Idx);
_cocktailDatas = InitializeDictionary(_cocktailDataSo.Datas, data => data.Idx);
_liquidDatas = InitializeDictionary(liquidDataSo.Datas, data => data.Idx);
}
private Dictionary<string, T> InitializeDictionary<T>(List<T> dataList, Func<T, string> keySelector)
{
return dataList.ToDictionary(keySelector);
}
public void ItemDropRandomPosition(string idx, Vector3 dropPosition, float randomDropRadius = float.PositiveInfinity)
{
var itemDropTable = GetItemDropTableByIdx(idx);
if (itemDropTable == null) return;
var droppedItemList = itemDropTable.GetDroppedItemList();
var droppedPositions = new List<Vector3>();
foreach (var element in droppedItemList)
{
Vector3 newDropPosition;
var attempts = 0;
do
{
var radius = float.IsPositiveInfinity(randomDropRadius) ? _randomDropRadius : randomDropRadius;
attempts++;
var newDropPositionX = Random.Range(dropPosition.x - radius, dropPosition.x + radius);
var newDropPositionZ = Random.Range(dropPosition.z - radius, dropPosition.z + radius);
newDropPosition = new Vector3(newDropPositionX, dropPosition.y, newDropPositionZ);
} while (!IsDropPositionAvailable(newDropPosition, droppedPositions) && attempts < MaxAttempts);
droppedPositions.Add(newDropPosition);
var itemPrefab = _itemDatas[element.Idx].ItemPrefab;
if (!itemPrefab)
{
itemPrefab = _defaultItemPrefab;
}
var instantiateItem = Instantiate(itemPrefab, dropPosition, itemPrefab.transform.rotation);
instantiateItem.Initialize(element);
var pushPower = Vector3.up * 30f + (newDropPosition - dropPosition) * 10f;
instantiateItem.AddForce(pushPower, ForceMode.Impulse);
}
}
private bool IsDropPositionAvailable(Vector3 position, List<Vector3> positions)
{
return positions.Any(pos => Vector3.Distance(position, pos) > _minSeparationDistance);
}
public T GetDataByIdx<T>(Dictionary<string, T> dataDictionary, string idx) where T : class
{
if (dataDictionary.TryGetValue(idx, out var data))
return data;
Debug.LogError($"{idx}와 일치하는 아이템이 없습니다.");
return null;
}
public ItemData GetItemDataByIdx(string idx) => GetDataByIdx(_itemDatas, idx);
public ItemDropTable GetItemDropTableByIdx(string idx)
{
if (string.IsNullOrEmpty(idx))
{
Debug.Log("ItemDropTable이 비어있습니다.");
return null;
}
if (_itemDropTables.TryGetValue(idx, out var itemDropTable)) return itemDropTable;
Debug.LogError($"{idx}와 일치하는 아이템이 없습니다.");
return null;
}
public FoodData GetFoodDataByIdx(string idx) => GetDataByIdx(_foodDatas, idx);
public CocktailData GetCocktailDataByIdx(string idx) => GetDataByIdx(_cocktailDatas, idx);
public Dictionary<string, CocktailData> GetCocktailDatas() => _cocktailDatas;
public LiquidData GetLiquidDataByIdx(string idx) => GetDataByIdx(_liquidDatas, idx);
}
}