- Escape Menu: - Opens with Escape key from base game screen - Resume button to return to game - Exit Game button to quit application - Character sheet closes with Escape if open (takes priority) - Mouse capture/release handled by UI components - Weapon Slot System: - Visual weapon boxes (80x80) in character sheet - Display weapon icons from WeaponData - Empty slots appear dimmed - Hover tooltips show weapon stats (not clipped by containers) - Tooltips display: slot name, weapon name, damage, range, cooldown, knockback, block percentage - Tooltips positioned globally to avoid ScrollContainer clipping - Bug Fixes: - Fixed typo in lilguy_body.gd (dwextends -> extends) - Removed manual mouse toggle from player (now handled by UI) - Updated character_sheet.gd to use weapon slot components instead of text labels - Added weapon_tooltip.tscn as separate scene for unclipped tooltipsDashfix
parent
15865dd15f
commit
aba42e2a02
10 changed files with 382 additions and 37 deletions
@ -0,0 +1,106 @@ |
|||||||
|
[gd_scene load_steps=4 format=3 uid="uid://cepm3qkjr8h1h"] |
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://level/ui/scripts/escape_menu.gd" id="1_script"] |
||||||
|
[ext_resource type="Theme" uid="uid://dvsh7tuhulnfm" path="res://level/ui/theme/wow_style.tres" id="2_theme"] |
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_menu"] |
||||||
|
bg_color = Color(0.12, 0.1, 0.08, 0.95) |
||||||
|
border_width_left = 4 |
||||||
|
border_width_top = 4 |
||||||
|
border_width_right = 4 |
||||||
|
border_width_bottom = 4 |
||||||
|
border_color = Color(0.6, 0.5, 0.2, 1) |
||||||
|
corner_radius_top_left = 8 |
||||||
|
corner_radius_top_right = 8 |
||||||
|
corner_radius_bottom_right = 8 |
||||||
|
corner_radius_bottom_left = 8 |
||||||
|
|
||||||
|
[node name="EscapeMenu" type="Control"] |
||||||
|
layout_mode = 3 |
||||||
|
anchors_preset = 15 |
||||||
|
anchor_right = 1.0 |
||||||
|
anchor_bottom = 1.0 |
||||||
|
grow_horizontal = 2 |
||||||
|
grow_vertical = 2 |
||||||
|
theme = ExtResource("2_theme") |
||||||
|
script = ExtResource("1_script") |
||||||
|
|
||||||
|
[node name="DarkBackground" type="ColorRect" parent="."] |
||||||
|
layout_mode = 1 |
||||||
|
anchors_preset = 15 |
||||||
|
anchor_right = 1.0 |
||||||
|
anchor_bottom = 1.0 |
||||||
|
grow_horizontal = 2 |
||||||
|
grow_vertical = 2 |
||||||
|
color = Color(0, 0, 0, 0.7) |
||||||
|
|
||||||
|
[node name="Panel" type="PanelContainer" parent="."] |
||||||
|
layout_mode = 1 |
||||||
|
anchors_preset = 8 |
||||||
|
anchor_left = 0.5 |
||||||
|
anchor_top = 0.5 |
||||||
|
anchor_right = 0.5 |
||||||
|
anchor_bottom = 0.5 |
||||||
|
offset_left = -200.0 |
||||||
|
offset_top = -150.0 |
||||||
|
offset_right = 200.0 |
||||||
|
offset_bottom = 150.0 |
||||||
|
grow_horizontal = 2 |
||||||
|
grow_vertical = 2 |
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_menu") |
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="Panel"] |
||||||
|
layout_mode = 2 |
||||||
|
theme_override_constants/margin_left = 30 |
||||||
|
theme_override_constants/margin_top = 30 |
||||||
|
theme_override_constants/margin_right = 30 |
||||||
|
theme_override_constants/margin_bottom = 30 |
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="Panel/MarginContainer"] |
||||||
|
layout_mode = 2 |
||||||
|
theme_override_constants/separation = 20 |
||||||
|
|
||||||
|
[node name="TitleLabel" type="Label" parent="Panel/MarginContainer/VBoxContainer"] |
||||||
|
layout_mode = 2 |
||||||
|
theme_override_colors/font_color = Color(1, 0.8, 0, 1) |
||||||
|
theme_override_colors/font_outline_color = Color(0, 0, 0, 1) |
||||||
|
theme_override_constants/outline_size = 3 |
||||||
|
theme_override_font_sizes/font_size = 32 |
||||||
|
text = "MENU" |
||||||
|
horizontal_alignment = 1 |
||||||
|
|
||||||
|
[node name="Spacer" type="Control" parent="Panel/MarginContainer/VBoxContainer"] |
||||||
|
custom_minimum_size = Vector2(0, 20) |
||||||
|
layout_mode = 2 |
||||||
|
|
||||||
|
[node name="ResumeButton" type="Button" parent="Panel/MarginContainer/VBoxContainer"] |
||||||
|
custom_minimum_size = Vector2(0, 50) |
||||||
|
layout_mode = 2 |
||||||
|
theme_override_colors/font_color = Color(1, 1, 1, 1) |
||||||
|
theme_override_colors/font_hover_color = Color(1, 0.8, 0, 1) |
||||||
|
theme_override_font_sizes/font_size = 20 |
||||||
|
text = "Resume" |
||||||
|
|
||||||
|
[node name="ExitButton" type="Button" parent="Panel/MarginContainer/VBoxContainer"] |
||||||
|
custom_minimum_size = Vector2(0, 50) |
||||||
|
layout_mode = 2 |
||||||
|
theme_override_colors/font_color = Color(1, 1, 1, 1) |
||||||
|
theme_override_colors/font_hover_color = Color(1, 0.8, 0, 1) |
||||||
|
theme_override_font_sizes/font_size = 20 |
||||||
|
text = "Exit Game" |
||||||
|
|
||||||
|
[node name="Spacer2" type="Control" parent="Panel/MarginContainer/VBoxContainer"] |
||||||
|
custom_minimum_size = Vector2(0, 10) |
||||||
|
layout_mode = 2 |
||||||
|
|
||||||
|
[node name="HintLabel" type="Label" parent="Panel/MarginContainer/VBoxContainer"] |
||||||
|
layout_mode = 2 |
||||||
|
theme_override_colors/font_color = Color(0.7, 0.7, 0.7, 1) |
||||||
|
theme_override_colors/font_outline_color = Color(0, 0, 0, 1) |
||||||
|
theme_override_constants/outline_size = 1 |
||||||
|
theme_override_font_sizes/font_size = 14 |
||||||
|
text = "Press ESC to close" |
||||||
|
horizontal_alignment = 1 |
||||||
|
|
||||||
|
[connection signal="pressed" from="Panel/MarginContainer/VBoxContainer/ResumeButton" to="." method="_on_resume_pressed"] |
||||||
|
[connection signal="pressed" from="Panel/MarginContainer/VBoxContainer/ExitButton" to="." method="_on_exit_pressed"] |
||||||
@ -0,0 +1,44 @@ |
|||||||
|
[gd_scene load_steps=4 format=3 uid="uid://dnwg8b7xmh5qa"] |
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://level/ui/scripts/weapon_slot.gd" id="1_script"] |
||||||
|
[ext_resource type="Theme" uid="uid://dvsh7tuhulnfm" path="res://level/ui/theme/wow_style.tres" id="2_theme"] |
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_slot"] |
||||||
|
bg_color = Color(0.15, 0.15, 0.15, 0.9) |
||||||
|
border_width_left = 2 |
||||||
|
border_width_top = 2 |
||||||
|
border_width_right = 2 |
||||||
|
border_width_bottom = 2 |
||||||
|
border_color = Color(0.6, 0.5, 0.2, 1) |
||||||
|
corner_radius_top_left = 4 |
||||||
|
corner_radius_top_right = 4 |
||||||
|
corner_radius_bottom_right = 4 |
||||||
|
corner_radius_bottom_left = 4 |
||||||
|
|
||||||
|
[node name="WeaponSlot" type="Control"] |
||||||
|
custom_minimum_size = Vector2(80, 80) |
||||||
|
mouse_filter = 0 |
||||||
|
theme = ExtResource("2_theme") |
||||||
|
script = ExtResource("1_script") |
||||||
|
|
||||||
|
[node name="SlotPanel" type="PanelContainer" parent="."] |
||||||
|
layout_mode = 1 |
||||||
|
anchors_preset = 15 |
||||||
|
anchor_right = 1.0 |
||||||
|
anchor_bottom = 1.0 |
||||||
|
grow_horizontal = 2 |
||||||
|
grow_vertical = 2 |
||||||
|
mouse_filter = 2 |
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_slot") |
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="SlotPanel"] |
||||||
|
layout_mode = 2 |
||||||
|
theme_override_constants/margin_left = 4 |
||||||
|
theme_override_constants/margin_top = 4 |
||||||
|
theme_override_constants/margin_right = 4 |
||||||
|
theme_override_constants/margin_bottom = 4 |
||||||
|
|
||||||
|
[node name="IconRect" type="TextureRect" parent="SlotPanel/MarginContainer"] |
||||||
|
layout_mode = 2 |
||||||
|
expand_mode = 1 |
||||||
|
stretch_mode = 5 |
||||||
@ -0,0 +1,44 @@ |
|||||||
|
[gd_scene load_steps=3 format=3 uid="uid://ck5y3rmj8vx2p"] |
||||||
|
|
||||||
|
[ext_resource type="Theme" uid="uid://dvsh7tuhulnfm" path="res://level/ui/theme/wow_style.tres" id="1_theme"] |
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_tooltip"] |
||||||
|
bg_color = Color(0.15, 0.15, 0.15, 0.95) |
||||||
|
border_width_left = 2 |
||||||
|
border_width_top = 2 |
||||||
|
border_width_right = 2 |
||||||
|
border_width_bottom = 2 |
||||||
|
border_color = Color(0.6, 0.5, 0.2, 1) |
||||||
|
corner_radius_top_left = 4 |
||||||
|
corner_radius_top_right = 4 |
||||||
|
corner_radius_bottom_right = 4 |
||||||
|
corner_radius_bottom_left = 4 |
||||||
|
|
||||||
|
[node name="WeaponTooltip" type="PanelContainer"] |
||||||
|
z_index = 1000 |
||||||
|
offset_right = 200.0 |
||||||
|
offset_bottom = 150.0 |
||||||
|
theme = ExtResource("1_theme") |
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_tooltip") |
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="."] |
||||||
|
layout_mode = 2 |
||||||
|
theme_override_constants/margin_left = 8 |
||||||
|
theme_override_constants/margin_top = 8 |
||||||
|
theme_override_constants/margin_right = 8 |
||||||
|
theme_override_constants/margin_bottom = 8 |
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"] |
||||||
|
layout_mode = 2 |
||||||
|
|
||||||
|
[node name="StatsLabel" type="Label" parent="MarginContainer/VBoxContainer"] |
||||||
|
layout_mode = 2 |
||||||
|
theme_override_colors/font_color = Color(1, 1, 1, 1) |
||||||
|
theme_override_colors/font_outline_color = Color(0, 0, 0, 1) |
||||||
|
theme_override_constants/outline_size = 1 |
||||||
|
theme_override_font_sizes/font_size = 14 |
||||||
|
text = "Weapon Name |
||||||
|
--- |
||||||
|
Damage: 10 |
||||||
|
Range: 3 |
||||||
|
Cooldown: 0.5s" |
||||||
@ -0,0 +1,46 @@ |
|||||||
|
extends Control |
||||||
|
class_name EscapeMenu |
||||||
|
## Escape menu that opens when Escape is pressed |
||||||
|
## Allows player to exit the game or resume playing |
||||||
|
|
||||||
|
# Visibility |
||||||
|
var is_visible: bool = false |
||||||
|
|
||||||
|
# Player reference (to control mouse mode) |
||||||
|
var player: Character = null |
||||||
|
|
||||||
|
func _ready(): |
||||||
|
# Start hidden |
||||||
|
hide() |
||||||
|
is_visible = false |
||||||
|
|
||||||
|
func _input(event): |
||||||
|
# Toggle on Escape press |
||||||
|
if event.is_action_pressed("quit"): |
||||||
|
toggle_menu() |
||||||
|
get_viewport().set_input_as_handled() |
||||||
|
|
||||||
|
## Set the player reference |
||||||
|
func set_player(p: Character): |
||||||
|
player = p |
||||||
|
|
||||||
|
## Toggle menu visibility |
||||||
|
func toggle_menu(): |
||||||
|
is_visible = !is_visible |
||||||
|
if is_visible: |
||||||
|
show() |
||||||
|
# Release mouse when opening menu |
||||||
|
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE |
||||||
|
else: |
||||||
|
hide() |
||||||
|
# Recapture mouse when closing menu |
||||||
|
if player and player.is_multiplayer_authority(): |
||||||
|
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED |
||||||
|
|
||||||
|
## Called when Resume button is clicked |
||||||
|
func _on_resume_pressed(): |
||||||
|
toggle_menu() |
||||||
|
|
||||||
|
## Called when Exit button is clicked |
||||||
|
func _on_exit_pressed(): |
||||||
|
get_tree().quit() |
||||||
@ -0,0 +1 @@ |
|||||||
|
uid://brfqjw57ypd3g |
||||||
@ -0,0 +1,98 @@ |
|||||||
|
extends Control |
||||||
|
class_name WeaponSlot |
||||||
|
## Weapon slot that displays weapon icon and shows tooltip on hover |
||||||
|
|
||||||
|
# References |
||||||
|
@onready var icon_rect: TextureRect = $SlotPanel/MarginContainer/IconRect |
||||||
|
var tooltip: PanelContainer = null |
||||||
|
|
||||||
|
# Weapon data |
||||||
|
var weapon_data: WeaponData = null |
||||||
|
var slot_name: String = "Main Hand" |
||||||
|
|
||||||
|
func _ready(): |
||||||
|
# Create tooltip as a top-level CanvasLayer child so it's not clipped |
||||||
|
_create_tooltip() |
||||||
|
|
||||||
|
# Connect mouse events |
||||||
|
mouse_entered.connect(_on_mouse_entered) |
||||||
|
mouse_exited.connect(_on_mouse_exited) |
||||||
|
|
||||||
|
## Create tooltip as a top-level node to avoid clipping |
||||||
|
func _create_tooltip(): |
||||||
|
# Load tooltip scene template |
||||||
|
var tooltip_scene = load("res://level/ui/scenes/weapon_tooltip.tscn") |
||||||
|
if tooltip_scene: |
||||||
|
tooltip = tooltip_scene.instantiate() |
||||||
|
# Add to the root CanvasLayer (HUD) so it's not clipped |
||||||
|
var hud = get_node_or_null("/root/HUD") |
||||||
|
if hud: |
||||||
|
hud.add_child(tooltip) |
||||||
|
tooltip.hide() |
||||||
|
else: |
||||||
|
push_error("[WeaponSlot] Could not find HUD node") |
||||||
|
else: |
||||||
|
push_error("[WeaponSlot] Failed to load weapon_tooltip.tscn") |
||||||
|
|
||||||
|
## Set weapon data and update display |
||||||
|
func set_weapon(data: WeaponData, name: String = "Main Hand"): |
||||||
|
weapon_data = data |
||||||
|
slot_name = name |
||||||
|
_update_display() |
||||||
|
|
||||||
|
## Clear the weapon slot |
||||||
|
func clear_weapon(): |
||||||
|
weapon_data = null |
||||||
|
_update_display() |
||||||
|
|
||||||
|
## Update the icon display |
||||||
|
func _update_display(): |
||||||
|
if not icon_rect: |
||||||
|
return |
||||||
|
|
||||||
|
if weapon_data and weapon_data.icon: |
||||||
|
icon_rect.texture = weapon_data.icon |
||||||
|
icon_rect.modulate = Color.WHITE |
||||||
|
else: |
||||||
|
icon_rect.texture = null |
||||||
|
icon_rect.modulate = Color(0.3, 0.3, 0.3, 0.5) # Dim empty slot |
||||||
|
|
||||||
|
## Show tooltip on mouse enter |
||||||
|
func _on_mouse_entered(): |
||||||
|
if weapon_data and tooltip: |
||||||
|
_update_tooltip() |
||||||
|
# Position tooltip to the right of the slot |
||||||
|
var global_pos = global_position |
||||||
|
tooltip.position = Vector2(global_pos.x + size.x + 10, global_pos.y) |
||||||
|
tooltip.show() |
||||||
|
|
||||||
|
## Hide tooltip on mouse exit |
||||||
|
func _on_mouse_exited(): |
||||||
|
if tooltip: |
||||||
|
tooltip.hide() |
||||||
|
|
||||||
|
## Update tooltip content |
||||||
|
func _update_tooltip(): |
||||||
|
if not tooltip or not weapon_data: |
||||||
|
return |
||||||
|
|
||||||
|
var tooltip_label = tooltip.get_node_or_null("MarginContainer/VBoxContainer/StatsLabel") |
||||||
|
if not tooltip_label: |
||||||
|
return |
||||||
|
|
||||||
|
var text = "" |
||||||
|
text += slot_name.to_upper() + "\n" |
||||||
|
text += weapon_data.weapon_name + "\n" |
||||||
|
text += "---\n" |
||||||
|
text += "Damage: " + str(weapon_data.damage) + "\n" |
||||||
|
text += "Range: " + str(weapon_data.attack_range) + "\n" |
||||||
|
text += "Cooldown: " + str(weapon_data.attack_cooldown) + "s\n" |
||||||
|
text += "Knockback: " + str(weapon_data.knockback_force) + "\n" |
||||||
|
|
||||||
|
if weapon_data.can_block: |
||||||
|
text += "Block: " + str(int(weapon_data.block_reduction * 100)) + "%\n" |
||||||
|
|
||||||
|
if weapon_data.description: |
||||||
|
text += "\n" + weapon_data.description |
||||||
|
|
||||||
|
tooltip_label.text = text |
||||||
@ -0,0 +1 @@ |
|||||||
|
uid://ev146dh8du3y |
||||||
Loading…
Reference in new issue