stack item pickup (in progress), throwable hand consumes items, spawnable objects tied to item definitions

This commit is contained in:
2026-09-16 22:48:52 -05:00
parent d8295719b0
commit f4642ea005
17 changed files with 444 additions and 26 deletions
+13 -4
View File
@@ -35,18 +35,26 @@ private void Update()
}
}
// we'll set this up to only try to add one item to the inventory at a time for now
// there won't be stacked items in the wild for right now
public bool AddItem(Item item, int quantity)
{
int curQuantity = quantity;
// first try to stack
for (int i = 0; i < itemSlots.Length; i++)
{
if (itemSlots[i].item == item.id && itemSlots[i].quantity < item.maxStack)
if (itemSlots[i].item == item.id && itemSlots[i].quantity + quantity < item.maxStack)
{
itemSlots[i].quantity += 1;
return true;
}
else if (itemSlots[i].item == item.id)
{
curQuantity = quantity - (item.maxStack - itemSlots[i].quantity);
itemSlots[i].quantity = item.maxStack;
if (curQuantity <= 0)
return true;
}
}
// no stack to add to, try to find an empty slot
@@ -56,7 +64,7 @@ public bool AddItem(Item item, int quantity)
{
itemSlots[i] = new ItemSlot();
itemSlots[i].quantity = 1;
itemSlots[i].quantity = curQuantity;
itemSlots[i].item = item.id;
return true;
}
@@ -88,6 +96,7 @@ public bool RemoveItemQuantity(ItemIdEnum itemId, int quantity)
// we have exactly enough in the current slot, so nullify it and
// exit
itemSlots[i].item = ItemIdEnum.NONE;
itemSlots[i].quantity = 0;
break;
}
else
+2
View File
@@ -17,6 +17,7 @@ public class GameManager : MonoBehaviour
public MenuController MenuController { get; private set; }
public SoundSettingManager SoundSettingManager { get; private set; }
public PlayerController PlayerController { get; private set; }
public ItemInstantiationManager ItemInstantiationManager { get; private set; }
public Image BlackScreen { get; private set; }
// Are we currently in a scene transition?
@@ -59,6 +60,7 @@ private void ReloadReferences()
Instance.Inventory = GetComponent<Inventory>();
Instance.TimeManager = GetComponent<TimeManager>();
Instance.PlayerManager = GetComponent<PlayerManager>();
Instance.ItemInstantiationManager = GetComponent<ItemInstantiationManager>();
Instance.SoundSettingManager = GetComponent<SoundSettingManager>();
Instance.SoundSettingManager.ReloadReferences();
@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using UnityEngine;
public class ItemInstantiationManager : MonoBehaviour
{
private Dictionary<ItemIdEnum, GameObject> spawnablePrefabs = new Dictionary<ItemIdEnum, GameObject>();
private void Awake()
{
LoadSpawnablePrefabs();
}
private void LoadSpawnablePrefabs()
{
foreach (ItemIdEnum itemId in Enum.GetValues(typeof(ItemIdEnum)))
{
Item item = ItemUtilities.GetItemFromId(itemId);
if (item.throwable)
{
GameObject prefab = Resources.Load<GameObject>($"SpawnablePrefabs/ID_{itemId.ToString()}");
if (prefab != null)
{
spawnablePrefabs.Add(itemId, prefab);
}
}
}
}
public GameObject GetThrowablePrefab(ItemIdEnum itemId)
{
return spawnablePrefabs[itemId];
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f2dcea982e135f3448df561481c5fea7
@@ -255,14 +255,14 @@ void RotatePlayerTowardMouse()
Vector3 targetPoint;
// 1. Try real world hit first (most stable)
if (Physics.Raycast(ray, out RaycastHit hit, 1000f))
// Try real world hit first (most stable), ignoring Dither layer
if (Physics.Raycast(ray, out RaycastHit hit, 1000f, ~LayerMask.GetMask("Dither")))
{
targetPoint = hit.point;
}
else
{
// 2. Fallback to plane at player height
// Fallback to plane at player height
Plane plane = new Plane(Vector3.up, DougBody.transform.position);
if (!plane.Raycast(ray, out float enter))
+53 -8
View File
@@ -8,7 +8,8 @@ public class ThrowableHand : Tool
public float range;
public float forceModifier;
public float loft;
public GameObject testBomb;
public ItemIdEnum activeThrowable;
private int activeThrowableIndex;
// Mathematical plane used to catch the raycast from camera to get direction for
// looking at the mouse
@@ -89,20 +90,64 @@ private void DrawTargetProjection()
targetProjection.transform.position = finalPosition;
}
private ItemIdEnum GetNextThrowable()
{
// Use active throwable index to let us continue to search for throwables
if (activeThrowableIndex >= GameManager.Instance.Inventory.itemSlots.Length)
activeThrowableIndex = 0;
// Search starting at throwable index
for (int i = activeThrowableIndex; i < GameManager.Instance.Inventory.itemSlots.Length; i++)
{
if (ItemUtilities.GetItemFromId(GameManager.Instance.Inventory.itemSlots[i].item).throwable)
{
activeThrowableIndex = i;
return GameManager.Instance.Inventory.itemSlots[i].item;
}
}
// Wrap back around to 0 if we didn't find anything
for (int i = 0; i < activeThrowableIndex; i++)
{
if (ItemUtilities.GetItemFromId(GameManager.Instance.Inventory.itemSlots[i].item).throwable)
{
activeThrowableIndex = i;
return GameManager.Instance.Inventory.itemSlots[i].item;
}
}
// We have no throwable items...
activeThrowableIndex = 0;
return ItemIdEnum.NONE;
}
public override void Use()
{
GameObject newBomb = Instantiate(testBomb);
newBomb.transform.position = transform.position;
if (activeThrowable == ItemIdEnum.NONE)
{
activeThrowable = GetNextThrowable();
}
Vector3 direction = transform.forward * throwForce * forceModifier;
direction += GameManager.Instance.PlayerController.GetVelocity();
direction.y = loft;
if (activeThrowable != ItemIdEnum.NONE && GameManager.Instance.Inventory.GetItemQuantity(activeThrowable) > 0)
{
GameObject throwable = Instantiate(GameManager.Instance.ItemInstantiationManager.GetThrowablePrefab(activeThrowable));
newBomb.GetComponent<Rigidbody>().AddForce(direction, ForceMode.Impulse);
if (throwable != null)
{
throwable.transform.position = transform.position;
Vector3 direction = transform.forward * throwForce * forceModifier;
direction += GameManager.Instance.PlayerController.GetVelocity();
direction.y = loft;
throwable.GetComponent<Rigidbody>().AddForce(direction, ForceMode.Impulse);
GameManager.Instance.Inventory.RemoveItemQuantity(activeThrowable, 1);
}
}
}
public override void UseAlt()
{
throw new System.NotImplementedException();
activeThrowable = GetNextThrowable();
}
}
+19 -4
View File
@@ -9,14 +9,16 @@ public class Item
public int maxStack = 10;
public string description = "";
public string itemImagePath = "";
public bool throwable = false;
public Item(string itemName, ItemIdEnum id, int maxStack, string description, string itemImagePath)
public Item(string itemName, ItemIdEnum id, int maxStack, string description, string itemImagePath, bool throwable = false)
{
this.itemName = itemName;
this.id = id;
this.maxStack = maxStack;
this.description = description;
this.itemImagePath = itemImagePath;
this.throwable = throwable;
}
public Item(ItemIdEnum id)
@@ -28,15 +30,18 @@ public Item(ItemIdEnum id)
this.maxStack = newItem.maxStack;
this.description = newItem.description;
this.itemImagePath= newItem.itemImagePath;
this.throwable = newItem.throwable;
}
}
public enum ItemIdEnum
{
NONE = 0,
STAR_SHARD = 1
STAR_SHARD = 1,
DYNAMITE = 2
}
[System.Serializable]
public static class ItemUtilities
{
// THIS IS WHERE ALL THE ITEMS ARE DEFINED
@@ -50,9 +55,19 @@ public static Item GetItemFromId(ItemIdEnum itemId)
id: itemId,
maxStack: 10,
description: "A rare material that can only be found here in the valley.",
itemImagePath: "ItemSprites/starShard");
itemImagePath: "ItemSprites/starShard",
false);
case ItemIdEnum.DYNAMITE:
return new Item(
itemName: "Dynamite",
id: itemId,
maxStack: 10,
description: "A throwable red stick that goes BOOM (after a short time).",
itemImagePath: "ItemSprites/dynamite",
true);
}
return new Item("", itemId, 0, "", "ItemSprites/noneItem"); ;
return new Item("", itemId, 0, "", "ItemSprites/noneItem");
}
}