Added touchscreen controls!
135
src/addons/touchscreenbuttoncontrol/TouchScreenButtonControl.gd
Normal 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
|
||||
@@ -0,0 +1 @@
|
||||
uid://bh5a3ydiu51eo
|
||||
@@ -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 |
@@ -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
|
||||
@@ -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")
|
||||
@@ -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")
|
||||
@@ -0,0 +1 @@
|
||||
uid://cq0bml8epsqa
|
||||
13
src/addons/touchscreenbuttoncontrol/button_style.tres
Normal 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
|
||||
1
src/addons/touchscreenbuttoncontrol/icon.svg
Normal 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 |
43
src/addons/touchscreenbuttoncontrol/icon.svg.import
Normal 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
|
||||
7
src/addons/touchscreenbuttoncontrol/plugin.cfg
Normal file
@@ -0,0 +1,7 @@
|
||||
[plugin]
|
||||
|
||||
name="TouchScreenButtonControl"
|
||||
description="A Control Node version to TouchScreenButton2D"
|
||||
author="Matata.exe"
|
||||
version="1.0"
|
||||
script="TouchScreenButtonControlPlugin.gd"
|
||||
1
src/addons/virtual_joystick/icon.svg
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
43
src/addons/virtual_joystick/icon.svg.import
Normal 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
|
||||
8
src/addons/virtual_joystick/plugin.cfg
Normal 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"
|
||||
11
src/addons/virtual_joystick/plugin.gd
Normal 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")
|
||||
1
src/addons/virtual_joystick/plugin.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://e7m2yqefj838
|
||||
|
After Width: | Height: | Size: 58 KiB |
@@ -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
|
||||
|
After Width: | Height: | Size: 78 KiB |
@@ -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
|
||||
|
After Width: | Height: | Size: 7.8 KiB |
@@ -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
|
||||
|
After Width: | Height: | Size: 62 KiB |
@@ -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
|
||||
|
After Width: | Height: | Size: 8.4 KiB |
@@ -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
|
||||
|
After Width: | Height: | Size: 66 KiB |
@@ -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
|
||||
|
After Width: | Height: | Size: 24 KiB |
@@ -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
|
||||
|
After Width: | Height: | Size: 14 KiB |
@@ -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
|
||||
|
After Width: | Height: | Size: 16 KiB |
@@ -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
|
||||
|
After Width: | Height: | Size: 15 KiB |
@@ -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
|
||||
|
After Width: | Height: | Size: 16 KiB |
@@ -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
|
||||
|
After Width: | Height: | Size: 16 KiB |
@@ -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
|
||||
496
src/addons/virtual_joystick/virtual_joystick.gd
Normal 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 ===================================================
|
||||
1
src/addons/virtual_joystick/virtual_joystick.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dhn1uax7qtt1v
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
@@ -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"
|
||||
@@ -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:
|
||||
@@ -72,6 +72,23 @@ func _input(event):
|
||||
_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
|
||||
chat_input.visible = 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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -1 +0,0 @@
|
||||
uid://dxkd5t8jbbmdm
|
||||
@@ -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": []
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
uid://dj0n3aevweyhu
|
||||
@@ -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.
|
||||
@@ -1 +0,0 @@
|
||||
uid://20kfmxrtt20e
|
||||
@@ -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"]
|
||||
@@ -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")
|
||||
@@ -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.
|
||||
@@ -1 +0,0 @@
|
||||
uid://bawxh5vhj4ii3
|
||||
@@ -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"]
|
||||
56
src/scripts/mobile_input.gd
Normal 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
|
||||
1
src/scripts/mobile_input.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://5hepk3l8u2eg
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||