Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pause={
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
enter={
accept={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194309,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
Expand All @@ -85,7 +85,12 @@ god={
}
skip={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)
]
}
close_tutorial={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194309,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
debug_open_portal={
Expand Down
15 changes: 14 additions & 1 deletion scenes/game/tutorial_dialogue_balloon.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ MarginContainer/constants/margin_top = 15
PanelContainer/styles/panel = SubResource("StyleBoxFlat_qkmqt")

[node name="TutorialDialogueBalloon" type="CanvasLayer"]
layer = 100
layer = 10
script = ExtResource("1_ekbxt")

[node name="Balloon" type="Control" parent="."]
Expand Down Expand Up @@ -144,5 +144,18 @@ visible = false
layout_mode = 2
text = "Response example"

[node name="CloseTutorialButton" type="Button" parent="Balloon"]
layout_mode = 0
offset_left = 760.0
offset_top = 495.0
offset_right = 1032.0
offset_bottom = 529.0
size_flags_horizontal = 8
size_flags_vertical = 0
focus_mode = 0
text = "Press Enter to close tutorial"
flat = true

[connection signal="gui_input" from="Balloon" to="." method="_on_balloon_gui_input"]
[connection signal="response_selected" from="Balloon/ResponsesMenu" to="." method="_on_responses_menu_response_selected"]
[connection signal="pressed" from="Balloon/CloseTutorialButton" to="." method="_on_close_tutorial_button_pressed"]
6 changes: 5 additions & 1 deletion scenes/globals/gui_manager.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ text = "Back"
flat = true

[node name="SettingsMenu" type="CanvasLayer" parent="."]
layer = 60
visible = false

[node name="TextureRect" type="TextureRect" parent="SettingsMenu"]
Expand Down Expand Up @@ -570,6 +571,7 @@ vertical_alignment = 1
visible = false

[node name="InputSettings" type="CanvasLayer" parent="."]
layer = 60
visible = false

[node name="Control" type="Control" parent="InputSettings"]
Expand Down Expand Up @@ -601,7 +603,7 @@ anchor_bottom = 0.5
offset_left = -283.0
offset_top = -196.0
offset_right = 243.0
offset_bottom = 157.0
offset_bottom = 204.0
grow_horizontal = 2
grow_vertical = 2
focus_neighbor_top = NodePath("MarginContainer/VBoxContainer/BackToSettingsButton")
Expand Down Expand Up @@ -723,6 +725,7 @@ offset_bottom = 412.0
text = "Restart"

[node name="PauseMenu" type="CanvasLayer" parent="."]
layer = 50
visible = false

[node name="TextureRect" type="TextureRect" parent="PauseMenu"]
Expand Down Expand Up @@ -908,6 +911,7 @@ visible = false
[node name="StatsTable" parent="StatsTable" instance=ExtResource("15_7aiwd")]

[node name="SoundIcon" parent="." instance=ExtResource("6_haemp")]
layer = 150

[connection signal="pressed" from="InputSettings/Control/PanelContainer/MarginContainer/VBoxContainer/ResetButton" to="InputSettings/Control" method="_on_reset_button_pressed"]
[connection signal="pressed" from="InputSettings/Control/PanelContainer/MarginContainer/VBoxContainer/BackToSettingsButton" to="InputSettings/Control" method="_on_back_to_settings_button_pressed"]
1 change: 1 addition & 0 deletions scenes/globals/settings_icon.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[ext_resource type="Texture2D" uid="uid://bbb3yar7vfie3" path="res://assets/sprites/icons/settings-icon.svg" id="2_1jmkx"]

[node name="SettingsIcon" type="CanvasLayer"]
layer = 100
script = ExtResource("1_knx0a")

[node name="VBoxContainer" type="VBoxContainer" parent="."]
Expand Down
62 changes: 46 additions & 16 deletions scripts/game/tutorial_dialogue_balloon.gd
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
class_name TutorialDialogueBalloon extends CanvasLayer
## A basic dialogue balloon for use with Dialogue Manager.

@onready var close_tutorial_button: Button = $Balloon/CloseTutorialButton

## The action to use for advancing the dialogue
@export var next_action: StringName = &"ui_accept"

Expand Down Expand Up @@ -61,17 +63,28 @@ var mutation_cooldown: Timer = Timer.new()
func _ready() -> void:
balloon.hide()
Engine.get_singleton("DialogueManager").mutated.connect(_on_mutated)

# If the responses menu doesn't have a next action set, use this one
if responses_menu.next_action.is_empty():
responses_menu.next_action = next_action

mutation_cooldown.timeout.connect(_on_mutation_cooldown_timeout)
add_child(mutation_cooldown)


func _unhandled_input(_event: InputEvent) -> void:
# Only the balloon is allowed to handle input while it's showing
if is_instance_valid(close_tutorial_button):
_update_close_tutorial_text()


func _unhandled_input(event: InputEvent) -> void:
# Se o balão nao está visível, não bloqueia nada
if not is_instance_valid(balloon) or not balloon.visible:
return
# Deixa o jogo abrir o pause/menu principal mesmo durante o tutorial
if event.is_action_pressed("pause") or event.is_action_pressed("ui_cancel"):
return
# fechar tutorial (tecla configurável)
if event.is_action_pressed("close_tutorial"):
_on_close_tutorial_button_pressed()
get_viewport().set_input_as_handled()
return
# Bloqueia o resto para não "vazar" input pro gameplay
get_viewport().set_input_as_handled()


Expand All @@ -96,29 +109,22 @@ func start(dialogue_resource: DialogueResource, title: String, extra_game_states
## Apply any changes to the balloon given a new [DialogueLine].
func apply_dialogue_line() -> void:
mutation_cooldown.stop()

is_waiting_for_input = false
balloon.focus_mode = Control.FOCUS_ALL
balloon.grab_focus()

character_label.visible = not dialogue_line.character.is_empty()
character_label.text = tr(dialogue_line.character, "dialogue")

dialogue_label.hide()
dialogue_label.dialogue_line = dialogue_line

responses_menu.hide()
responses_menu.responses = dialogue_line.responses

# Show our balloon
balloon.show()
will_hide_balloon = false

dialogue_label.show()
if not dialogue_line.text.is_empty():
dialogue_label.type_out()
await dialogue_label.finished_typing

# Wait for input
if dialogue_line.responses.size() > 0:
balloon.focus_mode = Control.FOCUS_NONE
Expand Down Expand Up @@ -166,13 +172,10 @@ func _on_balloon_gui_input(event: InputEvent) -> void:
get_viewport().set_input_as_handled()
dialogue_label.skip_typing()
return

if not is_waiting_for_input: return
if dialogue_line.responses.size() > 0: return

# When there are no response options the balloon itself is the clickable thing
get_viewport().set_input_as_handled()

if event is InputEventMouseButton and event.is_pressed() and event.button_index == MOUSE_BUTTON_LEFT:
next(dialogue_line.next_id)
elif event.is_action_pressed(next_action) and get_viewport().gui_get_focus_owner() == balloon:
Expand All @@ -184,3 +187,30 @@ func _on_responses_menu_response_selected(response: DialogueResponse) -> void:


#endregion


func _on_close_tutorial_button_pressed() -> void:
# Não rodar tutorial de novo nessa run
Singleton.skip_tutorial = true
# Para qualquer avanço automático enquanto fecha
advance_after_blocking_mutation = false
is_waiting_for_input = false
balloon.hide()
# Espera 1 frame pra não matar o state "self"
# enquanto o DialogueManager ainda está resolvendo/mutando.
await get_tree().process_frame
queue_free()



func _update_close_tutorial_text() -> void:
var key_text := _get_action_first_bind_text(&"close_tutorial")
close_tutorial_button.text = "Press %s to close tutorial" % key_text


func _get_action_first_bind_text(action: StringName) -> String:
var events := InputMap.action_get_events(action)
if events.is_empty():
return "?"
# pega o primeiro bind
return events[0].as_text().trim_suffix(" (Physical)")
3 changes: 3 additions & 0 deletions scripts/globals/singleton.gd
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ func _close_all_dialogue_balloons() -> void:
for balloon in get_tree().get_nodes_in_group("dialogue_balloon"):
if is_instance_valid(balloon):
balloon.visible = false
active_balloons.clear()


## Retoma o jogo a partir do estado de pausa.
Expand Down Expand Up @@ -173,6 +174,8 @@ func open_credits() -> void:
## Abre o Main Menu.
func open_main_menu() -> void:
get_tree().paused = true
_close_all_dialogue_balloons()
_tutorial_running = false
if gui_manager:
if gui_manager.is_paused:
if gui_manager.has_method("hide_pause_overlay_only"):
Expand Down
22 changes: 3 additions & 19 deletions scripts/menus/input_settings.gd
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ var input_actions := {
"move_down": "Move down",
"move_left": "Move left",
"pause": "Pause",
"enter": "Enter",
"accept": "Accept",
"boost": "Boost",
"god": "God",
"skip": "Skip tutorial",
"close_tutorial": "Close tutorial",
}


Expand Down Expand Up @@ -55,7 +57,6 @@ func _on_input_button_pressed(button: Node, action: String) -> void:
remap_armed = false
action_to_remap = action
remapping_button = button

# limpa estado visual anterior, se houver
_set_error_ui(button, false)
button.find_child("LabelInput").text = "Press key to bind..."
Expand All @@ -72,20 +73,17 @@ func _on_input_button_pressed(button: Node, action: String) -> void:
func _create_action_list() -> void:
for item in action_list.get_children():
item.queue_free()

for action in input_actions:
var button := input_button_scene.instantiate()
var action_label := button.find_child("LabelAction")
var input_label := button.find_child("LabelInput")
action_label.text = input_actions[action]

# Pega os eventos atuais da ação.
var events := InputMap.action_get_events(action)
if events.size() > 0:
input_label.text = events[0].as_text().trim_suffix(" (Physical)")
else:
input_label.text = ""

action_list.add_child(button)
button.pressed.connect(_on_input_button_pressed.bind(button, action))

Expand All @@ -105,52 +103,42 @@ func _input(event: InputEvent) -> void:
# só captura se estiver remapeando
if not is_remapping or not remap_armed:
return

# --- Allowlist dos tipos aceitos ---
var is_key := event is InputEventKey
var is_mouse_btn := event is InputEventMouseButton
var is_pad_btn := event is InputEventJoypadButton

if not (is_key or is_mouse_btn or is_pad_btn):
return

if is_key and not event.pressed:
return
if is_mouse_btn and not event.pressed:
return
if is_pad_btn and not event.pressed:
return

# evita duplicidade por double click no mouse
if is_mouse_btn and event.double_click:
event.double_click = false

var conflict_with := _is_event_in_use(event, action_to_remap)
if conflict_with != "":
if remapping_button:
var label := remapping_button.find_child("LabelInput")
if label:
label.text = "Shortcut already in use. Try another one."
_set_error_ui(remapping_button, true)

accept_event()
return

# aplica o novo atalho
InputMap.action_erase_events(action_to_remap)
InputMap.action_add_event(action_to_remap, event)
_update_action_list(remapping_button, event)

# restaura UI (cor padrão + largura original)
if remapping_button:
_set_error_ui(remapping_button, false)

# encerra remapeamento
is_remapping = false
remap_armed = false
action_to_remap = ""
remapping_button = null

accept_event()


Expand All @@ -170,16 +158,13 @@ func _save_input_map() -> void:
func _load_input_map() -> void:
if not SaveManager:
return

var profile := SaveManager.profile
if typeof(profile) != TYPE_DICTIONARY or not profile.has("participants"):
return

# chave usada pelo SaveManager
var key := "input_settings"
if not profile.participants.has(key):
return

var bindings: Dictionary = profile.participants[key].get("bindings", {})
for action_name in input_actions.keys():
InputMap.action_erase_events(action_name)
Expand Down Expand Up @@ -319,7 +304,6 @@ func _is_event_in_use(new_event: InputEvent, except_action: String) -> String:
func _set_error_ui(line_button: Node, is_error: bool) -> void:
var label: Label = line_button.find_child("LabelInput")
var left_column: Control = line_button.find_child("LeftColumn")

if is_error:
if label:
label.add_theme_color_override("font_color", Color(1, 0.3, 0.1))
Expand Down