262 lines
6.9 KiB
C#
262 lines
6.9 KiB
C#
using UnityEngine;
|
||
using System.Collections.Generic;
|
||
|
||
#if UNITY_EDITOR
|
||
using UnityEditor;
|
||
#endif
|
||
|
||
public class ItemGenerator : MonoBehaviour
|
||
{
|
||
[Header("Item Template")]
|
||
public string itemId = "";
|
||
public string itemName = "";
|
||
public string description = "";
|
||
public ItemType itemType = ItemType.Material;
|
||
public Sprite icon;
|
||
public GameObject modelPrefab;
|
||
public int maxStack = 64;
|
||
public bool isCraftable;
|
||
|
||
[Header("Crafting (if craftable)")]
|
||
public string[] craftIngredients;
|
||
public int[] craftAmounts;
|
||
public string craftResultId;
|
||
public int craftResultAmount = 1;
|
||
|
||
public ItemData GenerateItemData()
|
||
{
|
||
if (string.IsNullOrEmpty(itemId))
|
||
{
|
||
itemId = System.Guid.NewGuid().ToString();
|
||
}
|
||
|
||
var itemData = ScriptableObject.CreateInstance<ItemData>();
|
||
itemData.id = itemId;
|
||
itemData.itemName = itemName;
|
||
itemData.description = description;
|
||
itemData.type = itemType;
|
||
itemData.modelPrefab = modelPrefab;
|
||
itemData.icon = icon;
|
||
itemData.maxStack = maxStack;
|
||
itemData.isCraftable = isCraftable;
|
||
|
||
if (isCraftable && craftIngredients != null && craftIngredients.Length > 0)
|
||
{
|
||
itemData.craftingRecipe = new ItemData.CraftingRecipe
|
||
{
|
||
ingredients = craftIngredients,
|
||
amounts = craftAmounts,
|
||
resultId = craftResultId,
|
||
resultAmount = craftResultAmount
|
||
};
|
||
}
|
||
|
||
return itemData;
|
||
}
|
||
|
||
public static List<ItemData> GenerateAll(List<ItemGenerator> generators)
|
||
{
|
||
var items = new List<ItemData>();
|
||
foreach (var generator in generators)
|
||
{
|
||
if (generator != null)
|
||
{
|
||
items.Add(generator.GenerateItemData());
|
||
}
|
||
}
|
||
return items;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Предмет в мире - подбирается игроком
|
||
/// </summary>
|
||
public class WorldItem : MonoBehaviour
|
||
{
|
||
public ItemData itemData;
|
||
public int amount = 1;
|
||
|
||
[Header("Settings")]
|
||
public float pickupDelay = 0f;
|
||
public bool useFactory = true;
|
||
|
||
private bool _canPickup;
|
||
|
||
public void Setup(ItemData data, int count)
|
||
{
|
||
itemData = data;
|
||
amount = count;
|
||
|
||
if (data.modelPrefab != null)
|
||
{
|
||
var model = Instantiate(data.modelPrefab, transform);
|
||
model.transform.localPosition = Vector3.zero;
|
||
}
|
||
|
||
// Задержка перед подбором
|
||
if (pickupDelay > 0)
|
||
Invoke(nameof(EnablePickup), pickupDelay);
|
||
else
|
||
_canPickup = true;
|
||
}
|
||
|
||
private void EnablePickup() => _canPickup = true;
|
||
|
||
void OnTriggerEnter(Collider other)
|
||
{
|
||
TryPickup(other);
|
||
}
|
||
|
||
void OnControllerColliderHit(ControllerColliderHit hit)
|
||
{
|
||
TryPickup(hit.controller);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Подобрать предмет вручную (по кнопке)
|
||
/// </summary>
|
||
public bool TryPickupByButton()
|
||
{
|
||
Debug.Log($"[TryPickup] _canPickup={_canPickup}, itemData={itemData?.itemName}, amount={amount}, Instance={InventoryManager.Instance != null}");
|
||
|
||
if (!_canPickup)
|
||
{
|
||
Debug.LogWarning("[TryPickup] Cannot pickup - not ready yet");
|
||
return false;
|
||
}
|
||
if (itemData == null)
|
||
{
|
||
Debug.LogWarning("[TryPickup] itemData is null!");
|
||
return false;
|
||
}
|
||
if (InventoryManager.Instance == null)
|
||
{
|
||
Debug.LogWarning("[TryPickup] InventoryManager.Instance is null!");
|
||
return false;
|
||
}
|
||
|
||
int remaining = InventoryManager.Instance.AddItem(itemData, amount);
|
||
Debug.Log($"[TryPickup] AddItem returned remaining={remaining}");
|
||
|
||
if (remaining <= 0)
|
||
{
|
||
Destroy(gameObject);
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
amount = remaining;
|
||
return false;
|
||
}
|
||
}
|
||
|
||
void TryPickup(Collider other)
|
||
{
|
||
if (!_canPickup) return;
|
||
if (other == null) return;
|
||
if (!other.CompareTag("Player")) return;
|
||
|
||
if (useFactory && InventoryItemFactory.Instance != null)
|
||
{
|
||
InventoryItemFactory.Instance.PickupItem(this, this);
|
||
}
|
||
else
|
||
{
|
||
// Fallback - старый способ
|
||
int remaining = InventoryManager.Instance.AddItem(itemData, amount);
|
||
if (remaining <= 0)
|
||
{
|
||
Destroy(gameObject);
|
||
}
|
||
else
|
||
{
|
||
amount = remaining;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Выбросить предмет с силой
|
||
/// </summary>
|
||
public void Throw(Vector3 velocity)
|
||
{
|
||
var rb = GetComponent<Rigidbody>();
|
||
if (rb == null) rb = gameObject.AddComponent<Rigidbody>();
|
||
rb.linearVelocity = velocity;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Точка спавна предмета
|
||
/// </summary>
|
||
public class ItemSpawner : MonoBehaviour
|
||
{
|
||
public ItemData item;
|
||
public int amount = 1;
|
||
public float despawnTime = 300f;
|
||
public bool spawnOnStart = false;
|
||
public bool useFactory = true;
|
||
|
||
public void Setup(ItemData itemData, int itemAmount, float despawn)
|
||
{
|
||
item = itemData;
|
||
amount = itemAmount;
|
||
despawnTime = despawn;
|
||
}
|
||
|
||
void Start()
|
||
{
|
||
if (spawnOnStart) Spawn();
|
||
}
|
||
|
||
public void Spawn()
|
||
{
|
||
if (useFactory && InventoryItemFactory.Instance != null)
|
||
{
|
||
var worldItem = InventoryItemFactory.Instance.CreateWorldItem(item, amount, transform.position);
|
||
if (worldItem != null && despawnTime > 0)
|
||
{
|
||
Destroy(worldItem.gameObject, despawnTime);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Fallback - старый способ
|
||
var prefab = Resources.Load<GameObject>("Prefabs/WorldItem");
|
||
if (prefab != null)
|
||
{
|
||
var worldItem = Instantiate(prefab, transform.position, Quaternion.identity).GetComponent<WorldItem>();
|
||
worldItem.Setup(item, amount);
|
||
Destroy(worldItem.gameObject, despawnTime);
|
||
}
|
||
}
|
||
}
|
||
|
||
public void Despawn()
|
||
{
|
||
Destroy(gameObject);
|
||
}
|
||
}
|
||
|
||
#if UNITY_EDITOR
|
||
[CustomEditor(typeof(ItemGenerator))]
|
||
public class ItemGeneratorEditor : Editor
|
||
{
|
||
public override void OnInspectorGUI()
|
||
{
|
||
base.OnInspectorGUI();
|
||
|
||
if (GUILayout.Button("Generate ItemData"))
|
||
{
|
||
var generator = (ItemGenerator)target;
|
||
var itemData = generator.GenerateItemData();
|
||
|
||
string path = $"Assets/Inventory/Items/{itemData.itemName}.asset";
|
||
AssetDatabase.CreateAsset(itemData, path);
|
||
AssetDatabase.SaveAssets();
|
||
|
||
Debug.Log($"Created item: {itemData.itemName} at {path}");
|
||
}
|
||
}
|
||
}
|
||
#endif |