Add inventory system

This commit is contained in:
2025-01-05 12:05:55 -06:00
parent 750719ff88
commit e74878eb80
25 changed files with 247 additions and 46 deletions

View File

@@ -1,6 +1,6 @@
{
"godotTools.editorPath.godot4": "/var/lib/flatpak/app/org.godotengine.Godot/current/active/export/bin/org.godotengine.Godot",
"godotTools.editorPath.godot4": "/var/lib/flatpak/app/org.godotengine.Godot/current/active/export/bin/org.godotengine.Godot",
"terminal.integrated.tabs.enabled": false,
"editor.insertSpaces": false,
"editor.tabSize": 4,
"terminal.integrated.tabs.enabled": false
"editor.tabSize": 4
}

View File

@@ -1,7 +1,7 @@
[gd_scene load_steps=8 format=3 uid="uid://yhtpoum3eek7"]
[ext_resource type="Script" path="res://scripts/RosaController.gd" id="1_3g383"]
[ext_resource type="Script" path="res://scripts/RosaCamera.gd" id="2_tr66j"]
[ext_resource type="Script" path="res://scripts/Entities/RosaController.gd" id="1_3g383"]
[ext_resource type="Script" path="res://scripts/Entities/RosaCamera.gd" id="2_tr66j"]
[ext_resource type="Shader" path="res://shaders/NPC Shader.gdshader" id="3_j5vis"]
[ext_resource type="Texture2D" uid="uid://i34vweii6joy" path="res://textures/rosa.png" id="4_qdjyy"]

View File

@@ -1,6 +1,6 @@
[gd_scene load_steps=7 format=3 uid="uid://dr4b2pmsknuhc"]
[ext_resource type="Script" path="res://scripts/TestNPCController.gd" id="1_61g2d"]
[ext_resource type="Script" path="res://scripts/Entities/TestNPCController.gd" id="1_61g2d"]
[ext_resource type="Shader" path="res://shaders/NPC Shader.gdshader" id="1_xgcv1"]
[ext_resource type="Texture2D" uid="uid://i34vweii6joy" path="res://textures/rosa.png" id="2_shls4"]

14
scenes/MapBounds.tscn Normal file
View File

@@ -0,0 +1,14 @@
[gd_scene load_steps=3 format=3 uid="uid://cy4r0tp2htivb"]
[ext_resource type="Script" path="res://scripts/MapBounds.gd" id="1_43dqt"]
[sub_resource type="BoxShape3D" id="BoxShape3D_ep4u2"]
[node name="MapBounds" type="Area3D"]
script = ExtResource("1_43dqt")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
shape = SubResource("BoxShape3D_ep4u2")
[connection signal="body_entered" from="." to="." method="_on_body_entered"]
[connection signal="body_exited" from="." to="." method="_on_body_exited"]

6
scenes/Systems.tscn Normal file
View File

@@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://iibqlagufwhm"]
[ext_resource type="Script" path="res://scripts/Systems/Systems.gd" id="1_uen2c"]
[node name="Systems" type="Node3D"]
script = ExtResource("1_uen2c")

View File

@@ -1,8 +1,10 @@
[gd_scene load_steps=7 format=3 uid="uid://bdrpqtbwvtivd"]
[gd_scene load_steps=9 format=3 uid="uid://bdrpqtbwvtivd"]
[ext_resource type="PackedScene" uid="uid://yhtpoum3eek7" path="res://scenes/NPC/Rosa.tscn" id="1_3u2u0"]
[ext_resource type="PackedScene" uid="uid://dr4b2pmsknuhc" path="res://scenes/NPC/TestNPC.tscn" id="2_6f3lj"]
[ext_resource type="PackedScene" uid="uid://yhtpoum3eek7" path="res://scenes/Entities/Rosa.tscn" id="1_3u2u0"]
[ext_resource type="PackedScene" uid="uid://iibqlagufwhm" path="res://scenes/Systems.tscn" id="1_3x3uf"]
[ext_resource type="PackedScene" uid="uid://dr4b2pmsknuhc" path="res://scenes/Entities/TestNPC.tscn" id="2_6f3lj"]
[ext_resource type="PackedScene" uid="uid://7wjfo6u4dp3h" path="res://scenes/Maps/test.tscn" id="4_18e1y"]
[ext_resource type="PackedScene" uid="uid://cy4r0tp2htivb" path="res://scenes/MapBounds.tscn" id="4_gv7tl"]
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_1b6it"]
sky_horizon_color = Color(0.59625, 0.6135, 0.6375, 1)
@@ -19,6 +21,8 @@ sky = SubResource("Sky_weucl")
[node name="TestSceneRoot" type="Node3D"]
[node name="Systems" parent="." instance=ExtResource("1_3x3uf")]
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = SubResource("Environment_18twt")
@@ -34,3 +38,6 @@ light_energy = 15.315
omni_range = 281.646
[node name="test" parent="." instance=ExtResource("4_18e1y")]
[node name="MapBounds" parent="." instance=ExtResource("4_gv7tl")]
transform = Transform3D(22.0363, 0, 0, 0, 7.5201, 0, 0, 0, 19.278, 1.48402, 2.89779, 1.65935)

View File

@@ -0,0 +1,13 @@
[gd_scene load_steps=3 format=3 uid="uid://dlwauw7qvyxnn"]
[sub_resource type="BoxShape3D" id="BoxShape3D_qpmw6"]
[sub_resource type="BoxMesh" id="BoxMesh_lddii"]
[node name="TestCube" type="StaticBody3D"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
shape = SubResource("BoxShape3D_qpmw6")
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = SubResource("BoxMesh_lddii")

View File

@@ -1,4 +1,5 @@
extends CharacterBody3D
class_name OverworldEntity
enum Direction {
NORTH,
@@ -16,6 +17,12 @@ var meshInstance:MeshInstance3D;
var underFootTile:int = -1;
var underFootPosition:Vector3;
var withinMapBounds:MapBounds;
var withinBoundsLastFrame:bool = true;
func getSystems() -> Systems:
return get_tree().current_scene.get_node("Systems") as Systems;
func getDirectionVector() -> Vector3:
match direction:
Direction.NORTH:
@@ -52,7 +59,7 @@ func _updateTileData() -> void:
var collider = result.collider;
var colliderMesh = collider.get_node("../");
if !colliderMesh or !colliderMesh.mesh or colliderMesh.mesh.get_surface_count() == 0:
if !colliderMesh or !(colliderMesh is ArrayMesh) or !colliderMesh.mesh or colliderMesh.mesh.get_surface_count() == 0:
return;
# Get the face index (triangle)
@@ -90,6 +97,14 @@ func _ready() -> void:
pass
func _process(delta:float) -> void:
# Handle entity leaving map bounds
if !withinMapBounds:
if !withinBoundsLastFrame:
print("Entity ", self.name, " was out of map bounds for two frames");
withinBoundsLastFrame = false;
else:
withinBoundsLastFrame = true;
# Update logic
updateOverworldLogic(delta)

View File

@@ -1,4 +1,4 @@
extends "res://scripts/OverworldEntity.gd"
class_name RosaController extends "res://scripts/Entities/OverworldEntity.gd"
var interactRange = 0.7;
@@ -27,7 +27,6 @@ func updateMovement(delta) -> void:
if(dir.x != 0 or dir.y != 0):
velocity.x = dir.x * speed * delta;
velocity.z = dir.y * speed * delta;
print(dir.length());
# Update direction
if(dir.x >= abs(dir.y) and(

View File

@@ -0,0 +1,11 @@
class_name TestNPCController extends "res://scripts/Entities/OverworldEntity.gd"
func interact(interactor) -> void:
var systems = getSystems();
systems.ITEM.addItem(systems.ITEM.ITEM_POTION, 1);
#var itemSystem = (get_node("Systems") as Systems).ITEM;
#itemSystem.addItem(itemSystem.ITEM_POTION, 1);
#pass
func updateMovement(delta) -> void:
pass

36
scripts/Items/Item.gd Normal file
View File

@@ -0,0 +1,36 @@
class_name Item
enum ItemCategory {
MEDICINE,
KEY_ITEM,
INGREDIENT
};
func getName() -> String:
push_error("getName() must be overridden in derived classes");
return "";
func isStackable() -> bool:
return true;
func isDroppable() -> bool:
return true;
func isSellable() -> bool:
return true;
func getSellPrice() -> int:
return 0;
func getBuyPrice() -> int:
return 0;
func isConsumable() -> bool:
return false;
func consume() -> void:
pass
func getCategory() -> ItemCategory:
push_error("getCategory() must be overriden in derived class");
return ItemCategory.MEDICINE;

View File

@@ -0,0 +1,8 @@
class_name ItemStack
var item:Item;
var quantity:int;
func _init(item:Item, quantity:int = 1):
self.item = item;
self.quantity = quantity;

13
scripts/Items/Potion.gd Normal file
View File

@@ -0,0 +1,13 @@
class_name Potion extends "res://scripts/Items/Item.gd"
func getName() -> String:
return "Potion"
func getCategory() -> ItemCategory:
return ItemCategory.MEDICINE;
func isConsumable() -> bool:
return true;
func consume() -> void:
print("Consuming Potion");

17
scripts/MapBounds.gd Normal file
View File

@@ -0,0 +1,17 @@
extends Area3D
class_name MapBounds
func _ready() -> void:
pass
func _on_body_entered(body: Node3D) -> void:
if (!body is OverworldEntity):
return
print("Entered overworld ent")
(body as OverworldEntity).withinMapBounds = self;
func _on_body_exited(body: Node3D) -> void:
if (!body is OverworldEntity):
return
print("Entered overworld ent")
(body as OverworldEntity).withinMapBounds = null;

1
scripts/MapBounds.gd.uid Normal file
View File

@@ -0,0 +1 @@
uid://dbah1pmk8jola

View File

@@ -0,0 +1 @@
uid://dr3asofxu1pep

View File

@@ -0,0 +1 @@
uid://cubx2asrudfyp

View File

@@ -0,0 +1 @@
uid://dnls1370w0gr4

View File

@@ -0,0 +1,86 @@
class_name ItemSystem
const Item = preload("res://scripts/Items/Item.gd");
const ItemStack = preload("res://scripts/Items/ItemStack.gd");
enum ItemSortType {
NAME,
TYPE
};
class ItemStackNameComparator:
static func _sort(a, b):
return a.item.getName().to_lower() < b.item.getName().to_lower()
class ItemStackTypeComparator:
static func _sort(a, b):
return a.item.getCategory() < b.item.getCategory()
# Constants
const ITEM_STACK_SIZE_MAX = 99;
var ITEM_POTION = preload("res://scripts/Items/Potion.gd").new()
var inventory:Array[ItemStack] = [];
# Methods
func addItem(item: Item, quantity: int = 1) -> void:
print("Adding ", quantity, "x ", item.getName());
if !item.isStackable():
# Item cannot be stacked, add each item to inv
for i in range(quantity):
inventory.append(ItemStack.new(item, 1))
return
# Check for existing stacks
for stack in inventory:
if stack.item != item or stack.quantity >= ITEM_STACK_SIZE_MAX:
continue
var spaceAvailable = ITEM_STACK_SIZE_MAX - stack.quantity
if quantity <= spaceAvailable:
stack.quantity += quantity;
return
stack.quantity = ITEM_STACK_SIZE_MAX;
quantity -= spaceAvailable;
# Add any remaining inventory as new stack.
while quantity > 0:
var newStackQuantity = min(quantity, ITEM_STACK_SIZE_MAX);
inventory.append(ItemStack.new(item, newStackQuantity));
quantity -= newStackQuantity;
func removeItem(item: Item, quantity: int) -> void:
var totalQuantity = 0
# Calculate total quantity of the item in the inventory
for stack in inventory:
if stack.item != item:
continue
totalQuantity += stack.quantity
if totalQuantity < quantity:
push_error("Not enough quantity to remove");
return
# Remove the quantity from the stacks
for stack in inventory:
if stack.item != item:
continue
if stack.quantity < quantity:
quantity -= stack.quantity
inventory.erase(stack)
stack.quantity -= quantity
if stack.quantity == 0:
inventory.erase(stack)
if quantity == 0:
return
func sortBy(by:ItemSortType) -> void:
match by:
ItemSortType.NAME:
inventory.sort_custom(ItemStackNameComparator._sort)
ItemSortType.TYPE:
inventory.sort_custom(ItemStackTypeComparator._sort)

View File

@@ -0,0 +1,3 @@
class_name Systems extends Node
var ITEM = preload("res://scripts/Systems/ItemSystem.gd").new()

View File

@@ -1,34 +0,0 @@
extends "res://scripts/OverworldEntity.gd"
func interact(interactor) -> void:
print("Hello, I am an NPC!")
pass
func updateMovement(delta) -> void:
pass
# User movement
#var dir:Vector2 = Input.get_vector("left", "right", "up", "down");
#if(dir.x != 0 or dir.y != 0):
#velocity.x = dir.x * speed * delta;
#velocity.z = dir.y * speed * delta;
#
## Update direction
#if(dir.x > 0):
#if(
#dir.y == 0 or
#(dir.y < 0 and direction == Direction.SOUTH) or
#(dir.y > 0 and direction == Direction.NORTH)
#):
#direction = Direction.EAST;
#elif (dir.x < 0):
#if(
#dir.y == 0 or
#(dir.y < 0 and direction == Direction.SOUTH) or
#(dir.y > 0 and direction == Direction.NORTH)
#):
#direction = Direction.WEST;
#elif (dir.y > 0):
#direction = Direction.SOUTH;
#elif (dir.y < 0):
#direction = Direction.NORTH;
#pass

View File

@@ -0,0 +1 @@
uid://dq7mgokmvo80u

View File

@@ -0,0 +1 @@
uid://67hsyo0qqlfm

View File

@@ -0,0 +1 @@
uid://7h2axb2tsh17