diff --git a/.vscode/settings.json b/.vscode/settings.json index 5c972ae..811746e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -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 } \ No newline at end of file diff --git a/scenes/NPC/Rosa.tscn b/scenes/Entities/Rosa.tscn similarity index 88% rename from scenes/NPC/Rosa.tscn rename to scenes/Entities/Rosa.tscn index 0c18773..8bb4959 100644 --- a/scenes/NPC/Rosa.tscn +++ b/scenes/Entities/Rosa.tscn @@ -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"] diff --git a/scenes/NPC/TestNPC.tscn b/scenes/Entities/TestNPC.tscn similarity index 92% rename from scenes/NPC/TestNPC.tscn rename to scenes/Entities/TestNPC.tscn index e6c3140..579541c 100644 --- a/scenes/NPC/TestNPC.tscn +++ b/scenes/Entities/TestNPC.tscn @@ -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"] diff --git a/scenes/MapBounds.tscn b/scenes/MapBounds.tscn new file mode 100644 index 0000000..2273c3e --- /dev/null +++ b/scenes/MapBounds.tscn @@ -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"] diff --git a/scenes/Systems.tscn b/scenes/Systems.tscn new file mode 100644 index 0000000..e8ace88 --- /dev/null +++ b/scenes/Systems.tscn @@ -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") diff --git a/scenes/TestScene.tscn b/scenes/TestScene.tscn index a0c80c0..89bd8cc 100644 --- a/scenes/TestScene.tscn +++ b/scenes/TestScene.tscn @@ -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) diff --git a/scenes/Testing/TestCube.tscn b/scenes/Testing/TestCube.tscn new file mode 100644 index 0000000..3d23868 --- /dev/null +++ b/scenes/Testing/TestCube.tscn @@ -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") diff --git a/scripts/OverworldEntity.gd b/scripts/Entities/OverworldEntity.gd similarity index 83% rename from scripts/OverworldEntity.gd rename to scripts/Entities/OverworldEntity.gd index 58e9f10..349ce58 100644 --- a/scripts/OverworldEntity.gd +++ b/scripts/Entities/OverworldEntity.gd @@ -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) diff --git a/scripts/RosaCamera.gd b/scripts/Entities/RosaCamera.gd similarity index 100% rename from scripts/RosaCamera.gd rename to scripts/Entities/RosaCamera.gd diff --git a/scripts/RosaController.gd b/scripts/Entities/RosaController.gd similarity index 94% rename from scripts/RosaController.gd rename to scripts/Entities/RosaController.gd index c0c59c2..f2c0299 100644 --- a/scripts/RosaController.gd +++ b/scripts/Entities/RosaController.gd @@ -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( diff --git a/scripts/Entities/TestNPCController.gd b/scripts/Entities/TestNPCController.gd new file mode 100644 index 0000000..25fa899 --- /dev/null +++ b/scripts/Entities/TestNPCController.gd @@ -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 diff --git a/scripts/Items/Item.gd b/scripts/Items/Item.gd new file mode 100644 index 0000000..f55fbcb --- /dev/null +++ b/scripts/Items/Item.gd @@ -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; \ No newline at end of file diff --git a/scripts/Items/ItemStack.gd b/scripts/Items/ItemStack.gd new file mode 100644 index 0000000..afcd3d8 --- /dev/null +++ b/scripts/Items/ItemStack.gd @@ -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; diff --git a/scripts/Items/Potion.gd b/scripts/Items/Potion.gd new file mode 100644 index 0000000..c792e59 --- /dev/null +++ b/scripts/Items/Potion.gd @@ -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"); \ No newline at end of file diff --git a/scripts/MapBounds.gd b/scripts/MapBounds.gd new file mode 100644 index 0000000..f18b546 --- /dev/null +++ b/scripts/MapBounds.gd @@ -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; diff --git a/scripts/MapBounds.gd.uid b/scripts/MapBounds.gd.uid new file mode 100644 index 0000000..aaab6dd --- /dev/null +++ b/scripts/MapBounds.gd.uid @@ -0,0 +1 @@ +uid://dbah1pmk8jola diff --git a/scripts/OverworldEntity.gd.uid b/scripts/OverworldEntity.gd.uid new file mode 100644 index 0000000..39aa410 --- /dev/null +++ b/scripts/OverworldEntity.gd.uid @@ -0,0 +1 @@ +uid://dr3asofxu1pep diff --git a/scripts/RosaCamera.gd.uid b/scripts/RosaCamera.gd.uid new file mode 100644 index 0000000..bbc331f --- /dev/null +++ b/scripts/RosaCamera.gd.uid @@ -0,0 +1 @@ +uid://cubx2asrudfyp diff --git a/scripts/RosaController.gd.uid b/scripts/RosaController.gd.uid new file mode 100644 index 0000000..9d7727d --- /dev/null +++ b/scripts/RosaController.gd.uid @@ -0,0 +1 @@ +uid://dnls1370w0gr4 diff --git a/scripts/Systems/ItemSystem.gd b/scripts/Systems/ItemSystem.gd new file mode 100644 index 0000000..5696c21 --- /dev/null +++ b/scripts/Systems/ItemSystem.gd @@ -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) diff --git a/scripts/Systems/Systems.gd b/scripts/Systems/Systems.gd new file mode 100644 index 0000000..3829581 --- /dev/null +++ b/scripts/Systems/Systems.gd @@ -0,0 +1,3 @@ +class_name Systems extends Node + +var ITEM = preload("res://scripts/Systems/ItemSystem.gd").new() diff --git a/scripts/TestNPCController.gd b/scripts/TestNPCController.gd deleted file mode 100644 index 8dcef6c..0000000 --- a/scripts/TestNPCController.gd +++ /dev/null @@ -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 diff --git a/scripts/TestNPCController.gd.uid b/scripts/TestNPCController.gd.uid new file mode 100644 index 0000000..ff8ec8e --- /dev/null +++ b/scripts/TestNPCController.gd.uid @@ -0,0 +1 @@ +uid://dq7mgokmvo80u diff --git a/shaders/Map Shader.gdshader.uid b/shaders/Map Shader.gdshader.uid new file mode 100644 index 0000000..e823eea --- /dev/null +++ b/shaders/Map Shader.gdshader.uid @@ -0,0 +1 @@ +uid://67hsyo0qqlfm diff --git a/shaders/NPC Shader.gdshader.uid b/shaders/NPC Shader.gdshader.uid new file mode 100644 index 0000000..7ff2aba --- /dev/null +++ b/shaders/NPC Shader.gdshader.uid @@ -0,0 +1 @@ +uid://7h2axb2tsh17