Added touchscreen controls!

This commit is contained in:
2026-01-13 22:47:30 +01:00
parent 89a41397d1
commit 0c0998cd05
65 changed files with 1672 additions and 3270 deletions

View File

@@ -0,0 +1,135 @@
@tool
@icon("TouchScreenButtonControl.svg")
class_name TouchScreenButtonControl
extends TextureButton
const DefaultValues := {
"expand": true,
"ignore_texture_size": true,
"stretch_mode": TextureButton.STRETCH_KEEP_ASPECT_CENTERED,
"action_mode": TextureButton.ACTION_MODE_BUTTON_PRESS,
"focus_mode": TextureButton.FOCUS_NONE,
}
@export var use_default_values := true
@export var touchscreen_only := false
# The actual variable that holds the data
var input_action: String = ""
# 2. MATCHED the property name here...
func _get_property_list() -> Array:
var properties: Array = []
if Engine.is_editor_hint():
InputMap.load_from_project_settings()
# Get actions and format them for the dropdown
var actions = InputMap.get_actions()
var action_list = ",".join(actions)
properties.append({
"name": "input_action",
"type": TYPE_STRING,
"hint": PROPERTY_HINT_ENUM_SUGGESTION,
"hint_string": ",".join(actions),
"usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR
})
return properties
func _set(property: StringName, value: Variant) -> bool:
if property == "input_action":
input_action = value
return true
return false
func _get(property: StringName) -> Variant:
if property == "input_action":
return input_action
return null
# Track multiple simultaneous touches for multitouch support
var active_touches := {} # Dictionary: touch_index -> bool (true if pressed)
var initial_press_touches := {} # Dictionary: touch_index -> bool (true if this button was pressed on initial touch)
func _init():
if use_default_values:
for k in DefaultValues.keys():
self.set(k, DefaultValues.get(k))
# Set mouse_filter to IGNORE so the button doesn't consume touch events
# This allows multiple buttons to detect the same touch simultaneously
mouse_filter = Control.MOUSE_FILTER_IGNORE
if touchscreen_only and not DisplayServer.is_touchscreen_available():
hide()
func press():
var input_event: InputEvent = InputMap.action_get_events(input_action)[0]
input_event.pressed = true
Input.parse_input_event(input_event)
func release():
var input_event: InputEvent = InputMap.action_get_events(input_action)[0]
input_event.pressed = false
Input.parse_input_event(input_event)
func is_in(pos: Vector2) -> bool:
# Get the global rect of this Control node in screen coordinates
var global_rect = get_global_rect()
# Check if the touch position is within the button's global rect
if pos.x >= global_rect.position.x and pos.x <= global_rect.position.x + global_rect.size.x:
if pos.y >= global_rect.position.y and pos.y <= global_rect.position.y + global_rect.size.y:
return true
return false
func _input(event):
# Use _input to receive all touch events
# IMPORTANT: _input is called on ALL nodes in the scene tree, so multiple buttons
# can receive the same event. We don't consume the event so others can too.
if event is InputEventScreenTouch:
if event.pressed:
# Check if this touch is within this button's bounds
if is_in(event.position):
# Start tracking this touch for this button
if event.index not in active_touches:
active_touches[event.index] = true
initial_press_touches[event.index] = true # Mark as initial press
press()
else:
# Touch released - check if we were tracking it
if event.index in active_touches:
# This touch was being tracked by this button, release it
active_touches.erase(event.index)
initial_press_touches.erase(event.index)
# Only release the action if no other touches are active for this button
if active_touches.is_empty():
release()
elif event is InputEventScreenDrag:
# Handle touch drag with smart re-activation logic
if event.index in active_touches:
# We're tracking this touch
if initial_press_touches.has(event.index):
# This was an initial press - keep it active even if touch moves outside
# Don't release until touch ends
pass
else:
# This was a re-activation (touch moved back into bounds)
# Check if touch moved back out of bounds
if not is_in(event.position):
# Touch moved out of bounds, release this re-activated button
active_touches.erase(event.index)
if active_touches.is_empty():
release()
else:
# We're not tracking this touch - check if it moved into our bounds
# This allows "tapping" behavior - touch can re-enter and activate button
if is_in(event.position):
# Touch moved into bounds, start tracking (but not as initial press)
active_touches[event.index] = true
press()
# CRITICAL: Never call get_viewport().set_input_as_handled() here
# This would prevent other buttons from receiving the same touch event
# mouse_filter is set to IGNORE so the TextureButton doesn't consume mouse/touch events

View File

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

View File

@@ -0,0 +1 @@
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><defs/><g><path d="M3,1 C2.7249,1 2.4771,1.1087 2.2929,1.2929 C2.1087,1.4771 2,1.7249 2,2 L2,4 C2,4.2751 2.1087,4.5229 2.2929,4.7071 C2.4771,4.8913 2.7249,5 3,5 L5,5 L5,4 L3,4 L3,2 L11,2 L11,4 L9,4 L9,5 L11,5 C11.2751,5 11.5229,4.8913 11.7071,4.7071 C11.8913,4.5229 12,4.2751 12,4 L12,2 C12,1.7249 11.8913,1.4771 11.7071,1.2929 C11.5229,1.1087 11.2751,1 11,1 L3,1 Z M8,8 L8,4 C8,3.4015 7.5531,3 7,3 C6.4469,3 6,3.4015 6,4 L6,11.05 L3.5,9.25 C2.9376,8.8026 2.2507,8.8435 1.8125,9.3125 C1.3692,9.787 1.3561,10.4968 1.875,11 L6,15 L12,15 C12.5502,15 13.0459,14.7826 13.4142,14.4142 C13.7826,14.0459 14,13.5502 14,13 L14,10 C14,9.4498 13.7826,8.9541 13.4142,8.5858 C13.0459,8.2174 12.5502,8 12,8 L8,8 Z" fill="rgb(142,239,151)" opacity="1"/></g></svg>

After

Width:  |  Height:  |  Size: 807 B

View File

@@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ckvwnehwdvwyq"
path="res://.godot/imported/TouchScreenButtonControl.svg-ec8e7f48e271699010d76650daf1583d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/touchscreenbuttoncontrol/TouchScreenButtonControl.svg"
dest_files=["res://.godot/imported/TouchScreenButtonControl.svg-ec8e7f48e271699010d76650daf1583d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://dsj828xm2e28w"]
[ext_resource type="Script" path="res://addons/touchscreenbuttoncontrol/TouchScreenButtonControl.gd" id="1_5k641"]
[node name="TouchScreenButtonControl" type="TextureButton"]
script = ExtResource("1_5k641")

View File

@@ -0,0 +1,15 @@
@tool
extends EditorPlugin
var MyCustomNode = preload("res://addons/touchscreenbuttoncontrol/TouchScreenButtonControl.gd")
func _enter_tree():
add_custom_type(
"TouchScreenButtonControl",
"Control",
TouchScreenButtonControl,
preload("res://addons/touchscreenbuttoncontrol/TouchScreenButtonControl.svg")
)
func _exit_tree():
remove_custom_type("TouchScreenButtonControl")

View File

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

View File

@@ -0,0 +1,13 @@
[gd_resource type="StyleBoxFlat" format=3 uid="uid://cv5o175a2677e"]
[resource]
bg_color = Color(0.3, 0.3, 0.3, 0.7)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.8, 0.8, 0.8, 0.9)
corner_radius_top_left = 40
corner_radius_top_right = 40
corner_radius_bottom_right = 40
corner_radius_bottom_left = 40

View File

@@ -0,0 +1 @@
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><defs/><g><path d="M3,1 C2.7249,1 2.4771,1.1087 2.2929,1.2929 C2.1087,1.4771 2,1.7249 2,2 L2,4 C2,4.2751 2.1087,4.5229 2.2929,4.7071 C2.4771,4.8913 2.7249,5 3,5 L5,5 L5,4 L3,4 L3,2 L11,2 L11,4 L9,4 L9,5 L11,5 C11.2751,5 11.5229,4.8913 11.7071,4.7071 C11.8913,4.5229 12,4.2751 12,4 L12,2 C12,1.7249 11.8913,1.4771 11.7071,1.2929 C11.5229,1.1087 11.2751,1 11,1 L3,1 Z M8,8 L8,4 C8,3.4015 7.5531,3 7,3 C6.4469,3 6,3.4015 6,4 L6,11.05 L3.5,9.25 C2.9376,8.8026 2.2507,8.8435 1.8125,9.3125 C1.3692,9.787 1.3561,10.4968 1.875,11 L6,15 L12,15 C12.5502,15 13.0459,14.7826 13.4142,14.4142 C13.7826,14.0459 14,13.5502 14,13 L14,10 C14,9.4498 13.7826,8.9541 13.4142,8.5858 C13.0459,8.2174 12.5502,8 12,8 L8,8 Z" fill="rgb(142,239,151)" opacity="1"/></g></svg>

After

Width:  |  Height:  |  Size: 807 B

View File

@@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://x5ggo5vlsqwn"
path="res://.godot/imported/icon.svg-e7770945a21c9fca528355bbf6b1708f.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/touchscreenbuttoncontrol/icon.svg"
dest_files=["res://.godot/imported/icon.svg-e7770945a21c9fca528355bbf6b1708f.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@@ -0,0 +1,7 @@
[plugin]
name="TouchScreenButtonControl"
description="A Control Node version to TouchScreenButton2D"
author="Matata.exe"
version="1.0"
script="TouchScreenButtonControlPlugin.gd"

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ndaordejurrl"
path="res://.godot/imported/icon.svg-3eaf29e1973fdc580c89279657f85e37.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/virtual_joystick/icon.svg"
dest_files=["res://.godot/imported/icon.svg-3eaf29e1973fdc580c89279657f85e37.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@@ -0,0 +1,8 @@
[plugin]
name="Virtual Joystick"
description="Virtual Joystick is a lightweight and fully configurable plugin that adds a virtual joystick to the screen, ideal for mobile games or touch-based interfaces.
With it, you can control player movement or any other input action using a simple, responsive, and customizable visual stick."
author="Saulo de Souza"
version="1.0.7"
script="plugin.gd"

View File

@@ -0,0 +1,11 @@
@tool
extends EditorPlugin
var icon = preload("res://addons/virtual_joystick/icon.svg")
var script_main = preload("res://addons/virtual_joystick/virtual_joystick.gd")
func _enter_tree():
add_custom_type("VirtualJoystick", "Control", script_main, icon)
func _exit_tree():
remove_custom_type("VirtualJoystick")

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://mfjv5h7sdlhy"
path="res://.godot/imported/joystick_texture_1.png-9fe11098e467f8f7500bf2529275c515.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/virtual_joystick/resources/textures/joystick_texture_1.png"
dest_files=["res://.godot/imported/joystick_texture_1.png-9fe11098e467f8f7500bf2529275c515.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cppp7p7l040i5"
path="res://.godot/imported/joystick_texture_2.png-bd8e129c570c51a41d34619540e549b1.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/virtual_joystick/resources/textures/joystick_texture_2.png"
dest_files=["res://.godot/imported/joystick_texture_2.png-bd8e129c570c51a41d34619540e549b1.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ct6r0wagtmapd"
path="res://.godot/imported/joystick_texture_3.png-d28d8fdffe3dd01bcd800f8da8ffad5c.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/virtual_joystick/resources/textures/joystick_texture_3.png"
dest_files=["res://.godot/imported/joystick_texture_3.png-d28d8fdffe3dd01bcd800f8da8ffad5c.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://rxah3fc1lih3"
path="res://.godot/imported/joystick_texture_4.png-288403f1a78edebf82b0917d63d71545.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/virtual_joystick/resources/textures/joystick_texture_4.png"
dest_files=["res://.godot/imported/joystick_texture_4.png-288403f1a78edebf82b0917d63d71545.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://01qhightlcso"
path="res://.godot/imported/joystick_texture_5.png-b4d7bb661b1dfa9d44580770afad2948.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/virtual_joystick/resources/textures/joystick_texture_5.png"
dest_files=["res://.godot/imported/joystick_texture_5.png-b4d7bb661b1dfa9d44580770afad2948.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://don118m3unno4"
path="res://.godot/imported/joystick_texture_6.png-2b34481992ebc7f5529547a31713f9e4.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/virtual_joystick/resources/textures/joystick_texture_6.png"
dest_files=["res://.godot/imported/joystick_texture_6.png-2b34481992ebc7f5529547a31713f9e4.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dv7m8ofd7vjkg"
path="res://.godot/imported/stick_texture_1.png-b7322c6c9fa9ceca47042e9525a31e3d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/virtual_joystick/resources/textures/stick_texture_1.png"
dest_files=["res://.godot/imported/stick_texture_1.png-b7322c6c9fa9ceca47042e9525a31e3d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bra3aeybagspi"
path="res://.godot/imported/stick_texture_2.png-56a0dc5972515a4c813acb0018d59897.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/virtual_joystick/resources/textures/stick_texture_2.png"
dest_files=["res://.godot/imported/stick_texture_2.png-56a0dc5972515a4c813acb0018d59897.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b76m3oio3bpve"
path="res://.godot/imported/stick_texture_3.png-ac8c0e09219e9294012c766efb28a6dd.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/virtual_joystick/resources/textures/stick_texture_3.png"
dest_files=["res://.godot/imported/stick_texture_3.png-ac8c0e09219e9294012c766efb28a6dd.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dt4ujdvuod0ei"
path="res://.godot/imported/stick_texture_4.png-ea228bad22a241c375a4eb387cc66da7.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/virtual_joystick/resources/textures/stick_texture_4.png"
dest_files=["res://.godot/imported/stick_texture_4.png-ea228bad22a241c375a4eb387cc66da7.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dywm4x5vqdtsm"
path="res://.godot/imported/stick_texture_5.png-f76da9fbec9ae506d29c25a5b2e273b4.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/virtual_joystick/resources/textures/stick_texture_5.png"
dest_files=["res://.godot/imported/stick_texture_5.png-f76da9fbec9ae506d29c25a5b2e273b4.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://fts4nb53arsl"
path="res://.godot/imported/stick_texture_6.png-0fdb4087c1eca258d05fa6e2a535cbbe.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/virtual_joystick/resources/textures/stick_texture_6.png"
dest_files=["res://.godot/imported/stick_texture_6.png-0fdb4087c1eca258d05fa6e2a535cbbe.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@@ -0,0 +1,496 @@
@tool
@icon("res://addons/virtual_joystick/icon.svg")
class_name VirtualJoystick
extends Control
#region Signals =================================================
## Emitted when the stick is moved.
signal analogic_changed(
value: Vector2,
distance: float,
angle: float,
angle_clockwise: float,
angle_not_clockwise: float
)
## Emitted when the stick enters the dead zone.
signal deadzone_enter
## Emitted when the stick leaves the dead zone.
signal deadzone_leave
#endregion Signals ===============================================
#region Private Properties ======================================
var _joystick: VirtualJoystickCircle
var _stick: VirtualJoystickCircle
var _joystick_radius: float = 100.0
var _joystick_border_width: float = 10.0
var _joystick_start_position: Vector2 = Vector2(_joystick_radius + _joystick_border_width, _joystick_radius + _joystick_border_width)
var _stick_radius: float = 45.0
var _stick_border_width: float = -1.0
var _stick_start_position: Vector2 = _joystick_start_position
var _drag_started_inside := false
var _click_in := false
var _delta: Vector2 = Vector2.ZERO
var _in_deadzone: bool = false:
set(value):
if value != _in_deadzone:
_in_deadzone = value
if not active:
return
if _in_deadzone:
deadzone_enter.emit()
else:
deadzone_leave.emit()
var _real_size: Vector2 = size * scale
var _warnings: PackedStringArray = []
var _DEFAULT_JOYSTICK_TEXTURE = preload("res://addons/virtual_joystick/resources/textures/joystick_texture_1.png")
var _JOYSTICK_TEXTURE_2 = preload("res://addons/virtual_joystick/resources/textures/joystick_texture_2.png")
var _JOYSTICK_TEXTURE_3 = preload("res://addons/virtual_joystick/resources/textures/joystick_texture_3.png")
var _JOYSTICK_TEXTURE_4 = preload("res://addons/virtual_joystick/resources/textures/joystick_texture_4.png")
var _JOYSTICK_TEXTURE_5 = preload("res://addons/virtual_joystick/resources/textures/joystick_texture_5.png")
var _JOYSTICK_TEXTURE_6 = preload("res://addons/virtual_joystick/resources/textures/joystick_texture_6.png")
var _DEFAULT_STICK_TEXTURE = preload("res://addons/virtual_joystick/resources/textures/stick_texture_1.png")
var _STICK_TEXTURE_2 = preload("res://addons/virtual_joystick/resources/textures/stick_texture_2.png")
var _STICK_TEXTURE_3 = preload("res://addons/virtual_joystick/resources/textures/stick_texture_3.png")
var _STICK_TEXTURE_4 = preload("res://addons/virtual_joystick/resources/textures/stick_texture_4.png")
var _STICK_TEXTURE_5 = preload("res://addons/virtual_joystick/resources/textures/stick_texture_5.png")
var _STICK_TEXTURE_6 = preload("res://addons/virtual_joystick/resources/textures/stick_texture_6.png")
enum _preset_enum {
## Nothing
NONE,
## Default preset texture
PRESET_DEFAULT,
## Texture 2
PRESET_2,
## Texture 3
PRESET_3,
## Texture 4
PRESET_4,
## Texture 5
PRESET_5,
## Texture 6
PRESET_6,
}
#endregion Private Properties ====================================
#region Public Properties =======================================
## Normalized joystick direction vector (X, Y).
var value: Vector2 = Vector2.ZERO
## Distance of the stick from the joystick center (0.0 to 1.0).
var distance: float = 0.0
## Angle in degrees (universal reference, 0° = right).
var angle_degrees: float = 0.0
## Angle in degrees, measured clockwise.
var angle_degrees_clockwise: float = 0.0
## Angle in degrees, measured counter-clockwise.
var angle_degrees_not_clockwise: float = 0.0
#endregion Public Properties =====================================
#region Exports ===================================================
@export_category("Virtual Joystick")
## Enables or disables the joystick input.
@export var active: bool = true
## Deadzone threshold (0.0 = off, 1.0 = full range).
@export_range(0.0, 0.9, 0.001, "suffix:length") var deadzone: float = 0.1
## Global scale factor of the joystick.
@export_range(0.1, 2.0, 0.001, "suffix:x", "or_greater") var scale_factor: float = 1.0:
set(value):
scale_factor = value
scale = Vector2(value, value)
_update_real_size()
queue_redraw()
## If true, the Joystick will only be displayed on the screen on mobile devices.
@export var only_mobile: bool = false:
set(value):
only_mobile = value
if only_mobile == true and OS.get_name().to_lower() not in ["android", "ios"]:
visible = false
else:
visible = true
@export_category("Joystick")
## Enable the use of textures for the joystick.
@export var joystick_use_textures: bool = true:
set(value):
joystick_use_textures = value
if value and joystick_texture == null:
_set_joystick_preset(joystick_preset_texture)
_verify_can_use_border()
update_configuration_warnings()
queue_redraw()
## Select one of the available models. More models will be available soon.
@export var joystick_preset_texture: _preset_enum = _preset_enum.PRESET_5: set = _set_joystick_preset
## Select a texture for the joystick figure.
@export var joystick_texture: Texture2D = _JOYSTICK_TEXTURE_5:
set(value):
joystick_texture = value
update_configuration_warnings()
_verify_can_use_border()
queue_redraw()
## Base color of the joystick background.
@export_color_no_alpha() var joystick_color: Color = Color.WHITE:
set(value):
joystick_color = value
if _joystick:
_joystick.color = value
_joystick.opacity = joystick_opacity
queue_redraw()
## Opacity of the joystick base.
@export_range(0.0, 1.0, 0.001, "suffix:alpha") var joystick_opacity: float = 0.8:
set(value):
joystick_opacity = value
if _joystick:
_joystick.opacity = value
queue_redraw()
## Width of the joystick base border.
@export_range(1.0, 20.0, 0.01, "suffix:px", "or_greater") var joystick_border: float = 1.0:
set(value):
joystick_border = value
_joystick.width = value
_joystick_border_width = value
_joystick_start_position = Vector2(_joystick_radius + _joystick_border_width, _joystick_radius + _joystick_border_width)
_joystick.position = _joystick_start_position
_stick_start_position = Vector2(_joystick_radius + _joystick_border_width, _joystick_radius + _joystick_border_width)
_stick.position = _stick_start_position
update_configuration_warnings()
queue_redraw()
@export_category("Stick")
## Enable the use of textures for the stick.
@export var stick_use_textures: bool = true:
set(value):
stick_use_textures = value
if value and stick_texture == null:
_set_stick_preset(stick_preset_texture)
update_configuration_warnings()
queue_redraw()
## Select one of the available models. More models will be available soon.
@export var stick_preset_texture: _preset_enum = _preset_enum.PRESET_5: set = _set_stick_preset
## Select a texture for the stick figure.
@export var stick_texture: Texture2D = _STICK_TEXTURE_5:
set(value):
stick_texture = value
update_configuration_warnings()
queue_redraw()
## Stick (thumb) color.
@export_color_no_alpha() var stick_color: Color = Color.WHITE:
set(value):
stick_color = value
if _stick:
_stick.color = value
_stick.opacity = stick_opacity
queue_redraw()
## Opacity of the stick.
@export_range(0.0, 1.0, 0.001, "suffix:alpha") var stick_opacity: float = 0.8:
set(value):
stick_opacity = value
if _stick:
_stick.opacity = value
queue_redraw()
#endregion Exports =================================================
#region Engine Methods =============================================
func _init() -> void:
_joystick = VirtualJoystickCircle.new(_joystick_start_position, _joystick_radius, _joystick_border_width, false, joystick_color, joystick_opacity)
_stick = VirtualJoystickCircle.new(_stick_start_position, _stick_radius, _stick_border_width, true, stick_color, stick_opacity)
queue_redraw()
func _ready() -> void:
set_size(Vector2(_joystick_radius * 2 + _joystick_border_width * 2, _joystick_radius * 2 + _joystick_border_width * 2))
_update_real_size()
func _draw() -> void:
if joystick_use_textures and joystick_texture:
var base_size = joystick_texture.get_size()
var base_scale = (_joystick_radius * 2) / base_size.x
draw_set_transform(_joystick.position, 0, Vector2(base_scale, base_scale))
draw_texture(joystick_texture, -base_size / 2, Color(joystick_color.r, joystick_color.g, joystick_color.b, joystick_opacity))
draw_set_transform(Vector2.ZERO, 0, Vector2.ONE)
else:
_joystick.draw(self, false)
if stick_use_textures and stick_texture:
var stick_size = stick_texture.get_size()
var stick_scale = (_stick_radius * 2) / stick_size.x
draw_set_transform(_stick.position, 0, Vector2(stick_scale, stick_scale))
draw_texture(stick_texture, -stick_size / 2, Color(stick_color.r, stick_color.g, stick_color.b, stick_opacity))
draw_set_transform(Vector2.ZERO, 0, Vector2.ONE)
else:
_stick.draw(self, false)
scale = Vector2(scale_factor, scale_factor)
set_size(Vector2((_joystick_radius * 2) + (_joystick_border_width * 2), (_joystick_radius * 2) + (_joystick_border_width * 2)))
func _gui_input(event: InputEvent) -> void:
if event is InputEventScreenTouch:
if event.pressed:
distance = event.position.distance_to(_joystick.position)
_drag_started_inside = distance <= _joystick.radius + _joystick.width / 2
if _drag_started_inside:
_click_in = true
_update_stick(event.position)
else:
_click_in = false
else:
if _click_in:
_reset_values()
_update_emit_signals()
_click_in = false
_drag_started_inside = false
_stick.position = _stick_start_position
queue_redraw()
elif event is InputEventScreenDrag:
if _drag_started_inside:
_update_stick(event.position)
func _get_configuration_warnings() -> PackedStringArray:
_warnings = []
if joystick_use_textures and (joystick_texture == null):
_warnings.append("The joystick_texture properties must be set when using joystick_use_textures = true.")
if stick_use_textures and (stick_texture == null):
_warnings.append("The stick_texture properties must be set when using stick_use_textures = true.")
if joystick_use_textures and joystick_texture != null and joystick_preset_texture != _preset_enum.NONE and joystick_border > 1.0:
_warnings.append("When using a texture preset, the ideal border height would be 1.0.")
return _warnings
#endregion Engine Methods =============================================
#region Private Methods ============================================
func _update_stick(_position: Vector2) -> void:
_delta = _position - _stick_start_position
if _delta.length() > _joystick.radius:
_delta = _delta.normalized() * _joystick.radius
_stick.position = _stick_start_position + _delta
queue_redraw()
var processed = _apply_deadzone(_delta / _joystick.radius)
value = processed.value
distance = processed.distance
angle_degrees = processed.angle_degrees
angle_degrees_clockwise = processed.angle_clockwise
angle_degrees_not_clockwise = processed.angle_not_clockwise
_update_emit_signals()
func _reset_values() -> void:
_delta = Vector2.ZERO
value = Vector2.ZERO
distance = 0.0
angle_degrees = 0.0
angle_degrees_clockwise = 0.0
angle_degrees_not_clockwise = 0.0
_stick.position = _stick_start_position
var length = (_delta / _joystick.radius).length()
var dz = clamp(deadzone, 0.0, 0.99)
if length <= dz:
_in_deadzone = true
queue_redraw()
## Applies linear deadzone adjustment and calculates resulting angles.
func _apply_deadzone(input_value: Vector2) -> Dictionary:
var length = input_value.length()
var result = Vector2.ZERO
var dz = clamp(deadzone, 0.0, 0.99)
if length <= dz:
_in_deadzone = true
result = Vector2.ZERO
length = 0.0
else:
_in_deadzone = false
# Re-scale linearly between deadzone and full range
var adjusted = (length - dz) / (1.0 - dz)
result = input_value.normalized() * adjusted
length = adjusted
var angle_cw = _get_angle_delta(result * _joystick.radius, true, true)
var angle_ccw = _get_angle_delta(result * _joystick.radius, true, false)
var angle = _get_angle_delta(result * _joystick.radius, false, false)
if active:
return {
"value": result,
"distance": length,
"angle_clockwise": angle_cw,
"angle_not_clockwise": angle_ccw,
"angle_degrees": angle
}
else:
return {
"value": Vector2.ZERO,
"distance": 0.0,
"angle_clockwise": 0.0,
"angle_not_clockwise": 0.0,
"angle_degrees": 0.0
}
func _update_emit_signals() -> void:
if not active:
return
if _in_deadzone:
analogic_changed.emit(
Vector2.ZERO,
0.0,
0.0,
0.0,
0.0
)
else:
analogic_changed.emit(
value,
distance,
angle_degrees,
angle_degrees_clockwise,
angle_degrees_not_clockwise
)
func _update_real_size() -> void:
_real_size = size * scale
pivot_offset = size / 2
## Calculates the angle of a vector in degrees.
func _get_angle_delta(delta: Vector2, continuous: bool, clockwise: bool) -> float:
var angle_deg = 0.0
if continuous and not clockwise:
angle_deg = rad_to_deg(atan2(-delta.y, delta.x))
else:
angle_deg = rad_to_deg(atan2(delta.y, delta.x))
if continuous and angle_deg < 0.0:
angle_deg += 360.0
return angle_deg
func _set_joystick_preset(_value: _preset_enum) -> void:
joystick_preset_texture = _value
match (_value):
_preset_enum.PRESET_DEFAULT:
joystick_texture = _DEFAULT_JOYSTICK_TEXTURE
_preset_enum.PRESET_2:
joystick_texture = _JOYSTICK_TEXTURE_2
_preset_enum.PRESET_3:
joystick_texture = _JOYSTICK_TEXTURE_3
_preset_enum.PRESET_4:
joystick_texture = _JOYSTICK_TEXTURE_4
_preset_enum.PRESET_5:
joystick_texture = _JOYSTICK_TEXTURE_5
_preset_enum.PRESET_6:
joystick_texture = _JOYSTICK_TEXTURE_6
_preset_enum.NONE:
if joystick_texture in [_DEFAULT_JOYSTICK_TEXTURE, _JOYSTICK_TEXTURE_2, _JOYSTICK_TEXTURE_3, _JOYSTICK_TEXTURE_4, _JOYSTICK_TEXTURE_5, _JOYSTICK_TEXTURE_6]:
joystick_texture = null
_verify_can_use_border()
update_configuration_warnings()
func _set_stick_preset(_value: _preset_enum) -> void:
stick_preset_texture = _value
match (_value):
_preset_enum.PRESET_DEFAULT:
stick_texture = _DEFAULT_STICK_TEXTURE
_preset_enum.PRESET_2:
stick_texture = _STICK_TEXTURE_2
_preset_enum.PRESET_3:
stick_texture = _STICK_TEXTURE_3
_preset_enum.PRESET_4:
stick_texture = _STICK_TEXTURE_4
_preset_enum.PRESET_5:
stick_texture = _STICK_TEXTURE_5
_preset_enum.PRESET_6:
stick_texture = _STICK_TEXTURE_6
_preset_enum.NONE:
if stick_texture in [_DEFAULT_STICK_TEXTURE, _STICK_TEXTURE_2, _STICK_TEXTURE_3, _STICK_TEXTURE_4, _STICK_TEXTURE_5, _STICK_TEXTURE_6]:
stick_texture = null
func _verify_can_use_border() -> bool:
if joystick_use_textures and not joystick_texture == null:
joystick_border = 1.0
return false
return true
#endregion Private Methods ===========================================
#region Public Methods =============================================
## Returns the current joystick vector value.
func get_value() -> Vector2:
return value
## Returns the joystick distance (0 to 1).
func get_distance() -> float:
return distance
## Returns the current joystick angle (clockwise).
func get_angle_degrees_clockwise() -> float:
return angle_degrees_clockwise
## Returns the current joystick angle (counter-clockwise).
func get_angle_degrees_not_clockwise() -> float:
return angle_degrees_not_clockwise
## Returns a specific angle configuration.
func get_angle_degrees(continuous: bool = true, clockwise: bool = false) -> float:
return _get_angle_delta(_delta, continuous, clockwise)
#endregion Public Methods ============================================
#region Classes ====================================================
class VirtualJoystickCircle extends RefCounted:
var position: Vector2
var radius: float
var color: Color
var width: float
var filled: bool
var antialiased: bool
var opacity: float:
set(value):
opacity = value
self.color.a = opacity
func _init(_position: Vector2, _radius: float, _width: float = -1.0, _filled: bool = true, _color: Color = Color.WHITE, _opacity: float = 1.0, _antialiased: bool = true):
self.position = _position
self.radius = _radius
self.color = _color
self.width = _width
self.filled = _filled
self.antialiased = _antialiased
self.opacity = _opacity
self.color.a = _opacity
func draw(canvas_item: CanvasItem, offset: bool) -> void:
var pos = self.position + (Vector2(self.radius, self.radius) if offset else Vector2.ZERO)
canvas_item.draw_circle(pos, self.radius, self.color, self.filled, self.width, self.antialiased)
#endregion Classes ===================================================

View File

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

View File

@@ -69,3 +69,53 @@ Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorActi
ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue
Remove-Item -Recurse -Force '{temp_dir}'"
[preset.1]
name="Web"
platform="Web"
runnable=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="../export/www/index.html"
patches=PackedStringArray()
patch_delta_encoding=false
patch_delta_compression_level_zstd=19
patch_delta_min_reduction=0.1
patch_delta_include_filters="*"
patch_delta_exclude_filters=""
encryption_include_filters=""
encryption_exclude_filters=""
seed=0
encrypt_pck=false
encrypt_directory=false
script_export_mode=2
[preset.1.options]
custom_template/debug=""
custom_template/release=""
variant/extensions_support=false
variant/thread_support=true
vram_texture_compression/for_desktop=true
vram_texture_compression/for_mobile=false
html/export_icon=true
html/custom_html_shell=""
html/head_include=""
html/canvas_resize_policy=2
html/focus_canvas_on_start=true
html/experimental_virtual_keyboard=false
progressive_web_app/enabled=false
progressive_web_app/ensure_cross_origin_isolation_headers=true
progressive_web_app/offline_page=""
progressive_web_app/display=1
progressive_web_app/orientation=1
progressive_web_app/icon_144x144=""
progressive_web_app/icon_180x180=""
progressive_web_app/icon_512x512=""
progressive_web_app/background_color=Color(0, 0, 0, 1)
threads/emscripten_pool_size=8
threads/godot_pool_size=4

View File

@@ -32,6 +32,10 @@ window/size/viewport_height=720
window/stretch/mode="canvas_items"
window/stretch/scale_mode="integer"
[editor_plugins]
enabled=PackedStringArray("res://addons/touchscreenbuttoncontrol/plugin.cfg", "res://addons/virtual_joystick/plugin.cfg")
[input]
move_left={
@@ -74,6 +78,10 @@ attack={
]
}
[input_devices]
pointing/emulate_touch_from_mouse=true
[physics]
3d/physics_engine="Jolt Physics"

View File

@@ -12,15 +12,6 @@ layer = 200
script = ExtResource("1_chat_ui")
[node name="ChatContainer" type="Control" parent="." unique_id=-1294967296]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 1
[node name="BottomLeft" type="MarginContainer" parent="ChatContainer" unique_id=-294967296]
layout_mode = 1
anchors_preset = 2
anchor_top = 1.0
@@ -31,6 +22,16 @@ offset_right = 400.0
offset_bottom = -10.0
grow_horizontal = 0
grow_vertical = 0
mouse_filter = 1
[node name="BottomLeft" type="MarginContainer" parent="ChatContainer" unique_id=-294967296]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 1
[node name="Background" type="ColorRect" parent="ChatContainer/BottomLeft" unique_id=705032704]
visible = false
@@ -40,16 +41,21 @@ color = Color(0, 0, 0, 0.5)
[node name="VBox" type="VBoxContainer" parent="ChatContainer/BottomLeft" unique_id=1705032704]
layout_mode = 2
mouse_filter = 2
[node name="MessageScroll" type="ScrollContainer" parent="ChatContainer/BottomLeft/VBox" unique_id=-1589934592]
custom_minimum_size = Vector2(380, 150)
layout_mode = 2
size_flags_vertical = 3
mouse_filter = 1
scroll_horizontal_enabled = false
scroll_vertical_enabled = true
[node name="MessageList" type="VBoxContainer" parent="ChatContainer/BottomLeft/VBox/MessageScroll" unique_id=-589934592]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
mouse_filter = 1
[node name="ChatInput" type="LineEdit" parent="ChatContainer/BottomLeft/VBox" unique_id=1410065408]
visible = false

View File

@@ -4,7 +4,6 @@
[ext_resource type="PackedScene" uid="uid://cxfvw8y7jqn2p" path="res://scenes/player.tscn" id="2"]
[ext_resource type="Script" uid="uid://db58xcyo4cjk" path="res://scripts/game_world.gd" id="4"]
[ext_resource type="Script" uid="uid://wff5063ctp7g" path="res://scripts/debug_overlay.gd" id="5"]
[ext_resource type="Script" path="res://scripts/room_lighting_system.gd" id="6"]
[ext_resource type="AudioStream" uid="uid://dthr2w8x0cj6v" path="res://assets/audio/sfx/ambience/wind-castle-loop.wav.mp3" id="6_6c6v5"]
[ext_resource type="TileSet" uid="uid://dqem5tbvooxrg" path="res://assets/gfx/RPG DUNGEON VOL 3.tres" id="9"]
@@ -40,8 +39,5 @@ light_mask = 1048575
visibility_layer = 1048575
color = Color(0.4140625, 0.4140625, 0.4140625, 1)
[node name="RoomLightingSystem" type="Node2D" parent="." unique_id=1234567893]
script = ExtResource("6")
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="." unique_id=1141138343]
stream = ExtResource("6_6c6v5")

View File

@@ -3,7 +3,13 @@
[ext_resource type="Script" uid="uid://da5sp508nk1tx" path="res://scripts/ingame_hud.gd" id="1_hud_script"]
[ext_resource type="FontFile" uid="uid://bajcvmidrnc33" path="res://assets/fonts/standard_font.png" id="2_standard_font"]
[ext_resource type="Texture2D" uid="uid://dkisxs8ecfaul" path="res://assets/gfx/ui/hearts_filled.png" id="4_hearts_filled"]
[ext_resource type="Script" uid="uid://5hepk3l8u2eg" path="res://scripts/mobile_input.gd" id="5_44yxk"]
[ext_resource type="Script" uid="uid://dhn1uax7qtt1v" path="res://addons/virtual_joystick/virtual_joystick.gd" id="5_i0hld"]
[ext_resource type="Texture2D" uid="uid://dkpritx47nd4m" path="res://assets/gfx/pickups/items_n_shit.png" id="5_key_texture"]
[ext_resource type="Texture2D" uid="uid://01qhightlcso" path="res://addons/virtual_joystick/resources/textures/joystick_texture_5.png" id="6_yeruy"]
[ext_resource type="Texture2D" uid="uid://dywm4x5vqdtsm" path="res://addons/virtual_joystick/resources/textures/stick_texture_5.png" id="7_44yxk"]
[ext_resource type="Script" uid="uid://bh5a3ydiu51eo" path="res://addons/touchscreenbuttoncontrol/TouchScreenButtonControl.gd" id="8_cu5yl"]
[ext_resource type="StyleBox" uid="uid://cv5o175a2677e" path="res://addons/touchscreenbuttoncontrol/button_style.tres" id="8_yeruy"]
[sub_resource type="Theme" id="Theme_standard_font"]
default_font = ExtResource("2_standard_font")
@@ -15,6 +21,7 @@ region = Rect2(160, 208, 16, 16)
margin = Rect2(0, -2, 0, 0)
[node name="IngameHUD" type="CanvasLayer" unique_id=846985801]
layer = 201
script = ExtResource("1_hud_script")
[node name="UpperLeft" type="MarginContainer" parent="." unique_id=22752255]
@@ -128,3 +135,149 @@ horizontal_alignment = 1
[node name="TextureProgressBarBossHP" type="TextureProgressBar" parent="UpperRight/HBoxContainer/VBoxContainerBoss" unique_id=1266602557]
layout_mode = 2
texture_progress = ExtResource("4_hearts_filled")
[node name="MobileInput" type="Control" parent="." unique_id=1373461519]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 1
script = ExtResource("5_44yxk")
[node name="VirtualJoystick" type="Control" parent="MobileInput" unique_id=1151061008]
z_index = 4096
layout_mode = 1
anchors_preset = 4
anchor_top = 0.5
anchor_bottom = 0.5
offset_left = 48.0
offset_top = -114.0
offset_right = 250.0
offset_bottom = 88.0
grow_vertical = 2
pivot_offset = Vector2(101, 101)
script = ExtResource("5_i0hld")
joystick_texture = ExtResource("6_yeruy")
joystick_opacity = 0.235
stick_texture = ExtResource("7_44yxk")
stick_opacity = 0.746
metadata/_custom_type_script = "uid://dhn1uax7qtt1v"
[node name="Control" type="Control" parent="MobileInput" unique_id=131649841]
layout_mode = 1
anchors_preset = 6
anchor_left = 1.0
anchor_top = 0.5
anchor_right = 1.0
anchor_bottom = 0.5
offset_left = -40.0
offset_top = -20.0
offset_bottom = 20.0
grow_horizontal = 0
grow_vertical = 2
[node name="MarginContainer" type="MarginContainer" parent="MobileInput/Control" unique_id=710364056]
layout_mode = 1
anchors_preset = 6
anchor_left = 1.0
anchor_top = 0.5
anchor_right = 1.0
anchor_bottom = 0.5
offset_left = -205.765
offset_top = -94.475
offset_right = -5.7649994
offset_bottom = 25.525024
grow_horizontal = 0
grow_vertical = 2
theme_override_constants/margin_right = 42
[node name="B_ButtonContainer" type="Control" parent="MobileInput/Control/MarginContainer" unique_id=297390115]
layout_mode = 2
[node name="B_Circle" type="Panel" parent="MobileInput/Control/MarginContainer/B_ButtonContainer" unique_id=2138926309]
layout_mode = 1
anchors_preset = 4
anchor_top = 0.5
anchor_bottom = 0.5
offset_top = -32.0
offset_right = 64.0
offset_bottom = 32.0
grow_vertical = 2
theme_override_styles/panel = ExtResource("8_yeruy")
[node name="B_Label" type="Label" parent="MobileInput/Control/MarginContainer/B_ButtonContainer/B_Circle" unique_id=1440094044]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
text = "B"
horizontal_alignment = 1
vertical_alignment = 1
[node name="TouchScreenButtonControl" type="TextureButton" parent="MobileInput/Control/MarginContainer/B_ButtonContainer/B_Circle" unique_id=1583063757]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
focus_mode = 0
mouse_filter = 2
action_mode = 0
ignore_texture_size = true
stretch_mode = 5
script = ExtResource("8_cu5yl")
touchscreen_only = true
input_action = "attack"
metadata/_custom_type_script = "uid://bh5a3ydiu51eo"
[node name="A_ButtonContainer" type="Control" parent="MobileInput/Control/MarginContainer" unique_id=1039434657]
layout_mode = 2
[node name="A_Circle" type="Panel" parent="MobileInput/Control/MarginContainer/A_ButtonContainer" unique_id=1415076009]
layout_mode = 1
anchors_preset = 6
anchor_left = 1.0
anchor_top = 0.5
anchor_right = 1.0
anchor_bottom = 0.5
offset_left = -64.0
offset_top = -32.0
offset_bottom = 32.0
grow_horizontal = 0
grow_vertical = 2
theme_override_styles/panel = ExtResource("8_yeruy")
[node name="A_Label" type="Label" parent="MobileInput/Control/MarginContainer/A_ButtonContainer/A_Circle" unique_id=619215455]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
text = "A"
horizontal_alignment = 1
vertical_alignment = 1
[node name="TouchScreenButtonControl" type="TextureButton" parent="MobileInput/Control/MarginContainer/A_ButtonContainer/A_Circle" unique_id=322194330]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
focus_mode = 0
mouse_filter = 2
action_mode = 0
ignore_texture_size = true
stretch_mode = 5
script = ExtResource("8_cu5yl")
touchscreen_only = true
input_action = "grab"
metadata/_custom_type_script = "uid://bh5a3ydiu51eo"
[connection signal="analogic_changed" from="MobileInput/VirtualJoystick" to="MobileInput" method="_on_virtual_joystick_analogic_changed"]

20
src/scenes/test.tscn Normal file
View File

@@ -0,0 +1,20 @@
[gd_scene format=3 uid="uid://o8cbi1whsbo0"]
[ext_resource type="Script" uid="uid://dhn1uax7qtt1v" path="res://addons/virtual_joystick/virtual_joystick.gd" id="1_iyx0m"]
[ext_resource type="Texture2D" uid="uid://01qhightlcso" path="res://addons/virtual_joystick/resources/textures/joystick_texture_5.png" id="2_74lek"]
[ext_resource type="Texture2D" uid="uid://dywm4x5vqdtsm" path="res://addons/virtual_joystick/resources/textures/stick_texture_5.png" id="3_j5jx5"]
[node name="Test" type="Node2D" unique_id=459289533]
[node name="VirtualJoystick" type="Control" parent="." unique_id=322625393]
layout_mode = 3
anchors_preset = 0
offset_left = 391.0
offset_top = 172.0
offset_right = 611.0
offset_bottom = 392.0
pivot_offset = Vector2(110, 110)
script = ExtResource("1_iyx0m")
joystick_texture = ExtResource("2_74lek")
stick_texture = ExtResource("3_j5jx5")
metadata/_custom_type_script = "uid://dhn1uax7qtt1v"

View File

@@ -57,7 +57,7 @@ func _ready():
visible = true # Chat UI is always visible (background and messages fade)
# Hide scrollbar by default (will show when chat is opened)
# Hide scrollbar permanently
if message_scroll:
var scroll_bar = message_scroll.get_v_scroll_bar()
if scroll_bar:
@@ -71,6 +71,23 @@ func _input(event):
else:
_send_and_close_chat()
get_viewport().set_input_as_handled()
# Don't consume touch events outside chat area - let them pass through to joystick
# Only consume keyboard events for chat
if event is InputEventScreenTouch or event is InputEventScreenDrag:
# Check if touch is in chat area
if chat_container:
var bottom_left = chat_container.get_node_or_null("BottomLeft")
if bottom_left:
var chat_rect = bottom_left.get_global_rect()
if event is InputEventScreenTouch:
if not chat_rect.has_point(event.position):
# Touch is outside chat area, don't consume it
return
elif event is InputEventScreenDrag:
if not chat_rect.has_point(event.position):
# Drag is outside chat area, don't consume it
return
func _open_chat():
chat_open = true
@@ -79,11 +96,15 @@ func _open_chat():
chat_input.grab_focus()
background.visible = true
# Show scrollbar when chat is open
# Enable scrolling when chat is open
if message_scroll:
message_scroll.mouse_filter = Control.MOUSE_FILTER_STOP # Allow scrolling
# Keep scrollbar hidden
var scroll_bar = message_scroll.get_v_scroll_bar()
if scroll_bar:
scroll_bar.visible = true
scroll_bar.visible = false
if message_list:
message_list.mouse_filter = Control.MOUSE_FILTER_STOP # Allow interaction
# Make all messages fully visible when chat is opened
_show_all_messages()
@@ -101,11 +122,15 @@ func _send_and_close_chat():
chat_input.visible = false
chat_input.release_focus()
# Hide scrollbar when chat is closed
# Disable scrolling when chat is closed (so it doesn't block joystick)
if message_scroll:
message_scroll.mouse_filter = Control.MOUSE_FILTER_IGNORE # Don't block input
# Keep scrollbar hidden
var scroll_bar = message_scroll.get_v_scroll_bar()
if scroll_bar:
scroll_bar.visible = false
if message_list:
message_list.mouse_filter = Control.MOUSE_FILTER_IGNORE # Don't block input
# Unlock player controls
_lock_player_controls(false)

View File

@@ -688,11 +688,6 @@ func _generate_dungeon():
# Restore players (make visible and restore collision)
_restore_all_players()
# Reinitialize room lighting system for new level
var room_lighting = get_node_or_null("RoomLightingSystem")
if room_lighting and room_lighting.has_method("reinitialize"):
room_lighting.reinitialize()
# Update camera immediately to ensure it's looking at the players
await get_tree().process_frame # Wait a frame for players to be fully in scene tree
_update_camera()
@@ -1141,11 +1136,6 @@ func _sync_dungeon(dungeon_data_sync: Dictionary, seed_value: int, level: int, h
# Spawn room triggers on client
_spawn_room_triggers()
# Reinitialize room lighting system for new level (client)
var room_lighting = get_node_or_null("RoomLightingSystem")
if room_lighting and room_lighting.has_method("reinitialize"):
room_lighting.reinitialize()
# Wait a frame to ensure all enemies and objects are properly added to scene tree and initialized
await get_tree().process_frame
await get_tree().process_frame # Wait an extra frame to ensure enemies are fully ready

View File

@@ -1,161 +0,0 @@
extends CharacterBody2D
var friction = 8.0 # Lower values make the slowdown more gradual
var is_collected = false
var bounceTimer = 0.0
var timeBeforePickup = 0.8
@onready var damage_number_scene = preload("res://assets/scripts/components/damage_number.tscn")
# Z-axis variables
var positionZ = 4.0 # Start slightly in the air
var velocityZ = 10.0 # Initial upward velocity
var accelerationZ = -300.0 # Gravity
var bounceRestitution = 0.6 # How much bounce energy is retained (0-1)
var minBounceVelocity = 40.0 # Minimum velocity needed to bounce
var bodyToPickUp:Node2D = null
var sync_position := Vector2()
var sync_velocity := Vector2()
var sync_positionZ: float = 4.0
var sync_velocityZ: float = 10.0
func _ready() -> void:
add_to_group("coins")
$Area2DCollision.set_deferred("monitoring", false)
update_sprite_scale()
# Start animation
$AnimationPlayer.play("idle")
func _process(delta: float) -> void:
if bodyToPickUp != null and !is_collected and timeBeforePickup == 0 and positionZ < 5:
visible = false
$SfxCoinCollect.play()
is_collected = true
$Area2DCollision.set_deferred("monitoring", false)
var damage_number = damage_number_scene.instantiate() as Label
if damage_number:
get_tree().current_scene.add_child(damage_number)
damage_number.global_position = global_position + Vector2(0, -16)
if "direction" in damage_number:
damage_number.direction = Vector2(0, -1)
damage_number.move_duration = 1.0
if "label" in damage_number:
damage_number.label = "+1 COIN"
if "color" in damage_number:
damage_number.color = Color.YELLOW
if "stats" in bodyToPickUp:
bodyToPickUp.stats.add_coin(1)
await $SfxCoinCollect.finished
call_deferred("queue_free")
return
if is_collected:
return
if timeBeforePickup > 0.0:
timeBeforePickup -= delta
if timeBeforePickup < 0:
$Area2DCollision.set_deferred("monitoring", true)
timeBeforePickup = 0
if bounceTimer > 0.0:
bounceTimer -= delta
if bounceTimer < 0:
bounceTimer = 0
# Update vertical movement
velocityZ += accelerationZ * delta
positionZ += velocityZ * delta
# Ground collision and bounce
if positionZ <= 0:
velocity = velocity.lerp(Vector2.ZERO, 1.0 - exp(-friction * delta)) # only slow down if on floor
positionZ = 0
if abs(velocityZ) > minBounceVelocity:
#print(velocityZ)
$SfxCoinBounce.volume_db = -1 + (-10 - (velocityZ * 0.1))
$SfxCoinBounce.play()
velocityZ = -velocityZ * bounceRestitution
else:
velocityZ = 0
update_sprite_scale()
move_and_slide()
'
func _physics_process(delta: float) -> void:
if multiplayer.is_server():
for peer_id in multiplayer.get_peers():
sync_coin.rpc_id(peer_id, position, velocity, positionZ, velocityZ)
if !multiplayer.is_server():
position = position.lerp(sync_position, delta * 15.0)
velocity = velocity.lerp(sync_velocity, delta * 15.0)
positionZ = sync_positionZ
velocityZ = sync_velocityZ
if positionZ <= 0:
velocity = velocity.lerp(Vector2.ZERO, 1.0 - exp(-friction * delta)) # only slow down if on floor
positionZ = 0
if abs(velocityZ) > minBounceVelocity:
#print(velocityZ)
$SfxCoinBounce.volume_db = -1 + (-10 - (velocityZ * 0.1))
$SfxCoinBounce.play()
update_sprite_scale()
pass
'
@rpc("unreliable")
func sync_coin(pos: Vector2, vel: Vector2, posZ: float, velZ: float):
sync_position = pos
sync_velocity = vel
sync_positionZ = posZ
sync_velocityZ = velZ
pass
func update_sprite_scale() -> void:
# Calculate scale based on height
# Maximum height will have scale 1.3, ground will have scale 1.0
var height_factor = positionZ / 50.0 # Assuming 20 is max height
var posY = 0.0 + (2 * positionZ)
var sc = 1.0 + (0.8 * height_factor)
$Sprite2D.scale = Vector2(sc, sc)
$Sprite2D.position.y = -posY
func _on_area_2d_collision_body_entered(_body: Node2D) -> void:
if bounceTimer == 0:
$SfxCoinBounce.play()
bounceTimer = 0.08
# inverse the direction and slow down slightly
var collision_shape = $Area2DCollision.get_overlapping_bodies()
if collision_shape.size() > 0:
var collider = collision_shape[0]
var normal = (global_position - collider.global_position).normalized()
velocity = velocity.bounce(normal)
pass # Replace with function body.
@rpc("any_peer", "reliable")
func pick_up(_char: CharacterBody2D):
# does nothing... handled by coin itself!
return false
func _on_area_2d_pickup_body_entered(body: Node2D) -> void:
if !is_collected:
bodyToPickUp = body.get_parent()
pass # Replace with function body.
func _on_area_2d_pickup_body_exited(_body: Node2D) -> void:
bodyToPickUp = null
pass # Replace with function body.
func _on_area_2d_pickup_area_entered(area: Area2D) -> void:
if !is_collected:
bodyToPickUp = area.get_parent()
pass # Replace with function body.
func _on_area_2d_pickup_area_exited(_area: Area2D) -> void:
bodyToPickUp = null
pass # Replace with function body.

View File

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

View File

@@ -1,617 +0,0 @@
extends RefCounted # Using RefCounted instead of Node since this is a utility class
enum DUNGEON_ENTITY_TYPES {
ENEMY,
OBJECT,
TRAP
}
# Constants
const DOOR_MODIFIERS = [
{"name": "Locked Door", "type": "Locked"},
{"name": "Bomb Wall", "type": "Bombable"}
]
const FLOOR_TILES = [
7,8,9,10,11,12,
25,26,27,28,29,30,31,
44,45,46,47,48,49,50,
63,64,65,66,67,68,69
]
const WALL_VARIATIONS = [
0.45,
0.15,
0.15,
0.15,
0.1
]
const OBJECT_TYPES = [
{"name": "Barrel", "ti": [70], "ti2": [89], "openable": false, "liftable": true, "throwable": false, "hp": - 1, "pushable": true, "size": {"x": 1, "y": 1}},
{"name": "Pot", "ti": [13, 14, 15], "ti2": [51, 52, 53], "openable": false, "liftable": true, "throwable": true, "hp": 1, "pushable": true, "size": {"x": 1, "y": 1}},
{"name": "Chest", "ti": [108], "ti2": [127], "openable": true, "liftable": false, "throwable": false, "hp": - 1, "pushable": false, "size": {"x": 1, "y": 1}},
{"name": "Bench", "ti": [35, 36], "ti2": [16, 17], "openable": false, "liftable": false, "throwable": false, "hp": - 1, "pushable": false, "size": {"x": 2, "y": 1}}
]
const MONSTER_TYPES = [
{
"name": "Goblin",
},
{
"name": "Slime",
},
# ... other monster types similar to JS version
]
const TRAP_TYPES = [
{"name": "Spike Trap", "description": "Spikes shoot up from the floor when triggered."},
{"name": "Arrow Trap", "description": "Arrows fire from the walls when a player steps on a pressure plate."},
# ... other trap types
]
const ROOM_MODIFIERS = [
{"name": "Player Start", "description": "The players start here.", "type": "START", "negative_modifiers": {"min": 0, "max": 0}},
{"name": "Exit", "description": "Room contains an exit.", "type": "EXIT", "negative_modifiers": {"min": 0, "max": 0}},
# ... other room modifiers
]
# Main generation function
func generate_dungeon(map_size: Vector2, _num_rooms: int, min_room_size: int, max_room_size: int) -> Dictionary:
# Initialize grid
var grid = []
var randgrid = []
for x in range(map_size.x):
grid.append([])
randgrid.append([])
for y in range(map_size.y):
grid[x].append(0)
randgrid[x].append(0)
var all_rooms = []
var all_doors = []
# 1. Create first room at a random position
var first_w = rand_range_i(min_room_size, max_room_size)
var first_h = rand_range_i(min_room_size, max_room_size)
var first_room = {
"x": rand_range_i(4, map_size.x - first_w - 4), # Random position with buffer
"y": rand_range_i(4, map_size.y - first_h - 4),
"w": first_w,
"h": first_h,
"modifiers": []
}
set_floor(first_room, grid, map_size)
all_rooms.append(first_room)
var nrOfDoorErrors = 0
var nrOfRoomErrors = 0
# 2. Try to place rooms until we can't fit any more
var attempts = 1000 # Prevent infinite loops
while attempts > 0 and all_rooms.size() > 0:
# Pick a random existing room
var source_room = all_rooms[randi() % all_rooms.size()]
# Try to place a new room near it
var new_room = try_place_room_near(source_room, grid, map_size, min_room_size, max_room_size)
if new_room.w > 0: # Valid room created
set_floor(new_room, grid, map_size)
all_rooms.append(new_room)
attempts -= 1
if attempts <= 0:
nrOfRoomErrors += 1
break
# 3. Connect rooms with corridors/doors
if all_rooms.size() > 1:
var connected_rooms = {}
for room in all_rooms:
connected_rooms[room] = []
# First pass: try to connect each room to its closest neighbors
for room in all_rooms:
var closest_rooms = find_closest_rooms(room, all_rooms)
#print("Connecting room at ", room.x, ",", room.y)
var connection_attempts = 0
var max_connection_attempts = 3 # Try to connect to multiple neighbors
for target_room in closest_rooms:
if connection_attempts >= max_connection_attempts:
break
if not rooms_are_connected(room, target_room, all_doors):
var door = create_corridor_between_rooms(room, target_room, grid)
if door.size() > 0:
#print("Created direct connection between rooms")
set_door(door, grid)
all_doors.append(door)
connected_rooms[room].append(target_room)
connected_rooms[target_room].append(room)
connection_attempts += 1
# Second pass: ensure all rooms are connected
var attempts2 = 100
while attempts2 > 0:
var reachable = find_reachable_rooms(all_rooms[0], all_rooms, all_doors)
#print("Reachable rooms: ", reachable.size(), "/", all_rooms.size())
if reachable.size() == all_rooms.size():
#print("All rooms connected!")
break
# Find an unreachable room and try to connect it
for room in all_rooms:
if not reachable.has(room):
var connected = false
# Try to connect to each reachable room until success
for target_room in reachable:
var door = create_corridor_between_rooms(room, target_room, grid)
if door.size() > 0:
set_door(door, grid)
all_doors.append(door)
connected = true
break
if not connected:
# Try creating intermediate room with multiple positions
for offset_x in [-2, 0, 2]:
for offset_y in [-2, 0, 2]:
var mid_room = create_intermediate_room(room, reachable[0], offset_x, offset_y)
if is_valid_room_position(mid_room, grid, map_size):
set_floor(mid_room, grid, map_size)
all_rooms.append(mid_room)
var door1 = create_corridor_between_rooms(room, mid_room, grid)
var door2 = create_corridor_between_rooms(mid_room, reachable[0], grid)
if door1.size() > 0 and door2.size() > 0:
set_door(door1, grid)
set_door(door2, grid)
all_doors.append(door1)
all_doors.append(door2)
connected = true
break
if connected:
break
if connected:
break
attempts2 -= 1
if attempts2 <= 0:
nrOfDoorErrors += 1
break
for x in range(map_size.x):
for y in range(map_size.y):
if grid[x][y] == 0: # wall
var rand = randf()
var sum:float = 0.0
for i in WALL_VARIATIONS.size():
sum += WALL_VARIATIONS[i];
if rand <= sum:
randgrid[x][y] = i
break
elif grid[x][y] == 1: # floor
if randf() < 0.6:
randgrid[x][y] = 0
else:
randgrid[x][y] = randi_range(1,FLOOR_TILES.size()-1)
elif grid[x][y] == 2: # door
randgrid[x][y] = 0 # we dont care about these... only have 1 variant
var startRoomIndex = randi_range(0,all_rooms.size()-1)
all_rooms[startRoomIndex].modifiers.push_back(ROOM_MODIFIERS[0])
var farthestRoom = null
var maxDistance = 0
var exitRoomIndex = -1
var roomIndex = 0
for r in all_rooms:
var distance = abs(r.x - all_rooms[startRoomIndex].x) + abs(r.y - all_rooms[startRoomIndex].y)
if (distance > maxDistance):
maxDistance = distance
farthestRoom = r
exitRoomIndex = roomIndex
roomIndex+=1
pass
farthestRoom.modifiers.push_back(ROOM_MODIFIERS[1])
var entities = []
var TILE_SIZE = 16
roomIndex = 0
#populate rooms and decide modifiers for rooms
for r in all_rooms:
if roomIndex != startRoomIndex and roomIndex != exitRoomIndex:
var validRoomLocations = []
var min_x = (r.x + 1)
var max_x = ((r.x + r.w) - 1)
var min_y = (r.y + 1)
var max_y = ((r.y + r.h) - 1)
for rw in range(min_x,max_x):
for rh in range(min_y, max_y):
validRoomLocations.push_back(Vector2(rw*TILE_SIZE - 8, rh*TILE_SIZE - 8)) # we assume entities are 16x16 are centered
# bigger rooms can have a larger content number!
var randNrOfEntities = randi_range(0, 4)
for entI in randNrOfEntities:
var enttype:DUNGEON_ENTITY_TYPES = randi_range(0, DUNGEON_ENTITY_TYPES.size()-1) as DUNGEON_ENTITY_TYPES
var entStats = {}
# hand code to only be enemies atm
if enttype == DUNGEON_ENTITY_TYPES.TRAP:
enttype = DUNGEON_ENTITY_TYPES.OBJECT
#enttype = DUNGEON_ENTITY_TYPES.OBJECT ## only objects now...
var subtype = "goblin"
if enttype == DUNGEON_ENTITY_TYPES.ENEMY:
var randType = randi_range(0, 1)
var cStats = CharacterStats.new()
if randType == 1:
cStats.hp = 2
subtype = "slime"
else:
cStats.hp = 3
cStats.skin = "res://assets/gfx/Puny-Characters/Layer 0 - Skins/Orc1.png"
cStats.skin = "res://assets/gfx/Puny-Characters/Layer 0 - Skins/Orc2.png"
var hair = 0
if randf() > 0.6:
hair = randi_range(1,13)
cStats.setHair(hair, randi_range(0,8))
var facialhair = 0
if randf() > 0.75: # very uncommon for facial hair on goblins
facialhair = randi_range(1,3)
cStats.setFacialHair(facialhair, randi_range(0, 4))
#cStats.add_on = "res://assets/gfx/Puny-Characters/Layer 7 - Add-ons/Orc Add-ons/GoblinEars1.png"
cStats.add_on = "res://assets/gfx/Puny-Characters/Layer 7 - Add-ons/Orc Add-ons/GoblinEars2.png"
#cStats.add_on = "res://assets/gfx/Puny-Characters/Layer 7 - Add-ons/Orc Add-ons/OrcJaw1.png"
#cStats.add_on = "res://assets/gfx/Puny-Characters/Layer 7 - Add-ons/Orc Add-ons/OrcJaw2.png"
# randomize if the goblin will have a weapon like dagger or sword
# randomize if the goblin will have bow and arrows also
# randomize if the goblin will have an armour and helmet etc.
entStats = cStats.save()
elif enttype == DUNGEON_ENTITY_TYPES.OBJECT:
subtype = "pot"
else:
subtype = "spike"
var posI = randi_range(0, validRoomLocations.size()-1)
var entity = {
"type": enttype,
"subtype": subtype,
"stats": entStats,
"position": {
"x": validRoomLocations[posI].x,
"y": validRoomLocations[posI].y
}
}
entities.push_back(entity)
validRoomLocations.remove_at(posI) # this is now occupied... don't allow anything else spawn on it.
# fill up modifiers per room
if ROOM_MODIFIERS.size() > 2:
r.modifiers.push_back(ROOM_MODIFIERS[randi_range(2, ROOM_MODIFIERS.size()-2)])
pass
roomIndex += 1
return {
"rooms": all_rooms,
"entities": entities,
"doors": all_doors,
"grid": grid,
"randgrid": randgrid, # grid containing actual tile index-ish(ish)
"mapSize": map_size,
"nrOfDoorErrors": nrOfDoorErrors,
"nrOfRoomErrors": nrOfRoomErrors
}
# Helper functions
func create_random_room(map_size: Vector2, min_size: int, max_size: int) -> Dictionary:
var x = randi() % (int(map_size.x) - max_size - 2) + 1
var y = randi() % (int(map_size.y) - max_size - 2) + 1
var w = rand_range_i(min_size, max_size)
var h = rand_range_i(min_size, max_size)
return {"x": x, "y": y, "w": w, "h": h, "modifiers": []}
func rand_range_i(min_val: int, max_val: int) -> int:
return min_val + (randi() % (max_val - min_val + 1))
func set_floor(room: Dictionary, grid: Array, map_size: Vector2) -> void:
for x in range(room.x, room.x + room.w):
for y in range(room.y, room.y + room.h):
if x >= 0 and x < map_size.x and y >= 0 and y < map_size.y:
grid[x][y] = 1 # Set as floor tile
# ... Additional helper functions and implementation details would follow ...
# ... previous code ...
func try_place_room_near(source_room: Dictionary, grid: Array, map_size: Vector2,
min_room_size: int, max_room_size: int) -> Dictionary:
var attempts = 20
while attempts > 0:
var w = rand_range_i(min_room_size, max_room_size)
var h = rand_range_i(min_room_size, max_room_size)
# Try all four sides of the source room
var sides = ["N", "S", "E", "W"]
sides.shuffle()
for side in sides:
var x = source_room.x
var y = source_room.y
match side:
"N":
x = source_room.x + (randi() % max(1, source_room.w - w))
y = source_room.y - h - 4 # 4 tiles away
"S":
x = source_room.x + (randi() % max(1, source_room.w - w))
y = source_room.y + source_room.h + 4
"W":
x = source_room.x - w - 4
y = source_room.y + (randi() % max(1, source_room.h - h))
"E":
x = source_room.x + source_room.w + 4
y = source_room.y + (randi() % max(1, source_room.h - h))
if is_valid_room_position({"x": x, "y": y, "w": w, "h": h}, grid, map_size):
return {"x": x, "y": y, "w": w, "h": h, "modifiers": []}
attempts -= 1
return {"x": 0, "y": 0, "w": 0, "h": 0, "modifiers": []}
func find_closest_rooms(room: Dictionary, all_rooms: Array) -> Array:
if all_rooms.size() <= 1:
return []
var distances = []
for other in all_rooms:
if other == room:
continue
var dist = abs(room.x - other.x) + abs(room.y - other.y)
distances.append({"room": other, "distance": dist})
# Sort by distance
if distances.size() > 0:
distances.sort_custom(func(a, b): return a.distance < b.distance)
# Return the rooms only, in order of distance
return distances.map(func(item): return item.room)
return []
func rooms_are_connected(room1: Dictionary, room2: Dictionary, doors: Array) -> bool:
for door in doors:
if (door.room1 == room1 and door.room2 == room2) or \
(door.room1 == room2 and door.room2 == room1):
return true
return false
func create_corridor_between_rooms(room1: Dictionary, room2: Dictionary, _grid: Array) -> Dictionary:
# Determine if rooms are more horizontal or vertical from each other
var dx = abs(room2.x - room1.x)
var dy = abs(room2.y - room1.y)
# Check if rooms are too far apart (more than 8 tiles)
if dx > 8 and dy > 8:
return {}
if dx > dy:
# Horizontal corridor
var leftRoom = room1 if room1.x < room2.x else room2
var rightRoom = room2 if room1.x < room2.x else room1
# Check if rooms are horizontally adjacent (gap should be reasonable)
if rightRoom.x - (leftRoom.x + leftRoom.w) > 8:
return {}
# Door must start at the right edge of left room plus 1 tile gap
var door_x = leftRoom.x + leftRoom.w
# Door y must be within both rooms' height ranges, accounting for walls
var min_y = max(leftRoom.y + 1, rightRoom.y + 1) # +1 to account for walls
var max_y = min(leftRoom.y + leftRoom.h - 2, rightRoom.y + rightRoom.h - 2) # -2 to ensure both tiles fit
# Make sure we have a valid range
if max_y < min_y:
return {}
# Pick a valid y position within the range
var door_y = min_y + (randi() % max(1, max_y - min_y + 1))
# Calculate actual width needed (distance between rooms)
var door_width = rightRoom.x - (leftRoom.x + leftRoom.w + 1)
# Use the larger of minimum width (4) or actual distance
door_width = max(4, door_width + 1)
# Create door with calculated width
var door = {
"x": door_x,
"y": door_y,
"w": door_width, # Use calculated width
"h": 2, # Fixed height for horizontal doors
"dir": "E" if leftRoom == room1 else "W",
"room1": room1,
"room2": room2
}
return door
else:
# Vertical corridor
var topRoom = room1 if room1.y < room2.y else room2
var bottomRoom = room2 if room1.y < room2.y else room1
# Check if rooms are vertically adjacent (gap should be reasonable)
if bottomRoom.y - (topRoom.y + topRoom.h) > 8:
return {}
# Door must start at the bottom edge of top room plus 1 tile gap
var door_y = topRoom.y + topRoom.h
# Door x must be within both rooms' width ranges, accounting for walls
var min_x = max(topRoom.x + 1, bottomRoom.x + 1) # +1 to account for walls
var max_x = min(topRoom.x + topRoom.w - 2, bottomRoom.x + bottomRoom.w - 2) # -2 to ensure both tiles fit
# Make sure we have a valid range
if max_x < min_x:
return {}
# Pick a valid x position within the range
var door_x = min_x + (randi() % max(1, max_x - min_x + 1))
# Calculate actual height needed (distance between rooms)
var door_height = bottomRoom.y - (topRoom.y + topRoom.h + 1)
# Use the larger of minimum height (4) or actual distance
door_height = max(4, door_height + 1)
# Create door with calculated height
var door = {
"x": door_x,
"y": door_y,
"w": 2, # Fixed width for vertical doors
"h": door_height, # Use calculated height
"dir": "S" if topRoom == room1 else "N",
"room1": room1,
"room2": room2
}
return door
func add_room_modifiers(rooms: Array) -> void:
# Add start room modifier to first room
rooms[0].modifiers.append(ROOM_MODIFIERS[0]) # START modifier
# Add exit to last room
rooms[-1].modifiers.append(ROOM_MODIFIERS[1]) # EXIT modifier
# Add random modifiers to other rooms
for i in range(1, rooms.size() - 1):
if randf() < 0.3: # 30% chance for a modifier
var available_modifiers = ROOM_MODIFIERS.slice(2, ROOM_MODIFIERS.size())
# Only add modifier if there are available ones
if available_modifiers.size() > 0:
rooms[i].modifiers.append(available_modifiers[randi() % available_modifiers.size()])
func generate_all_room_objects(rooms: Array, doors: Array) -> Array:
var room_objects = []
# Generate objects for each room
for room in rooms:
var objects = generate_room_objects(room)
room_objects.append_array(objects)
# Add door modifiers
for door in doors:
if randf() < 0.2: # 20% chance for door modifier
var modifier = DOOR_MODIFIERS[randi() % DOOR_MODIFIERS.size()]
room_objects.append({
"type": "Door",
"x": door.x,
"y": door.y,
"modifier": modifier
})
return room_objects
func generate_room_objects(room: Dictionary) -> Array:
var objects = []
var max_objects = int((room.w * room.h) / 16) # Roughly one object per 16 tiles
for _i in range(max_objects):
if randf() < 0.7: # 70% chance to place each potential object
var obj_type = OBJECT_TYPES[randi() % OBJECT_TYPES.size()]
var x = rand_range_i(room.x + 1, room.x + room.w - obj_type.size.x - 1)
var y = rand_range_i(room.y + 1, room.y + room.h - obj_type.size.y - 1)
# Check if position is free
var can_place = true
for obj in objects:
if abs(obj.x - x) < 2 and abs(obj.y - y) < 2:
can_place = false
break
if can_place:
objects.append({
"type": obj_type.name,
"x": x,
"y": y,
"properties": obj_type
})
return objects
func set_door(door: Dictionary, grid: Array) -> void:
match door.dir:
"N", "S":
if door.h > 4:
# Set 2x4 corridor
for dx in range(2):
for dy in range(door.h):
#if grid[door.x + dx][door.y + dy] != 1: # Don't overwrite room
grid[door.x + dx][door.y + dy] = 2
"E", "W":
if door.w > 4:
# Set 4x2 corridor
for dx in range(door.w):
for dy in range(2):
#if grid[door.x + dx][door.y + dy] != 1: # Don't overwrite room
grid[door.x + dx][door.y + dy] = 2
func is_valid_room_position(room: Dictionary, grid: Array, map_size: Vector2) -> bool:
# Check if room is within map bounds with buffer
if room.x < 4 or room.y < 4 or room.x + room.w >= map_size.x - 4 or room.y + room.h >= map_size.y - 4:
#print("Room outside map bounds")
return false
# Check if room overlaps with existing rooms or corridors
# Check the actual room area plus 4-tile buffer for spacing
for x in range(room.x - 4, room.x + room.w + 4):
for y in range(room.y - 4, room.y + room.h + 4):
if x >= 0 and x < map_size.x and y >= 0 and y < map_size.y:
if grid[x][y] != 0: # If tile is not empty
#print("Room overlaps at ", Vector2(x, y))
return false
return true
# Add this helper function to check room connectivity
func find_reachable_rooms(start_room: Dictionary, _all_rooms: Array, all_doors: Array) -> Array:
var reachable = [start_room]
var queue = [start_room]
while queue.size() > 0:
var current = queue.pop_front()
for door in all_doors:
var next_room = null
if door.room1 == current:
next_room = door.room2
elif door.room2 == current:
next_room = door.room1
if next_room != null and not reachable.has(next_room):
reachable.append(next_room)
queue.append(next_room)
return reachable
func create_intermediate_room(room1: Dictionary, room2: Dictionary, offset_x: int, offset_y: int) -> Dictionary:
return {
"x": room1.x + (room2.x - room1.x) / 2 + offset_x,
"y": room1.y + (room2.y - room1.y) / 2 + offset_y,
"w": 6,
"h": 6,
"modifiers": []
}

View File

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

View File

@@ -1,491 +0,0 @@
extends CanvasLayer
var is_showing_inventory = true
var finished_tween = true
var selectedItem:Item = null
var selectedEquipment:Item = null
var lastPressedItem:Item = null
var lastPressedType = "Item"
var timerSelect:float = 0.0
func bindInventory():
if GameManager.character_data.is_connected("character_changed", _charChanged):
GameManager.character_data.disconnect("character_changed", _charChanged)
GameManager.character_data.connect("character_changed", _charChanged)
pass
func _ready() -> void:
is_showing_inventory = false
var move_range = -119
$ControlContainer/ControlStats.position.x += move_range
move_range = 80
$ControlContainer/ControlInventory.position.x += move_range
move_range = 33
$ControlContainer/ControlInfo.position.y += move_range
$ControlContainer.mouse_filter = Control.MOUSE_FILTER_IGNORE
# Set up multiplayer peer
'
GameManager.host(21212, false)
GameManager.character_data.connect("character_changed", _charChanged)
#$Player.position = Vector2(30, 30)
var item = Item.new()
item.item_type = Item.ItemType.Equippable
item.equipment_type = Item.EquipmentType.ARMOUR
item.item_name = "Leather Armour"
item.description = "A nice leather armour"
item.spriteFrame = 12
item.modifiers["def"] = 2
item.equipmentPath = "res://assets/gfx/Puny-Characters/Layer 2 - Clothes/Tunic Body/BrownTunic.png"
GameManager.character_data.add_item(item)
var item2 = Item.new()
item2.item_type = Item.ItemType.Equippable
item2.equipment_type = Item.EquipmentType.HEADGEAR
item2.item_name = "Leather helm"
item2.description = "A nice leather helm"
item2.spriteFrame = 31
item2.modifiers["def"] = 1
item2.equipmentPath = "res://assets/gfx/Puny-Characters/Layer 6 - Headgears/Basic Mage/MageHatRed.png"
item2.colorReplacements = [
{ "original": Color(255/255.0, 39/255.0, 44/255.0), "replace": Color(255/255.0,106/255.0,39/255.0)},
{ "original": Color(182/255.0, 0, 0), "replace": Color(182/255.0,106/255.0,0)},
{ "original": Color(118/255.0, 1/255.0, 0), "replace": Color(118/255.0,66/255.0,0)},
{ "original": Color(72/255.0, 0, 12/255.0), "replace": Color(72/255.0,34/255.0,0)}
]
GameManager.character_data.add_item(item2)
var item3 = Item.new()
item3.item_type = Item.ItemType.Equippable
item3.equipment_type = Item.EquipmentType.MAINHAND
item3.weapon_type = Item.WeaponType.SWORD
item3.item_name = "Dagger"
item3.description = "A sharp dagger"
item3.spriteFrame = 5*20 + 10
item3.modifiers["dmg"] = 2
GameManager.character_data.add_item(item3)
var item4 = Item.new()
item4.item_type = Item.ItemType.Equippable
item4.equipment_type = Item.EquipmentType.MAINHAND
item4.weapon_type = Item.WeaponType.AXE
item4.item_name = "Hand Axe"
item4.description = "A sharp hand axe"
item4.spriteFrame = 5*20 + 11
item4.modifiers["dmg"] = 4
GameManager.character_data.add_item(item4)
var item5 = Item.new()
item5.item_type = Item.ItemType.Equippable
item5.equipment_type = Item.EquipmentType.OFFHAND
item5.weapon_type = Item.WeaponType.AMMUNITION
item5.quantity = 13
item5.can_have_multiple_of = true
item5.item_name = "Iron Arrow"
item5.description = "A sharp arrow made of iron and feathers from pelican birds"
item5.spriteFrame = 7*20 + 11
item5.modifiers["dmg"] = 3
GameManager.character_data.add_item(item5)
var item6 = Item.new()
item6.item_type = Item.ItemType.Equippable
item6.equipment_type = Item.EquipmentType.MAINHAND
item6.weapon_type = Item.WeaponType.BOW
item6.item_name = "Wooden Bow"
item6.description = "A wooden bow made of elfish lembas trees"
item6.spriteFrame = 6*20 + 16
item6.modifiers["dmg"] = 3
GameManager.character_data.add_item(item6)
var item7 = Item.new()
item7.item_type = Item.ItemType.Equippable
item7.equipment_type = Item.EquipmentType.BOOTS
item7.weapon_type = Item.WeaponType.NONE
item7.item_name = "Sandals"
item7.description = "A pair of shitty sandals"
item7.equipmentPath = "res://assets/gfx/Puny-Characters/Layer 1 - Shoes/ShoesBrown.png"
item7.spriteFrame = 2*20 + 10
item7.modifiers["def"] = 1
GameManager.character_data.add_item(item7)
'
# clear default stuff
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.texture = null
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/LabelItemDescription.text = ""
pass
func _charChanged(iChar:CharacterStats):
# update all stats:
$ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer/LabelBaseStatsValue.text = str(iChar.level) + "\r\n" + \
"\r\n" + \
str(floori(iChar.hp)) + "/" + str(floori(iChar.maxhp)) + "\r\n" + \
str(floori(iChar.mp)) + "/" + str(floori(iChar.maxmp)) + "\r\n" + \
"\r\n" + \
str(iChar.baseStats.str) + "\r\n" + \
str(iChar.baseStats.dex) + "\r\n" + \
str(iChar.baseStats.end) + "\r\n" + \
str(iChar.baseStats.int) + "\r\n" + \
str(iChar.baseStats.wis) + "\r\n" + \
str(iChar.baseStats.lck)
$ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer/LabelDerivedStatsValue.text = str(floori(iChar.xp)) + "/" + str(floori(iChar.xp_to_next_level)) + "\r\n" + \
str(iChar.coin) + "\r\n" + \
"\r\n" + \
"\r\n" + \
"\r\n" + \
str(iChar.damage) + "\r\n" + \
str(iChar.defense) + "\r\n" + \
str(iChar.move_speed) + "\r\n" + \
str(iChar.attack_speed) + "\r\n" + \
str(iChar.sight) + "\r\n" + \
str(iChar.spell_amp) + "\r\n" + \
str(iChar.crit_chance) + "%"
# read inventory and populate inventory
var vboxInvent = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory
for child in vboxInvent.find_child("HBoxControl1").get_children():
child.get_parent().remove_child(child)
child.propagate_call("queue_free", [])
for child in vboxInvent.find_child("HBoxControl2").get_children():
child.get_parent().remove_child(child)
child.propagate_call("queue_free", [])
for child in vboxInvent.find_child("HBoxControl3").get_children():
child.get_parent().remove_child(child)
child.propagate_call("queue_free", [])
var selected_tex = preload("res://assets/gfx/ui/inventory_slot_kenny_white.png")
var styleBoxHover:StyleBox = StyleBoxTexture.new()
var styleBoxFocused:StyleBox = StyleBoxTexture.new()
var styleBoxPressed:StyleBox = StyleBoxTexture.new()
var styleBoxEmpty:StyleBox = StyleBoxEmpty.new()
styleBoxHover.texture = selected_tex
styleBoxFocused.texture = selected_tex
styleBoxPressed.texture = selected_tex
var quantityFont:Font = load("res://assets/fonts/dmg_numbers.png")
for item:Item in iChar.inventory:
var btn:Button = Button.new()
btn.add_theme_stylebox_override("normal", styleBoxEmpty)
btn.add_theme_stylebox_override("hover", styleBoxHover)
btn.add_theme_stylebox_override("focus", styleBoxFocused)
btn.add_theme_stylebox_override("pressed", styleBoxPressed)
btn.custom_minimum_size = Vector2(24, 24)
btn.size = Vector2(24, 24)
vboxInvent.find_child("HBoxControl1").add_child(btn)
var spr:Sprite2D = Sprite2D.new()
spr.texture = load(item.spritePath)
spr.hframes = item.spriteFrames.x
spr.vframes = item.spriteFrames.y
spr.frame = item.spriteFrame
spr.centered = false
spr.position = Vector2(4,4)
btn.add_child(spr)
if item.can_have_multiple_of:
var lblQuantity:Label = Label.new()
lblQuantity.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
lblQuantity.size = Vector2(24, 24)
lblQuantity.custom_minimum_size = Vector2(0,0)
lblQuantity.position = Vector2(10, 2)
lblQuantity.text = str(item.quantity)
lblQuantity.add_theme_font_override("font", quantityFont)
lblQuantity.add_theme_font_size_override("font", 8)
lblQuantity.scale = Vector2(0.5, 0.5)
btn.add_child(lblQuantity)
pass
btn.connect("pressed", _selectItem.bind(item, true))
btn.connect("focus_entered", _selectItem.bind(item, false))
pass
# clear eq container...
var eqContainer = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer
for child in eqContainer.get_children():
child.get_parent().remove_child(child)
child.propagate_call("queue_free", [])
'"mainhand": null,
"offhand": null,
"headgear": null,
"armour": null,
"boots": null,
"accessory": null'
addEq(iChar, "mainhand", eqContainer, styleBoxEmpty, styleBoxHover, styleBoxFocused, styleBoxPressed, quantityFont)
addEq(iChar, "offhand", eqContainer, styleBoxEmpty, styleBoxHover, styleBoxFocused, styleBoxPressed, quantityFont)
addEq(iChar, "headgear", eqContainer, styleBoxEmpty, styleBoxHover, styleBoxFocused, styleBoxPressed, quantityFont)
addEq(iChar, "armour", eqContainer, styleBoxEmpty, styleBoxHover, styleBoxFocused, styleBoxPressed, quantityFont)
addEq(iChar, "boots", eqContainer, styleBoxEmpty, styleBoxHover, styleBoxFocused, styleBoxPressed, quantityFont)
addEq(iChar, "accessory", eqContainer, styleBoxEmpty, styleBoxHover, styleBoxFocused, styleBoxPressed, quantityFont)
pass
func addEq(iChar:CharacterStats, iPiece:String, eqContainer:Control, styleBoxEmpty: StyleBox, styleBoxHover: StyleBox, styleBoxFocused: StyleBox, styleBoxPressed: StyleBox, quantityFont: Font):
if iChar.equipment[iPiece] != null:
var btn:Button = Button.new()
btn.add_theme_stylebox_override("normal", styleBoxEmpty)
btn.add_theme_stylebox_override("hover", styleBoxHover)
btn.add_theme_stylebox_override("focus", styleBoxFocused)
btn.add_theme_stylebox_override("pressed", styleBoxPressed)
btn.custom_minimum_size = Vector2(24, 24)
btn.position = Vector2(1,9)
match iPiece:
"armour":
btn.position = Vector2(28, 9)
pass
"offhand":
btn.position = Vector2(55, 9)
pass
"headgear":
btn.position = Vector2(1, 36)
pass
"boots":
btn.position = Vector2(28, 36)
pass
"accessory":
btn.position = Vector2(55, 36)
pass
pass
eqContainer.add_child(btn)
var spr:Sprite2D = Sprite2D.new()
spr.texture = load(iChar.equipment[iPiece].spritePath)
spr.hframes = iChar.equipment[iPiece].spriteFrames.x
spr.vframes = iChar.equipment[iPiece].spriteFrames.y
spr.frame = iChar.equipment[iPiece].spriteFrame
spr.centered = false
spr.position = Vector2(4,4)
btn.add_child(spr)
btn.connect("pressed", _selectEquipment.bind(iChar.equipment[iPiece], true))
btn.connect("focus_entered", _selectEquipment.bind(iChar.equipment[iPiece], false))
if iChar.equipment[iPiece].can_have_multiple_of:
var lblQuantity:Label = Label.new()
lblQuantity.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
lblQuantity.size = Vector2(24, 24)
lblQuantity.custom_minimum_size = Vector2(0,0)
lblQuantity.position = Vector2(10, 2)
lblQuantity.text = str(iChar.equipment[iPiece].quantity)
lblQuantity.add_theme_font_override("font", quantityFont)
lblQuantity.add_theme_font_size_override("font", 8)
lblQuantity.scale = Vector2(0.5, 0.5)
btn.add_child(lblQuantity)
pass
pass
pass
# draw equipment buttons (for unequipping)
func _selectEquipment(item:Item, isPress: bool):
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/ButtonDrop.visible = true
if !is_showing_inventory:
return
if lastPressedItem == item and lastPressedType == "Equipment" and timerSelect > 0:
$SfxUnequip.play()
GameManager.character_data.unequip_item(selectedEquipment)
selectedItem = selectedEquipment
lastPressedItem = null
selectedEquipment = null
lastPressedType = "Item"
var vboxInvent = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory
for child in vboxInvent.find_child("HBoxControl1").get_children():
child.grab_focus()
break
return
lastPressedType = "Equipment"
selectedEquipment = item
# update description in bottom
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.texture = load(item.spritePath)
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.hframes = item.spriteFrames.x
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.vframes = item.spriteFrames.y
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.frame = item.spriteFrame
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/LabelItemDescription.text = item.description
if isPress:
lastPressedItem = item
timerSelect = 0.4
# unequip item
pass
func _selectItem(item:Item, isPress: bool):
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/ButtonDrop.visible = true
if !is_showing_inventory:
return
if lastPressedItem == item and lastPressedType == "Item" and timerSelect > 0:
timerSelect = 0
$SfxEquip.play()
GameManager.character_data.equip_item(selectedItem)
selectedEquipment = selectedItem
selectedItem = null
lastPressedItem = null
lastPressedType = "Equipment"
var eqContainer = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer
for child in eqContainer.get_children():
child.grab_focus()
break
return
lastPressedType = "Item"
selectedItem = item
# update description in bottom
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.texture = load(item.spritePath)
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.hframes = item.spriteFrames.x
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.vframes = item.spriteFrames.y
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.frame = item.spriteFrame
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/LabelItemDescription.text = item.description
if isPress:
lastPressedItem = item
timerSelect = 0.4
pass
func _process(delta: float) -> void:
if timerSelect > 0:
timerSelect -= delta
if timerSelect <= 0:
timerSelect = 0
pass
func _input(_event: InputEvent):
#print("connected to newtwork:", GameManager.is_network_connected)
#print("finished tween:", finished_tween)
if !GameManager.is_network_connected or finished_tween == false:
return
if is_showing_inventory:
if !$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/ButtonDrop.has_focus():
if lastPressedType == "Equipment" and selectedEquipment != null and Input.is_action_just_pressed("ui_accept"):
$SfxUnequip.play()
GameManager.character_data.unequip_item(selectedEquipment)
selectedItem = selectedEquipment
selectedEquipment = null
lastPressedItem = null
lastPressedType = "Item"
var vboxInvent = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory
for child in vboxInvent.find_child("HBoxControl1").get_children():
child.grab_focus()
break
return
if lastPressedType == "Item" and selectedItem != null and Input.is_action_just_pressed("ui_accept"):
$SfxEquip.play()
GameManager.character_data.equip_item(selectedItem)
selectedEquipment = selectedItem
selectedItem = null
lastPressedItem = null
lastPressedType = "Equipment"
var eqContainer = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer
for child in eqContainer.get_children():
child.grab_focus()
break
return
if Input.is_action_just_pressed("inventory") and finished_tween == true:
finished_tween = false
var move_range = 119
var move_duration = 0.3
if is_showing_inventory:
move_range = -move_range
#stats movement
var move_tween = get_tree().create_tween()
move_tween.tween_property($ControlContainer/ControlStats, "position:x",$ControlContainer/ControlStats.position.x + move_range,move_duration).from($ControlContainer/ControlStats.position.x).set_trans(Tween.TRANS_EXPO).set_ease(Tween.EASE_IN_OUT)
move_range = -80
if is_showing_inventory:
move_range = -move_range
#inventory movement
var move_tween2 = get_tree().create_tween()
move_tween2.tween_property($ControlContainer/ControlInventory, "position:x",$ControlContainer/ControlInventory.position.x + move_range,move_duration).from($ControlContainer/ControlInventory.position.x).set_trans(Tween.TRANS_EXPO).set_ease(Tween.EASE_IN_OUT)
move_range = -33
if is_showing_inventory:
$SfxInventoryClose.play()
move_range = -move_range
else:
$SfxInventoryOpen.play()
#info movement
var move_tween3 = get_tree().create_tween()
move_tween3.tween_property($ControlContainer/ControlInfo, "position:y",$ControlContainer/ControlInfo.position.y + move_range,move_duration).from($ControlContainer/ControlInfo.position.y).set_trans(Tween.TRANS_EXPO).set_ease(Tween.EASE_IN_OUT)
is_showing_inventory = !is_showing_inventory
await move_tween3.finished
finished_tween = true
if is_showing_inventory:
# preselect first item
var vboxInvent = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory
var hadInventoryItem = false
for child in vboxInvent.find_child("HBoxControl1").get_children():
child.grab_focus()
hadInventoryItem = true
break
lastPressedType = "Item"
if hadInventoryItem == false:
# preselect something in equipment instead
selectedItem = null
lastPressedItem = null
lastPressedType = "Equipment"
var eqContainer = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer
for child in eqContainer.get_children():
child.grab_focus()
break
pass
pass
'
if Input.is_action_just_pressed("ui_right"):
$ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer.
pass
if Input.is_action_just_pressed("ui_left"):
pass'
'
if Input.is_action_just_pressed("ui_up"):
$ControlContainer/ControlInventory/Sprite2DSelector.position.y -= 20
pass
if Input.is_action_just_pressed("ui_down"):
$ControlContainer/ControlInventory/Sprite2DSelector.position.y += 20
pass'
func _on_button_drop_pressed() -> void:
if !is_showing_inventory:
return
if lastPressedType == "Item":
if selectedItem != null:
GameManager.character_data.drop_item(selectedItem)
selectedItem = null
# clear default stuff
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.texture = null
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/LabelItemDescription.text = ""
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/ButtonDrop.visible = false
else:
if selectedEquipment != null:
GameManager.character_data.drop_equipment(selectedEquipment)
selectedEquipment = null
# clear default stuff
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control/Sprite2DItem.texture = null
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/LabelItemDescription.text = ""
$ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/ButtonDrop.visible = false
var vboxInvent = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory
var hadInventoryItem = false
for child in vboxInvent.find_child("HBoxControl1").get_children():
child.grab_focus()
hadInventoryItem = true
break
lastPressedType = "Item"
if hadInventoryItem == false:
selectedItem = null
lastPressedItem = null
lastPressedType = "Equipment"
var eqContainer = $ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer
for child in eqContainer.get_children():
child.grab_focus()
break
pass # Replace with function body.

View File

@@ -1 +0,0 @@
uid://20kfmxrtt20e

View File

@@ -1,693 +0,0 @@
[gd_scene format=3 uid="uid://du1cpug8yag6w"]
[ext_resource type="Texture2D" uid="uid://b7u7dbiaub8lp" path="res://assets/gfx/ruinborn_mImwZSNWBM.png" id="1_0amil"]
[ext_resource type="Script" uid="uid://20kfmxrtt20e" path="res://assets/scripts/ui/inventory.gd" id="1_k81k7"]
[ext_resource type="Texture2D" uid="uid://hib38y541eog" path="res://assets/gfx/items_n_shit.png" id="2_7vwhs"]
[ext_resource type="Texture2D" uid="uid://ct0rllwve2s1y" path="res://assets/gfx/ui/inventory_panel_small.png" id="2_voqm7"]
[ext_resource type="Texture2D" uid="uid://who0clhmi5cl" path="res://assets/gfx/ui/inventory_panel.png" id="4_nlhqn"]
[ext_resource type="Texture2D" uid="uid://cxend0ndnfn32" path="res://assets/gfx/ui/inventory_slot_kenny_white.png" id="4_nxmsh"]
[ext_resource type="Texture2D" uid="uid://bsnfadlf1dgnw" path="res://assets/gfx/ui/inventory_slot_kenny_black_sword.png" id="6_k81k7"]
[ext_resource type="FontFile" uid="uid://cbmcfue0ek0tk" path="res://assets/fonts/dmg_numbers.png" id="7_kiwfx"]
[ext_resource type="Texture2D" uid="uid://tdivehfcj0el" path="res://assets/gfx/ui/inventory_slot_kenny_black_shield.png" id="7_vardb"]
[ext_resource type="Texture2D" uid="uid://b1l30o2ljhl2t" path="res://assets/gfx/ui/inventory_slot_kenny_black_armour.png" id="8_mnwqb"]
[ext_resource type="Texture2D" uid="uid://jgbrhnsaxvg" path="res://assets/gfx/ui/inventory_slot_kenny_black_helm.png" id="9_nbh80"]
[ext_resource type="Texture2D" uid="uid://b71gs7h2v0rdi" path="res://assets/gfx/ui/inventory_slot_kenny_black_ring.png" id="10_kiwfx"]
[ext_resource type="Texture2D" uid="uid://ckctmypotajtf" path="res://assets/gfx/ui/inventory_slot_kenny_black_shoes.png" id="11_ylqbh"]
[ext_resource type="Texture2D" uid="uid://c21a60s4funrr" path="res://assets/gfx/ui/inventory_info_panel.png" id="13_vardb"]
[ext_resource type="AudioStream" uid="uid://x6lxrywls7e2" path="res://assets/audio/sfx/inventory/inventory_open.mp3" id="14_mnwqb"]
[ext_resource type="AudioStream" uid="uid://cfsubtwvpi7yn" path="res://assets/audio/sfx/inventory/inventory_open_inverted.mp3" id="14_nbh80"]
[ext_resource type="AudioStream" uid="uid://djw6c5rb4mm60" path="res://assets/audio/sfx/cloth/leather_cloth_02.wav.mp3" id="17_51fgf"]
[ext_resource type="AudioStream" uid="uid://umoxmryvbm01" path="res://assets/audio/sfx/cloth/leather_cloth_01.wav.mp3" id="18_qk47y"]
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_nbh80"]
texture = ExtResource("4_nxmsh")
modulate_color = Color(0.511719, 0.511719, 0.511719, 1)
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_kiwfx"]
texture = ExtResource("4_nxmsh")
modulate_color = Color(0, 0, 0, 1)
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_ylqbh"]
texture = ExtResource("4_nxmsh")
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_nbh80"]
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_51fgf"]
texture = ExtResource("4_nxmsh")
[node name="Inventory" type="CanvasLayer"]
layer = 21
script = ExtResource("1_k81k7")
[node name="Sprite2D" type="Sprite2D" parent="."]
visible = false
modulate = Color(0.980057, 0.975295, 1, 1)
z_index = -2
z_as_relative = false
position = Vector2(164.625, 92.75)
scale = Vector2(0.258803, 0.263268)
texture = ExtResource("1_0amil")
[node name="ControlContainer" type="Control" parent="."]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="ControlStats" type="Control" parent="ControlContainer"]
layout_mode = 1
anchors_preset = 9
anchor_bottom = 1.0
grow_vertical = 2
[node name="Sprite2DPanelz" type="Sprite2D" parent="ControlContainer/ControlStats"]
texture = ExtResource("4_nlhqn")
centered = false
[node name="MarginContainer" type="MarginContainer" parent="ControlContainer/ControlStats"]
layout_mode = 0
offset_right = 40.0
offset_bottom = 40.0
theme_override_constants/margin_left = 3
theme_override_constants/margin_top = 3
theme_override_constants/margin_right = 3
theme_override_constants/margin_bottom = 3
[node name="VBoxContainer" type="VBoxContainer" parent="ControlContainer/ControlStats/MarginContainer"]
layout_mode = 2
[node name="LabelPlayerName" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 6
text = "Fronko"
horizontal_alignment = 1
[node name="HBoxContainer" type="HBoxContainer" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="LabelBaseStats" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 6
text = "Level
Hp
Mp
Str
Dex
End
Int
Wis
Lck"
[node name="LabelBaseStatsValue" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 6
text = "1
30 / 30
20 / 20
10
10
10
10
10
10"
horizontal_alignment = 2
[node name="LabelDerivedStats" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 6
text = "Exp
Coin
Damage
Defense
MovSpd
AtkSpd
Sight
SpellAmp
CritChance"
[node name="LabelDerivedStatsValue" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 6
text = "400 / 1000
1
2
3
2.1
1.4
7.0
3.0
12.0%"
horizontal_alignment = 2
[node name="ControlInventory" type="Control" parent="ControlContainer"]
custom_minimum_size = Vector2(80, 0)
layout_mode = 1
anchors_preset = 11
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 0
grow_vertical = 2
[node name="Sprite2DPanel" type="Sprite2D" parent="ControlContainer/ControlInventory"]
modulate = Color(0, 0, 0, 0.862745)
texture = ExtResource("2_voqm7")
centered = false
[node name="MarginContainer" type="MarginContainer" parent="ControlContainer/ControlInventory"]
custom_minimum_size = Vector2(80, 0)
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="VBoxContainer" type="VBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer"]
layout_mode = 2
theme_override_constants/separation = 0
[node name="LabelInventory" type="Label" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 6
text = "Inventory"
horizontal_alignment = 1
[node name="ControlInventory" type="Control" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer"]
custom_minimum_size = Vector2(0, 72)
layout_mode = 2
[node name="MarginContainer" type="MarginContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory"]
layout_mode = 2
offset_left = 2.0
offset_top = 2.0
offset_right = 78.0
offset_bottom = 70.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="ScrollContainer" type="ScrollContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer"]
layout_mode = 2
follow_focus = true
[node name="VBoxContainerInventory" type="VBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer"]
layout_mode = 2
theme_override_constants/separation = -4
[node name="HBoxControl1" type="HBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 0
[node name="Button3" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button3"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="LabelStack" type="Label" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button3"]
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -26.0
offset_top = 2.0
offset_right = -2.0
offset_bottom = 26.0
grow_horizontal = 0
theme_override_fonts/font = ExtResource("7_kiwfx")
theme_override_font_sizes/font_size = 8
text = "5"
horizontal_alignment = 2
[node name="Button6" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button6"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button5" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button5"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button4" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button4"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="HBoxControl2" type="HBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 0
[node name="Button3" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2/Button3"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button5" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2/Button5"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button4" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2/Button4"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="HBoxControl3" type="HBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 0
[node name="Button3" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3/Button3"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button5" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3/Button5"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button4" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3/Button4"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="ControlEquipment" type="Control" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer"]
custom_minimum_size = Vector2(80, 64)
layout_mode = 2
[node name="Label" type="Label" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
layout_mode = 1
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -21.5
offset_right = 21.5
offset_bottom = 23.0
grow_horizontal = 2
theme_override_font_sizes/font_size = 6
text = "Equipment"
horizontal_alignment = 1
[node name="Sprite2D" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(13, 21)
texture = ExtResource("6_k81k7")
[node name="Sprite2D2" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(67, 21)
texture = ExtResource("7_vardb")
[node name="Sprite2D3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(40, 21)
texture = ExtResource("8_mnwqb")
[node name="Sprite2D4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(13, 48)
texture = ExtResource("9_nbh80")
[node name="Sprite2D9" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(67, 48)
texture = ExtResource("10_kiwfx")
[node name="Sprite2D5" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(40, 48)
texture = ExtResource("11_ylqbh")
[node name="ControlEquipmentContainer" type="Control" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Button" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 1.0
offset_top = 9.0
offset_right = 25.0
offset_bottom = 33.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button2" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 28.0
offset_top = 9.0
offset_right = 52.0
offset_bottom = 33.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button2"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button3" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 55.0
offset_top = 9.0
offset_right = 79.0
offset_bottom = 33.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button3"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button4" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 1.0
offset_top = 36.0
offset_right = 25.0
offset_bottom = 60.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button4"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button5" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 28.0
offset_top = 36.0
offset_right = 52.0
offset_bottom = 60.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button5"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button6" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 55.0
offset_top = 36.0
offset_right = 79.0
offset_bottom = 60.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button6"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="ControlInfo" type="Control" parent="ControlContainer"]
custom_minimum_size = Vector2(0, 33)
layout_mode = 1
anchors_preset = 12
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 0
[node name="Control" type="Control" parent="ControlContainer/ControlInfo"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Sprite2D" type="Sprite2D" parent="ControlContainer/ControlInfo/Control"]
texture = ExtResource("13_vardb")
centered = false
[node name="MarginContainer" type="MarginContainer" parent="ControlContainer/ControlInfo/Control"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 5
theme_override_constants/margin_top = 5
theme_override_constants/margin_right = 5
theme_override_constants/margin_bottom = 5
[node name="HBoxContainer" type="HBoxContainer" parent="ControlContainer/ControlInfo/Control/MarginContainer"]
layout_mode = 2
[node name="Control" type="Control" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_vertical = 4
[node name="Sprite2DSelector" type="Sprite2D" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control"]
modulate = Color(0.20704, 0.205805, 0.214844, 1)
texture = ExtResource("4_nxmsh")
centered = false
[node name="Sprite2DItem" type="Sprite2D" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="LabelItemDescription" type="Label" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer"]
layout_mode = 2
size_flags_vertical = 1
theme_override_font_sizes/font_size = 6
text = "A small, but sturdy wooden shield. + 1 DEF"
[node name="ButtonDrop" type="Button" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 8
text = "Drop"
[node name="SfxInventoryClose" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("14_nbh80")
volume_db = -10.0
[node name="SfxInventoryOpen" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("14_mnwqb")
volume_db = -10.0
[node name="SfxUnequip" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("17_51fgf")
[node name="SfxEquip" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("18_qk47y")
[connection signal="pressed" from="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/ButtonDrop" to="." method="_on_button_drop_pressed"]

View File

@@ -1,692 +0,0 @@
[gd_scene load_steps=24 format=3 uid="uid://du1cpug8yag6w"]
[ext_resource type="Texture2D" uid="uid://b7u7dbiaub8lp" path="res://assets/gfx/ruinborn_mImwZSNWBM.png" id="1_0amil"]
[ext_resource type="Script" uid="uid://20kfmxrtt20e" path="res://assets/scripts/ui/inventory.gd" id="1_k81k7"]
[ext_resource type="Texture2D" uid="uid://hib38y541eog" path="res://assets/gfx/items_n_shit.png" id="2_7vwhs"]
[ext_resource type="Texture2D" uid="uid://ct0rllwve2s1y" path="res://assets/gfx/ui/inventory_panel_small.png" id="2_voqm7"]
[ext_resource type="Texture2D" uid="uid://who0clhmi5cl" path="res://assets/gfx/ui/inventory_panel.png" id="4_nlhqn"]
[ext_resource type="Texture2D" uid="uid://cxend0ndnfn32" path="res://assets/gfx/ui/inventory_slot_kenny_white.png" id="4_nxmsh"]
[ext_resource type="Texture2D" uid="uid://bsnfadlf1dgnw" path="res://assets/gfx/ui/inventory_slot_kenny_black_sword.png" id="6_k81k7"]
[ext_resource type="FontFile" uid="uid://cbmcfue0ek0tk" path="res://assets/fonts/dmg_numbers.png" id="7_kiwfx"]
[ext_resource type="Texture2D" uid="uid://tdivehfcj0el" path="res://assets/gfx/ui/inventory_slot_kenny_black_shield.png" id="7_vardb"]
[ext_resource type="Texture2D" uid="uid://b1l30o2ljhl2t" path="res://assets/gfx/ui/inventory_slot_kenny_black_armour.png" id="8_mnwqb"]
[ext_resource type="Texture2D" uid="uid://jgbrhnsaxvg" path="res://assets/gfx/ui/inventory_slot_kenny_black_helm.png" id="9_nbh80"]
[ext_resource type="Texture2D" uid="uid://b71gs7h2v0rdi" path="res://assets/gfx/ui/inventory_slot_kenny_black_ring.png" id="10_kiwfx"]
[ext_resource type="Texture2D" uid="uid://ckctmypotajtf" path="res://assets/gfx/ui/inventory_slot_kenny_black_shoes.png" id="11_ylqbh"]
[ext_resource type="Texture2D" uid="uid://c21a60s4funrr" path="res://assets/gfx/ui/inventory_info_panel.png" id="13_vardb"]
[ext_resource type="AudioStream" uid="uid://x6lxrywls7e2" path="res://assets/audio/sfx/inventory/inventory_open.mp3" id="14_mnwqb"]
[ext_resource type="AudioStream" uid="uid://cfsubtwvpi7yn" path="res://assets/audio/sfx/inventory/inventory_open_inverted.mp3" id="14_nbh80"]
[ext_resource type="AudioStream" uid="uid://djw6c5rb4mm60" path="res://assets/audio/sfx/cloth/leather_cloth_02.wav.mp3" id="17_51fgf"]
[ext_resource type="AudioStream" uid="uid://umoxmryvbm01" path="res://assets/audio/sfx/cloth/leather_cloth_01.wav.mp3" id="18_qk47y"]
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_nbh80"]
texture = ExtResource("4_nxmsh")
modulate_color = Color(0.511719, 0.511719, 0.511719, 1)
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_kiwfx"]
texture = ExtResource("4_nxmsh")
modulate_color = Color(0, 0, 0, 1)
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_ylqbh"]
texture = ExtResource("4_nxmsh")
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_nbh80"]
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_51fgf"]
texture = ExtResource("4_nxmsh")
[node name="Inventory" type="CanvasLayer"]
layer = 21
script = ExtResource("1_k81k7")
[node name="Sprite2D" type="Sprite2D" parent="."]
visible = false
modulate = Color(0.980057, 0.975295, 1, 1)
z_index = -2
z_as_relative = false
position = Vector2(164.625, 92.75)
scale = Vector2(0.258803, 0.263268)
texture = ExtResource("1_0amil")
[node name="ControlContainer" type="Control" parent="."]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="ControlStats" type="Control" parent="ControlContainer"]
layout_mode = 1
anchors_preset = 9
anchor_bottom = 1.0
grow_vertical = 2
[node name="Sprite2DPanelz" type="Sprite2D" parent="ControlContainer/ControlStats"]
texture = ExtResource("4_nlhqn")
centered = false
[node name="MarginContainer" type="MarginContainer" parent="ControlContainer/ControlStats"]
layout_mode = 0
offset_right = 40.0
offset_bottom = 40.0
theme_override_constants/margin_left = 3
theme_override_constants/margin_top = 3
theme_override_constants/margin_right = 3
theme_override_constants/margin_bottom = 3
[node name="VBoxContainer" type="VBoxContainer" parent="ControlContainer/ControlStats/MarginContainer"]
layout_mode = 2
[node name="LabelPlayerName" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 6
text = "Fronko"
horizontal_alignment = 1
[node name="HBoxContainer" type="HBoxContainer" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="LabelBaseStats" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 6
text = "Level
Hp
Mp
Str
Dex
End
Int
Wis
Lck"
[node name="LabelBaseStatsValue" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 6
text = "1
30 / 30
20 / 20
10
10
10
10
10
10"
horizontal_alignment = 2
[node name="LabelDerivedStats" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 6
text = "Exp
Coin
Damage
Defense
MovSpd
AtkSpd
Sight
SpellAmp
CritChance"
[node name="LabelDerivedStatsValue" type="Label" parent="ControlContainer/ControlStats/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/line_spacing = 0
theme_override_font_sizes/font_size = 6
text = "400 / 1000
1
2
3
2.1
1.4
7.0
3.0
12.0%"
horizontal_alignment = 2
[node name="ControlInventory" type="Control" parent="ControlContainer"]
custom_minimum_size = Vector2(80, 0)
layout_mode = 1
anchors_preset = 11
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 0
grow_vertical = 2
[node name="Sprite2DPanel" type="Sprite2D" parent="ControlContainer/ControlInventory"]
modulate = Color(0, 0, 0, 0.862745)
texture = ExtResource("2_voqm7")
centered = false
[node name="MarginContainer" type="MarginContainer" parent="ControlContainer/ControlInventory"]
custom_minimum_size = Vector2(80, 0)
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="VBoxContainer" type="VBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer"]
layout_mode = 2
theme_override_constants/separation = 0
[node name="LabelInventory" type="Label" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 6
text = "Inventory"
horizontal_alignment = 1
[node name="ControlInventory" type="Control" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer"]
custom_minimum_size = Vector2(0, 72)
layout_mode = 2
[node name="MarginContainer" type="MarginContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory"]
layout_mode = 2
offset_left = 2.0
offset_top = 2.0
offset_right = 78.0
offset_bottom = 70.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="ScrollContainer" type="ScrollContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer"]
layout_mode = 2
follow_focus = true
[node name="VBoxContainerInventory" type="VBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer"]
layout_mode = 2
theme_override_constants/separation = -4
[node name="HBoxControl1" type="HBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 0
[node name="Button3" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button3"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="LabelStack" type="Label" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button3"]
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -26.0
offset_top = 2.0
offset_right = -2.0
offset_bottom = 26.0
grow_horizontal = 0
theme_override_fonts/font = ExtResource("7_kiwfx")
theme_override_font_sizes/font_size = 8
text = "5"
horizontal_alignment = 2
[node name="Button6" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button6"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button5" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button5"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button4" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl1/Button4"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="HBoxControl2" type="HBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 0
[node name="Button3" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2/Button3"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button5" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2/Button5"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button4" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl2/Button4"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="HBoxControl3" type="HBoxContainer" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 0
[node name="Button3" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3/Button3"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button5" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3/Button5"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button4" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_nbh80")
theme_override_styles/hover = SubResource("StyleBoxTexture_kiwfx")
theme_override_styles/pressed = SubResource("StyleBoxTexture_ylqbh")
theme_override_styles/normal = SubResource("StyleBoxEmpty_nbh80")
text = " "
[node name="Sprite2DShield4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlInventory/MarginContainer/ScrollContainer/VBoxContainerInventory/HBoxControl3/Button4"]
process_mode = 4
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="ControlEquipment" type="Control" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer"]
custom_minimum_size = Vector2(80, 64)
layout_mode = 2
[node name="Label" type="Label" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
layout_mode = 1
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -21.5
offset_right = 21.5
offset_bottom = 23.0
grow_horizontal = 2
theme_override_font_sizes/font_size = 6
text = "Equipment"
horizontal_alignment = 1
[node name="Sprite2D" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(13, 21)
texture = ExtResource("6_k81k7")
[node name="Sprite2D2" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(67, 21)
texture = ExtResource("7_vardb")
[node name="Sprite2D3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(40, 21)
texture = ExtResource("8_mnwqb")
[node name="Sprite2D4" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(13, 48)
texture = ExtResource("9_nbh80")
[node name="Sprite2D9" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(67, 48)
texture = ExtResource("10_kiwfx")
[node name="Sprite2D5" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
modulate = Color(1, 1, 1, 0.670588)
position = Vector2(40, 48)
texture = ExtResource("11_ylqbh")
[node name="ControlEquipmentContainer" type="Control" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Button" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 1.0
offset_top = 9.0
offset_right = 25.0
offset_bottom = 33.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button2" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 28.0
offset_top = 9.0
offset_right = 52.0
offset_bottom = 33.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button2"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button3" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 55.0
offset_top = 9.0
offset_right = 79.0
offset_bottom = 33.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button3"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button4" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 1.0
offset_top = 36.0
offset_right = 25.0
offset_bottom = 60.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button4"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button5" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 28.0
offset_top = 36.0
offset_right = 52.0
offset_bottom = 60.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button5"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="Button6" type="Button" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 0
offset_left = 55.0
offset_top = 36.0
offset_right = 79.0
offset_bottom = 60.0
theme_override_styles/normal = SubResource("StyleBoxTexture_51fgf")
[node name="Sprite2DShield3" type="Sprite2D" parent="ControlContainer/ControlInventory/MarginContainer/VBoxContainer/ControlEquipment/ControlEquipmentContainer/Button6"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="ControlInfo" type="Control" parent="ControlContainer"]
custom_minimum_size = Vector2(0, 33)
layout_mode = 1
anchors_preset = 12
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 0
[node name="Control" type="Control" parent="ControlContainer/ControlInfo"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Sprite2D" type="Sprite2D" parent="ControlContainer/ControlInfo/Control"]
texture = ExtResource("13_vardb")
centered = false
[node name="MarginContainer" type="MarginContainer" parent="ControlContainer/ControlInfo/Control"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 5
theme_override_constants/margin_top = 5
theme_override_constants/margin_right = 5
theme_override_constants/margin_bottom = 5
[node name="HBoxContainer" type="HBoxContainer" parent="ControlContainer/ControlInfo/Control/MarginContainer"]
layout_mode = 2
[node name="Control" type="Control" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_vertical = 4
[node name="Sprite2DSelector" type="Sprite2D" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control"]
modulate = Color(0.20704, 0.205805, 0.214844, 1)
texture = ExtResource("4_nxmsh")
centered = false
[node name="Sprite2DItem" type="Sprite2D" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer/Control"]
position = Vector2(4, 4)
texture = ExtResource("2_7vwhs")
centered = false
hframes = 20
vframes = 14
frame = 8
[node name="LabelItemDescription" type="Label" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer"]
layout_mode = 2
size_flags_vertical = 1
theme_override_font_sizes/font_size = 6
text = "A small, but sturdy wooden shield. + 1 DEF"
[node name="ButtonEquip" type="Button" parent="ControlContainer/ControlInfo/Control/MarginContainer/HBoxContainer"]
visible = false
layout_mode = 2
theme_override_font_sizes/font_size = 8
text = "Equip"
[node name="SfxInventoryClose" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("14_nbh80")
volume_db = -10.0
[node name="SfxInventoryOpen" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("14_mnwqb")
volume_db = -10.0
[node name="SfxUnequip" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("17_51fgf")
[node name="SfxEquip" type="AudioStreamPlayer2D" parent="."]
stream = ExtResource("18_qk47y")

View File

@@ -1,167 +0,0 @@
extends CharacterBody2D
var it: Item = null
@export var sync_has_been_picked_up: bool = false
var friction = 8.0 # Lower values make the slowdown more gradual
var bounceTimer = 0.0
# Z-axis variables
var positionZ = 4.0 # Start slightly in the air
var velocityZ = 10.0 # Initial upward velocity
var accelerationZ = -330.0 # Gravity
var bounceRestitution = 0.3 # How much bounce energy is retained (0-1)
var minBounceVelocity = 60.0 # Minimum velocity needed to bounce
var sync_position := Vector2()
var sync_velocity := Vector2()
var sync_positionZ: float = 4.0
func _ready() -> void:
add_to_group("loot")
# Initialize item if needed
if it == null:
setItem()
func _process(delta: float) -> void:
if multiplayer.is_server():
if bounceTimer > 0.0:
bounceTimer -= delta
if bounceTimer < 0:
bounceTimer = 0
# Update vertical movement
velocityZ += accelerationZ * delta
positionZ += velocityZ * delta
# Ground collision and bounce
if positionZ <= 0:
velocity = velocity.lerp(Vector2.ZERO, 1.0 - exp(-friction * delta)) # only slow down if on floor
positionZ = 0
if abs(velocityZ) > minBounceVelocity:
#Bounce sound here for items:
#$SfxCoinBounce.volume_db = -1 + (-10-(velocityZ*0.1))
#$SfxCoinBounce.play()
velocityZ = -velocityZ * bounceRestitution
else:
velocityZ = 0
update_sprite_scale()
move_and_slide()
pass
func _physics_process(_delta: float) -> void:
if multiplayer.is_server():
for peer_id in multiplayer.get_peers():
sync_loot.rpc_id(peer_id, position, velocity, positionZ)
if !multiplayer.is_server():
position = sync_position
velocity = sync_velocity
positionZ = sync_positionZ
update_sprite_scale()
pass
@rpc("unreliable")
func sync_loot(pos: Vector2, vel: Vector2, posZ: float):
sync_position = pos
sync_velocity = vel
sync_positionZ = posZ
pass
func update_sprite_scale() -> void:
# Calculate scale based on height
# Maximum height will have scale 1.3, ground will have scale 1.0
var height_factor = positionZ / 50.0 # Assuming 20 is max height
var posY = 0.0 + (2 * positionZ)
var sc = 1.0 + (0.8 * height_factor)
$Sprite2D.scale = Vector2(sc, sc)
$Sprite2D.position.y = -posY
pass
func setItem(iItem: Item = null) -> void:
$Label.visible = false
if iItem != null:
it = iItem
else:
it = Item.new()
if $Sprite2D.texture != null or $Sprite2D.texture.resource_path != it.spritePath:
$Sprite2D.texture = load(it.spritePath)
$Sprite2D.frame = it.spriteFrame
pass
@rpc("any_peer", "reliable", "call_local")
func request_pickup(_player_id: int):
if multiplayer.is_server():
sync_has_been_picked_up = true
visible = false
# Tell all clients to remove the loot
remove_loot.rpc()
$SfxPickup.play()
await $SfxPickup.finished
# Remove loot on server too
queue_free()
# Called locally by the player picking up the item
func pick_up_local(player_id: int):
if sync_has_been_picked_up:
return
var player = MultiplayerManager.playersNode.get_node(str(player_id))
if player:
sync_has_been_picked_up = true
visible = false
# Add item to local inventory
player.stats.add_item(it)
# Tell server about pickup
if not multiplayer.is_server():
request_pickup.rpc_id(1, player_id)
else:
# Tell all clients to remove the loot
remove_loot.rpc()
$SfxPickup.play()
await $SfxPickup.finished
# Remove loot locally immediately
queue_free()
@rpc("authority", "reliable")
func remove_loot():
visible = false
sync_has_been_picked_up = true
$SfxPickup.play()
await $SfxPickup.finished
queue_free()
func _on_area_2d_body_entered(_body: Node2D) -> void:
$Label.visible = true
pass # Replace with function body.
func _on_area_2d_body_exited(_body: Node2D) -> void:
$Label.visible = false
pass # Replace with function body.
func _on_area_2d_collision_body_entered(_body: Node2D) -> void:
if bounceTimer == 0:
#$SfxCoinBounce.play()
bounceTimer = 0.08
# inverse the direction and slow down slightly
var collision_shape = $Area2DCollision.get_overlapping_bodies()
if collision_shape.size() > 0:
var collider = collision_shape[0]
var normal = (global_position - collider.global_position).normalized()
velocity = velocity.bounce(normal)
pass # Replace with function body.
func _on_area_2d_pickup_area_entered(_area: Area2D) -> void:
$Label.visible = true
pass # Replace with function body.
func _on_area_2d_pickup_area_exited(_area: Area2D) -> void:
$Label.visible = false
pass # Replace with function body.

View File

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

View File

@@ -1,152 +0,0 @@
[gd_scene load_steps=21 format=3 uid="uid://bdlg5orah64m5"]
[ext_resource type="Script" uid="uid://bj0ueurl3vovc" path="res://scripts/entities/world/pot.gd" id="1_hsjxb"]
[ext_resource type="Texture2D" uid="uid://bu4dq78f8lgj5" path="res://assets/gfx/sheet_18.png" id="1_rxnv2"]
[ext_resource type="AudioStream" uid="uid://fl0rfi4in3n4" path="res://assets/audio/sfx/environment/pot/Drunk lad destroys plant pot.mp3" id="3_vktry"]
[ext_resource type="AudioStream" uid="uid://dejjc0uqthi1b" path="res://assets/audio/sfx/environment/pot/pot_destroy_sound1.mp3" id="4_nb533"]
[ext_resource type="AudioStream" uid="uid://iuxunaogc8xr" path="res://assets/audio/sfx/environment/pot/pot_destroy_sound2.mp3" id="5_cmff4"]
[ext_resource type="AudioStream" uid="uid://bfqusej0pbxem" path="res://assets/audio/sfx/environment/pot/pot_destroy_sound3.mp3" id="6_lq20m"]
[ext_resource type="AudioStream" uid="uid://dq461vpiih3lc" path="res://assets/audio/sfx/environment/pot/pot_destroy_sound4.mp3" id="7_76fyq"]
[ext_resource type="AudioStream" uid="uid://cg1ndvx4t7xtd" path="res://assets/audio/sfx/environment/pot/pot_destroy_sound5.mp3" id="8_m11t2"]
[ext_resource type="AudioStream" uid="uid://bt5npaenq15h2" path="res://assets/audio/sfx/environment/pot/smaller_pot_crash.mp3" id="9_sb38x"]
[ext_resource type="Texture2D" uid="uid://b1twy68vd7f20" path="res://assets/gfx/pickups/indicator.png" id="10_nb533"]
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_hsjxb"]
properties/0/path = NodePath(".:position")
properties/0/spawn = true
properties/0/replication_mode = 2
[sub_resource type="Gradient" id="Gradient_nb533"]
offsets = PackedFloat32Array(0.847255, 0.861575)
colors = PackedColorArray(0, 0, 0, 0.764706, 0, 0, 0, 0)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_87nuj"]
gradient = SubResource("Gradient_nb533")
width = 16
height = 6
fill = 1
fill_from = Vector2(0.504274, 0.478632)
fill_to = Vector2(0.897436, 0.0769231)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_hsjxb"]
size = Vector2(12, 8)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_87nuj"]
size = Vector2(18, 15)
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_ui3li"]
streams_count = 7
stream_0/stream = ExtResource("3_vktry")
stream_1/stream = ExtResource("4_nb533")
stream_2/stream = ExtResource("5_cmff4")
stream_3/stream = ExtResource("6_lq20m")
stream_4/stream = ExtResource("7_76fyq")
stream_5/stream = ExtResource("8_m11t2")
stream_6/stream = ExtResource("9_sb38x")
[sub_resource type="Animation" id="Animation_cmff4"]
resource_name = "indicate"
length = 0.8
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:offset")
tracks/0/interp = 2
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.4, 0.8),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Vector2(0, 0), Vector2(0, -1), Vector2(0, 0)]
}
[sub_resource type="Animation" id="Animation_lq20m"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:offset")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(0, 0)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_76fyq"]
_data = {
&"RESET": SubResource("Animation_lq20m"),
&"indicate": SubResource("Animation_cmff4")
}
[sub_resource type="RectangleShape2D" id="RectangleShape2D_nb533"]
size = Vector2(14, 9)
[node name="Pot" type="CharacterBody2D"]
collision_layer = 128
collision_mask = 64
script = ExtResource("1_hsjxb")
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_hsjxb")
[node name="Sprite2DShadow" type="Sprite2D" parent="."]
position = Vector2(0, 3)
texture = SubResource("GradientTexture2D_87nuj")
[node name="Sprite2D" type="Sprite2D" parent="."]
position = Vector2(0, -4)
texture = ExtResource("1_rxnv2")
hframes = 19
vframes = 19
frame = 14
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, -1)
shape = SubResource("RectangleShape2D_hsjxb")
[node name="Area2DPickup" type="Area2D" parent="."]
collision_layer = 1024
collision_mask = 512
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DPickup"]
position = Vector2(0, -1)
shape = SubResource("RectangleShape2D_87nuj")
debug_color = Color(0.688142, 0.7, 0.0440007, 0.42)
[node name="SfxShatter" type="AudioStreamPlayer2D" parent="."]
stream = SubResource("AudioStreamRandomizer_ui3li")
attenuation = 9.84915
panning_strength = 1.46
bus = &"Sfx"
[node name="SfxThrow" type="AudioStreamPlayer2D" parent="."]
[node name="SfxDrop" type="AudioStreamPlayer2D" parent="."]
[node name="Indicator" type="Sprite2D" parent="."]
position = Vector2(0, -11)
texture = ExtResource("10_nb533")
[node name="AnimationPlayer" type="AnimationPlayer" parent="Indicator"]
libraries = {
&"": SubResource("AnimationLibrary_76fyq")
}
autoplay = "indicate"
[node name="Area2DCollision" type="Area2D" parent="."]
collision_layer = 1024
collision_mask = 704
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DCollision"]
position = Vector2(0, -1)
shape = SubResource("RectangleShape2D_nb533")
debug_color = Color(0.7, 0.132592, 0.232379, 0.42)
[connection signal="body_entered" from="Area2DPickup" to="." method="_on_area_2d_pickup_body_entered"]
[connection signal="body_exited" from="Area2DPickup" to="." method="_on_area_2d_pickup_body_exited"]
[connection signal="body_entered" from="Area2DCollision" to="." method="_on_area_2d_collision_body_entered"]
[connection signal="body_exited" from="Area2DCollision" to="." method="_on_area_2d_collision_body_exited"]

View File

@@ -0,0 +1,56 @@
extends Control
# Store the current joystick input value
var virtual_joystick_input: Vector2 = Vector2.ZERO
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
_update_visibility()
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta: float) -> void:
pass
func _update_visibility() -> void:
# Check if touchscreen is available
var has_touchscreen = DisplayServer.is_touchscreen_available()
# Check if running on mobile platform
var os_name = OS.get_name().to_lower()
var is_mobile_os = os_name in ["android", "ios"]
# Show mobile input if touchscreen is available OR if on mobile OS
var should_show = has_touchscreen or is_mobile_os
visible = should_show
# Debug output (optional, can be removed)
if Engine.is_editor_hint():
return
print("MobileInput visibility: ", should_show, " (touchscreen: ", has_touchscreen, ", mobile OS: ", is_mobile_os, ", OS: ", os_name, ")")
func _on_virtual_joystick_analogic_changed(value: Vector2, _distance: float, _angle: float, _angle_clockwise: float, _angle_not_clockwise: float) -> void:
# Store the joystick input value
# The value is already normalized (0.0 to 1.0) from the joystick
virtual_joystick_input = value
# Update all local players with the joystick input
_update_player_input()
func _update_player_input():
# Find all local players and set their virtual joystick input
var game_world = get_tree().get_first_node_in_group("game_world")
if not game_world:
return
var player_manager = game_world.get_node_or_null("PlayerManager")
if not player_manager:
return
# Get all local players
var local_players = player_manager.get_local_players()
for player in local_players:
if player and is_instance_valid(player):
# Set the virtual joystick input on the player
player.virtual_joystick_input = virtual_joystick_input

View File

@@ -0,0 +1 @@
uid://5hepk3l8u2eg

View File

@@ -22,6 +22,7 @@ var teleported_this_frame: bool = false # Flag to prevent position sync from ove
# Input device (for local multiplayer)
var input_device: int = -1 # -1 for keyboard, 0+ for gamepad index
var virtual_joystick_input: Vector2 = Vector2.ZERO # Virtual joystick input from mobile controls
# Interaction
var held_object = null
@@ -271,9 +272,8 @@ func _ready():
# Set up cone light blend mode, texture, initial rotation, and spread
if cone_light:
_create_cone_light_texture()
_update_cone_light_rotation()
_update_cone_light_spread()
_update_cone_light_spread() # This calls _create_cone_light_texture()
# Wait before allowing RPCs to ensure player is fully spawned on all clients
# This prevents "Node not found" errors when RPCs try to resolve node paths
@@ -1056,10 +1056,26 @@ func _physics_process(delta):
func _handle_input():
var input_vector = Vector2.ZERO
if input_device == -1:
# Check for virtual joystick input first (mobile/touchscreen)
if virtual_joystick_input.length() > 0.01:
input_vector = virtual_joystick_input
elif input_device == -1:
# Keyboard input
input_vector.x = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
input_vector.y = Input.get_action_strength("move_down") - Input.get_action_strength("move_up")
input_vector.x = max(
Input.get_action_strength("move_right"),
Input.get_action_strength("ui_right")
) - max(
Input.get_action_strength("move_left"),
Input.get_action_strength("ui_left")
)
input_vector.y = max(
Input.get_action_strength("move_down"),
Input.get_action_strength("ui_down")
) - max(
Input.get_action_strength("move_up"),
Input.get_action_strength("ui_up")
)
else:
# Gamepad input
input_vector.x = Input.get_joy_axis(input_device, JOY_AXIS_LEFT_X)
@@ -2252,8 +2268,18 @@ func _handle_struggle(delta):
var input_dir = Vector2.ZERO
if input_device == -1: # Keyboard
input_dir.x = Input.get_axis("move_left", "move_right")
input_dir.y = Input.get_axis("move_up", "move_down")
input_dir.x = clamp(
Input.get_axis("move_left", "move_right")
+ Input.get_axis("ui_left", "ui_right"),
-1.0,
1.0
)
input_dir.y = clamp(
Input.get_axis("move_up", "move_down")
+ Input.get_axis("ui_up", "ui_down"),
-1.0,
1.0
)
else: # Gamepad
input_dir.x = Input.get_joy_axis(input_device, JOY_AXIS_LEFT_X)
input_dir.y = Input.get_joy_axis(input_device, JOY_AXIS_LEFT_Y)

View File

@@ -1,259 +0,0 @@
extends Node2D
# Room Lighting System
# Manages per-room darkness and fog of war based on player lights and torch count
@onready var game_world = get_tree().get_first_node_in_group("game_world")
# Room lighting data
var room_lighting_data: Dictionary = {} # room_id -> {lit: bool, torch_count: int, darkness_level: float}
var room_darkness_overlays: Dictionary = {} # room_id -> ColorRect node
# Constants
const TILE_SIZE = 16 # Each tile is 16x16 pixels
const DARKNESS_COLOR = Color(0, 0, 0, 0.95) # Almost black, slightly transparent
const MIN_DARKNESS = 0.3 # Minimum darkness even with torches
const MAX_DARKNESS = 0.95 # Maximum darkness (no torches, unlit)
# Light detection
var light_check_timer: float = 0.0
const LIGHT_CHECK_INTERVAL = 0.1 # Check every 0.1 seconds
var darkness_layer: Node2D = null
func _ready():
# Create Node2D for darkness overlays (in world space, above game world)
darkness_layer = Node2D.new()
darkness_layer.name = "RoomDarknessLayer"
darkness_layer.z_index = 100 # High z-index to be above game world
add_child(darkness_layer)
# Wait for dungeon to be generated
call_deferred("_initialize_room_lighting")
func _initialize_room_lighting():
# Wait for dungeon data to be available
if not game_world or game_world.dungeon_data.is_empty():
await get_tree().process_frame
call_deferred("_initialize_room_lighting")
return
var dungeon_data = game_world.dungeon_data
if not dungeon_data.has("rooms") or not dungeon_data.has("torches"):
print("RoomLightingSystem: Dungeon data not ready yet")
await get_tree().process_frame
call_deferred("_initialize_room_lighting")
return
# Clear old room lighting data and overlays when reinitializing
room_lighting_data.clear()
if darkness_layer:
for child in darkness_layer.get_children():
child.queue_free()
room_darkness_overlays.clear()
# Count torches per room
var torch_counts: Dictionary = {} # room_id -> count
var rooms = dungeon_data.rooms
var torches = dungeon_data.torches
# Initialize all rooms as unlit
for i in range(rooms.size()):
var room = rooms[i]
var room_id = _get_room_id(room)
torch_counts[room_id] = 0
room_lighting_data[room_id] = {
"lit": false,
"torch_count": 0,
"darkness_level": MAX_DARKNESS
}
# Count torches in each room
for torch_data in torches:
var torch_pos = torch_data.position
# Find which room this torch belongs to
for i in range(rooms.size()):
var room = rooms[i]
if _is_position_in_room(torch_pos, room):
var room_id = _get_room_id(room)
torch_counts[room_id] = torch_counts.get(room_id, 0) + 1
break
# Update room lighting data with torch counts
for room_id in torch_counts:
var torch_count = torch_counts[room_id]
room_lighting_data[room_id].torch_count = torch_count
# Calculate darkness level based on torch count (0-4 torches)
# More torches = less darkness
var darkness = MAX_DARKNESS - (torch_count * 0.15) # Each torch reduces darkness by 0.15
darkness = clamp(darkness, MIN_DARKNESS, MAX_DARKNESS)
room_lighting_data[room_id].darkness_level = darkness
# Create darkness overlays for all rooms (initially all dark)
_create_darkness_overlays()
print("RoomLightingSystem: Initialized ", rooms.size(), " rooms with lighting data")
# Public method to reinitialize lighting (called when new level is generated)
func reinitialize():
call_deferred("_initialize_room_lighting")
func _get_room_id(room: Dictionary) -> String:
# Create unique ID from room position and size
return "%d_%d_%d_%d" % [room.x, room.y, room.w, room.h]
func _is_position_in_room(pos: Vector2, room: Dictionary) -> bool:
# Convert room tile coordinates to world coordinates
var room_world_x = room.x * TILE_SIZE
var room_world_y = room.y * TILE_SIZE
var room_world_w = room.w * TILE_SIZE
var room_world_h = room.h * TILE_SIZE
# Check if position is within room bounds (including walls)
return pos.x >= room_world_x and pos.x < room_world_x + room_world_w and \
pos.y >= room_world_y and pos.y < room_world_y + room_world_h
func _create_darkness_overlays():
if not darkness_layer:
push_error("RoomLightingSystem: Darkness layer not found!")
return
if not game_world or game_world.dungeon_data.is_empty():
return
var rooms = game_world.dungeon_data.rooms
# Create darkness overlay for each room
for i in range(rooms.size()):
var room = rooms[i]
var room_id = _get_room_id(room)
# Create ColorRect for darkness overlay
var overlay = ColorRect.new()
overlay.name = "Darkness_%s" % room_id
# Set position and size (in world coordinates)
var room_world_x = room.x * TILE_SIZE
var room_world_y = room.y * TILE_SIZE
var room_world_w = room.w * TILE_SIZE
var room_world_h = room.h * TILE_SIZE
overlay.position = Vector2(room_world_x, room_world_y)
overlay.size = Vector2(room_world_w, room_world_h)
# Set darkness color based on torch count
var lighting_data = room_lighting_data.get(room_id, {})
var darkness_level = lighting_data.get("darkness_level", MAX_DARKNESS)
var is_lit = lighting_data.get("lit", false)
# If room is lit, make it transparent (no darkness)
# Otherwise, apply darkness based on torch count
if is_lit:
overlay.color = Color(0, 0, 0, 0) # Transparent (lit)
else:
overlay.color = Color(0, 0, 0, darkness_level) # Dark (unlit)
darkness_layer.add_child(overlay)
room_darkness_overlays[room_id] = overlay
func _process(delta):
light_check_timer += delta
if light_check_timer >= LIGHT_CHECK_INTERVAL:
light_check_timer = 0.0
_check_player_lights()
func _check_player_lights():
if not game_world or game_world.dungeon_data.is_empty():
return
var rooms = game_world.dungeon_data.rooms
var players = get_tree().get_nodes_in_group("player")
# Check each room against each player's lights
for room in rooms:
var room_id = _get_room_id(room)
var was_lit = room_lighting_data[room_id].lit
# Check if any player's light intersects this room
var is_lit_now = false
for player in players:
if _player_light_intersects_room(player, room):
is_lit_now = true
break
# Update lighting state
if is_lit_now and not was_lit:
# Room just became lit
room_lighting_data[room_id].lit = true
_update_room_darkness(room_id)
elif not is_lit_now and was_lit:
# Room became unlit (shouldn't happen, but handle it)
# Actually, we keep rooms lit once they've been seen
pass
func _player_light_intersects_room(player: Node2D, room: Dictionary) -> bool:
# Check if player's cone light or point light intersects the room
var player_pos = player.global_position
# Get room bounds in world coordinates
var room_world_x = room.x * TILE_SIZE
var room_world_y = room.y * TILE_SIZE
var room_world_w = room.w * TILE_SIZE
var room_world_h = room.h * TILE_SIZE
var room_rect = Rect2(room_world_x, room_world_y, room_world_w, room_world_h)
# Check cone light (PointLight2D named "ConeLight")
var cone_light = player.get_node_or_null("ConeLight")
if cone_light:
# Get light range from texture or use default
# Cone light texture is 256x256, so range is approximately 128 pixels
var light_range = 128.0 # Approximate range of cone light
var light_pos = cone_light.global_position
# Check if light circle intersects room rectangle
if _circle_intersects_rect(light_pos, light_range, room_rect):
return true
# Check point light (PointLight2D) - even if not visible, it might be used
var point_light = player.get_node_or_null("PointLight2D")
if point_light:
# Get light range from texture or use default
# Point light has a gradient texture, estimate range
var light_range = 64.0 # Approximate range of point light
var light_pos = point_light.global_position
# Check if light circle intersects room rectangle
if _circle_intersects_rect(light_pos, light_range, room_rect):
return true
# Also check if player is inside the room (they can see it)
if room_rect.has_point(player_pos):
return true
return false
func _circle_intersects_rect(circle_center: Vector2, circle_radius: float, rect: Rect2) -> bool:
# Find the closest point on the rectangle to the circle center
var closest_x = clamp(circle_center.x, rect.position.x, rect.position.x + rect.size.x)
var closest_y = clamp(circle_center.y, rect.position.y, rect.position.y + rect.size.y)
var closest_point = Vector2(closest_x, closest_y)
# Check if the closest point is within the circle
var distance = circle_center.distance_to(closest_point)
return distance <= circle_radius
func _update_room_darkness(room_id: String):
var overlay = room_darkness_overlays.get(room_id)
if not overlay:
return
var lighting_data = room_lighting_data.get(room_id, {})
var is_lit = lighting_data.get("lit", false)
var darkness_level = lighting_data.get("darkness_level", MAX_DARKNESS)
# If room is lit, make overlay transparent
# Otherwise, apply darkness based on torch count
if is_lit:
overlay.color = Color(0, 0, 0, 0) # Transparent (lit)
else:
overlay.color = Color(0, 0, 0, darkness_level) # Dark (unlit)