194 lines
6.6 KiB
C#
194 lines
6.6 KiB
C#
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
public class ShopInventory : MonoBehaviour
|
|
{
|
|
public static ShopInventory Instance;
|
|
public GameObject inventoryUIPanel; // Reference to the inventory UI panel
|
|
public Transform spawnLocation; // Assign delivery location in Inspector
|
|
|
|
[Header("Item Data Assets")]
|
|
public List<ShopItemData> itemDataAssets; // Assign in Inspector
|
|
|
|
private Dictionary<string, ShopItemData> itemDatabase = new();
|
|
private Dictionary<string, int> itemStock = new(); // Track stock per item
|
|
|
|
private bool isInventoryOpen = false;
|
|
public bool IsInventoryOpen => isInventoryOpen;
|
|
|
|
void Awake()
|
|
{
|
|
Instance = this;
|
|
InitializeInventory();
|
|
if (inventoryUIPanel != null)
|
|
inventoryUIPanel.SetActive(false);
|
|
}
|
|
|
|
void InitializeInventory()
|
|
{
|
|
itemDatabase.Clear();
|
|
itemStock.Clear();
|
|
foreach (var data in itemDataAssets)
|
|
{
|
|
if (data != null && !itemDatabase.ContainsKey(data.itemName))
|
|
{
|
|
itemDatabase[data.itemName] = data;
|
|
itemStock[data.itemName] = 0; // Default starting stock
|
|
Debug.Log($"📦 Added item to inventory: {data.itemName} - £{data.price:0.00}");
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- Public API for UI and AI ---
|
|
|
|
public List<string> GetItemNames() => new List<string>(itemDatabase.Keys);
|
|
|
|
public ShopItemData GetItemData(string itemName) =>
|
|
itemDatabase.ContainsKey(itemName) ? itemDatabase[itemName] : null;
|
|
|
|
public int GetStock(string itemName) =>
|
|
itemStock.ContainsKey(itemName) ? itemStock[itemName] : 0;
|
|
|
|
// --- UI Control ---
|
|
|
|
public void OpenInventory()
|
|
{
|
|
if (isInventoryOpen)
|
|
return;
|
|
|
|
isInventoryOpen = true;
|
|
if (inventoryUIPanel != null)
|
|
inventoryUIPanel.SetActive(true);
|
|
Debug.Log("📦 Opening shop inventory...");
|
|
ShopkeeperUIController.Instance?.ShowInventory(itemDatabase);
|
|
LockCursor(false); // Unlock cursor for UI
|
|
}
|
|
|
|
public void CloseInventory()
|
|
{
|
|
if (!isInventoryOpen)
|
|
return;
|
|
|
|
isInventoryOpen = false;
|
|
if (inventoryUIPanel != null)
|
|
inventoryUIPanel.SetActive(false);
|
|
Debug.Log("📦 Closing shop inventory...");
|
|
ShopkeeperUIController.Instance?.HideInventory();
|
|
LockCursor(true); // Lock cursor for gameplay
|
|
}
|
|
|
|
void LockCursor(bool locked)
|
|
{
|
|
Cursor.lockState = locked ? CursorLockMode.Locked : CursorLockMode.None;
|
|
Cursor.visible = !locked;
|
|
}
|
|
|
|
// --- Stock and Price Management ---
|
|
|
|
public void RestockItem(string itemName, int amount)
|
|
{
|
|
if (!itemDatabase.ContainsKey(itemName))
|
|
{
|
|
Debug.LogWarning($"Item {itemName} not found in inventory.");
|
|
return;
|
|
}
|
|
|
|
var item = itemDatabase[itemName];
|
|
float totalCost = item.price * amount;
|
|
|
|
if (FinanceManager.Instance == null || FinanceManager.Instance.SpendMoney(totalCost))
|
|
{
|
|
itemStock[itemName] += amount;
|
|
GeneralUIController.Instance?.ShowMessage($"📦 Stock Updated: +{amount} {itemName}");
|
|
SpawnItems(itemName, amount);
|
|
}
|
|
}
|
|
|
|
public void SetItemPrice(string itemName, float price)
|
|
{
|
|
if (itemDatabase.ContainsKey(itemName))
|
|
{
|
|
itemDatabase[itemName].price = price;
|
|
Debug.Log($"Set price of {itemName} to £{price:0.00}");
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning($"Item {itemName} not found in inventory.");
|
|
}
|
|
}
|
|
|
|
// --- Spawning Items ---
|
|
|
|
void SpawnItems(string itemName, int amount)
|
|
{
|
|
var data = itemDatabase[itemName];
|
|
int packSize = Mathf.Max(1, data.packSize);
|
|
|
|
if (amount < packSize || data.cratePrefab == null)
|
|
{
|
|
// Spawn individual items
|
|
for (int i = 0; i < amount; i++)
|
|
{
|
|
SpawnSingleItem(data, spawnLocation.position + Vector3.up * 2f);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int numCrates = amount / packSize;
|
|
int leftovers = amount % packSize;
|
|
|
|
for (int c = 0; c < numCrates; c++)
|
|
{
|
|
// Spawn crate (make sure crate prefab has a Rigidbody and is NOT kinematic)
|
|
GameObject crate = Instantiate(data.cratePrefab, spawnLocation.position + Vector3.up * 2f, Quaternion.identity);
|
|
crate.name = $"{itemName}_Crate";
|
|
|
|
// Arrange items in a grid inside the crate, using localPosition
|
|
int gridCols = Mathf.CeilToInt(Mathf.Sqrt(packSize));
|
|
for (int i = 0; i < packSize; i++)
|
|
{
|
|
int row = i / gridCols;
|
|
int col = i % gridCols;
|
|
Vector3 offset = new Vector3(col * 0.5f, 0.2f, row * 0.3f); // Y offset to place items above crate floor
|
|
|
|
GameObject item = SpawnSingleItem(data, Vector3.zero); // Spawn at origin, we'll set localPosition
|
|
item.transform.SetParent(crate.transform);
|
|
item.transform.localPosition = offset;
|
|
|
|
// Make item kinematic so it stays in place until crate is opened
|
|
Rigidbody rb = item.GetComponent<Rigidbody>();
|
|
if (rb != null) rb.isKinematic = true;
|
|
}
|
|
}
|
|
|
|
// Spawn any leftovers as individuals
|
|
for (int i = 0; i < leftovers; i++)
|
|
{
|
|
SpawnSingleItem(data, spawnLocation.position + Vector3.up * 2f);
|
|
}
|
|
}
|
|
}
|
|
|
|
GameObject SpawnSingleItem(ShopItemData data, Vector3 position)
|
|
{
|
|
GameObject newItem = Instantiate(data.prefab, position, Quaternion.identity);
|
|
newItem.name = data.itemName;
|
|
Rigidbody rb = newItem.GetComponent<Rigidbody>();
|
|
if (rb == null) rb = newItem.AddComponent<Rigidbody>();
|
|
Collider col = newItem.GetComponent<Collider>();
|
|
if (col != null && col.sharedMaterial == null)
|
|
{
|
|
PhysicsMaterial bounceMat = new PhysicsMaterial("CartoonBounce");
|
|
bounceMat.bounciness = 0.2f;
|
|
bounceMat.bounceCombine = PhysicsMaterialCombine.Maximum;
|
|
bounceMat.frictionCombine = PhysicsMaterialCombine.Minimum;
|
|
col.sharedMaterial = bounceMat;
|
|
}
|
|
rb.AddForce(new Vector3(Random.Range(-1f, 1f), 0, Random.Range(-1f, 1f)) * 2f, ForceMode.Impulse);
|
|
var shopItem = newItem.GetComponent<ShopItem>();
|
|
if (shopItem != null)
|
|
shopItem.data = data;
|
|
return newItem;
|
|
}
|
|
} |