Files
Shopkeeper/Assets/Scripts/Items/ShopInventory.cs
Caleb Sandford deQuincey e9c9bc4409 initial game submission
2025-06-11 13:04:35 +01:00

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;
}
}