Add inventory system
This commit is contained in:
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@@ -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
|
||||
}
|
@@ -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"]
|
||||
|
@@ -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
14
scenes/MapBounds.tscn
Normal 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
6
scenes/Systems.tscn
Normal 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")
|
@@ -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)
|
||||
|
13
scenes/Testing/TestCube.tscn
Normal file
13
scenes/Testing/TestCube.tscn
Normal 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")
|
@@ -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)
|
||||
|
@@ -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(
|
11
scripts/Entities/TestNPCController.gd
Normal file
11
scripts/Entities/TestNPCController.gd
Normal 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
36
scripts/Items/Item.gd
Normal 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;
|
8
scripts/Items/ItemStack.gd
Normal file
8
scripts/Items/ItemStack.gd
Normal 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
13
scripts/Items/Potion.gd
Normal 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
17
scripts/MapBounds.gd
Normal 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
1
scripts/MapBounds.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dbah1pmk8jola
|
1
scripts/OverworldEntity.gd.uid
Normal file
1
scripts/OverworldEntity.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dr3asofxu1pep
|
1
scripts/RosaCamera.gd.uid
Normal file
1
scripts/RosaCamera.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cubx2asrudfyp
|
1
scripts/RosaController.gd.uid
Normal file
1
scripts/RosaController.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dnls1370w0gr4
|
86
scripts/Systems/ItemSystem.gd
Normal file
86
scripts/Systems/ItemSystem.gd
Normal 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)
|
3
scripts/Systems/Systems.gd
Normal file
3
scripts/Systems/Systems.gd
Normal file
@@ -0,0 +1,3 @@
|
||||
class_name Systems extends Node
|
||||
|
||||
var ITEM = preload("res://scripts/Systems/ItemSystem.gd").new()
|
@@ -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
|
1
scripts/TestNPCController.gd.uid
Normal file
1
scripts/TestNPCController.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dq7mgokmvo80u
|
1
shaders/Map Shader.gdshader.uid
Normal file
1
shaders/Map Shader.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://67hsyo0qqlfm
|
1
shaders/NPC Shader.gdshader.uid
Normal file
1
shaders/NPC Shader.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://7h2axb2tsh17
|
Reference in New Issue
Block a user