From 1f28fdc8f3060b170f65c2a28562e95cfd742086 Mon Sep 17 00:00:00 2001 From: Dennis Ploeger Date: Fri, 27 Aug 2021 08:15:52 +0200 Subject: [PATCH] feat: Implemented all dialog features. Fixes #345 (#376) Co-authored-by: Dennis Ploeger Co-authored-by: dploeger --- .../game/core-scripts/esc/types/esc_dialog.gd | 25 +++-- .../game/scenes/dialogs/dialog_player.gd | 71 ++++++------- .../dialogs/esc_dialog_options_chooser.gd | 34 +++++++ addons/escoria-core/plugin.gd | 13 +-- .../dialog_choosers/text_dialog_choice.gd | 94 ++++++++++-------- .../dialog_choosers/text_dialog_choice.tscn | 61 ++++++++---- docs/api/ESCDialog.md | 14 +-- docs/api/ESCDialogOptionsChooser.md | 57 +++++++++++ docs/api/ESCDialogsPlayer.md | 22 ++-- docs/api/ESCLogger.md | 8 +- docs/api/text_dialog_choice.gd.md | 18 ++-- docs/esc.md | 7 +- game/characters/mark/mark_talk.tscn | 34 +++++++ game/rooms/room06/esc/worker.esc | 4 +- game/translations/main_menu.en.translation | Bin 560 -> 921 bytes game/translations/main_menu.fr.translation | Bin 576 -> 956 bytes game/ui/commons/dialogs/text_dialog_choice.gd | 67 +++++++++++++ .../commons/dialogs/text_dialog_choice.tscn | 54 +++++++--- project.godot | 7 ++ 19 files changed, 418 insertions(+), 172 deletions(-) create mode 100644 addons/escoria-core/game/scenes/dialogs/esc_dialog_options_chooser.gd create mode 100644 docs/api/ESCDialogOptionsChooser.md create mode 100644 game/characters/mark/mark_talk.tscn mode change 100755 => 100644 game/rooms/room06/esc/worker.esc create mode 100644 game/ui/commons/dialogs/text_dialog_choice.gd diff --git a/addons/escoria-core/game/core-scripts/esc/types/esc_dialog.gd b/addons/escoria-core/game/core-scripts/esc/types/esc_dialog.gd index 66a45902..bd6fef28 100644 --- a/addons/escoria-core/game/core-scripts/esc/types/esc_dialog.gd +++ b/addons/escoria-core/game/core-scripts/esc/types/esc_dialog.gd @@ -5,7 +5,7 @@ class_name ESCDialog # Regex that matches dialog lines const REGEX = \ - '^(\\s*)\\?( (?[^ ]+))?( (?[^ ]+))?' +\ + '^(\\s*)\\?( (?[^ ]+))?' +\ '( (?[^ ]+))?( (?.+))?$' @@ -14,11 +14,8 @@ const END_REGEX = \ '^(?\\s*)!.*$' -# Dialog type -var type: String = "" - # Avatar used in the dialog -var avatar: String = "" +var avatar: String = "-" # Timeout until the timeout_option option is selected. Use 0 for no timeout var timeout: int = 0 @@ -37,8 +34,6 @@ func _init(dialog_string: String): if dialog_regex.search(dialog_string): for result in dialog_regex.search_all(dialog_string): - if "type" in result.names: - self.type = escoria.utils.get_re_group(result, "type") if "avatar" in result.names: self.avatar = escoria.utils.get_re_group(result, "avatar") if "timeout" in result.names: @@ -58,8 +53,22 @@ func _init(dialog_string: String): ) -# Dialogs have no conditions, just return true +# Check if dialog is valid func is_valid() -> bool: + if self.avatar != "-" and not ResourceLoader.exists(self.avatar): + escoria.logger.report_errors( + "Avatar scene not found: %s" % self.avatar, + [] + ) + return false + if self.timeout_option > self.options.size() \ + or self.timeout_option < 0: + escoria.logger.report_errors( + "Invalid timeout_option parameter given: %d" % self.timeout_option, + [] + ) + return false + return true diff --git a/addons/escoria-core/game/scenes/dialogs/dialog_player.gd b/addons/escoria-core/game/scenes/dialogs/dialog_player.gd index 8fbd496c..ce746edd 100644 --- a/addons/escoria-core/game/scenes/dialogs/dialog_player.gd +++ b/addons/escoria-core/game/scenes/dialogs/dialog_player.gd @@ -18,62 +18,41 @@ signal dialog_line_finished # Wether the player is currently speaking var is_speaking = false + # Reference to the dialog UI var _dialog_ui = null # Reference to the dialog chooser UI -var _dialog_chooser_ui = null +var _dialog_chooser_ui: ESCDialogOptionsChooser = null # Register the dialog player and load the dialog resources func _ready(): if !Engine.is_editor_hint(): escoria.dialog_player = self - preload_resources(ProjectSettings.get_setting("escoria/ui/dialogs_folder")) + _dialog_chooser_ui = ResourceLoader.load( + ProjectSettings.get_setting("escoria/ui/dialogs_chooser") + ).instance() + assert(_dialog_chooser_ui is ESCDialogOptionsChooser) + _dialog_chooser_ui.connect( + "option_chosen", + self, + "play_dialog_option_chosen" + ) + get_parent().call_deferred("add_child", _dialog_chooser_ui) # Trigger the finish fast function on the dialog ui +# +# #### Parameters +# +# - event: The input event func _input(event): if event is InputEventMouseButton and \ event.pressed: finish_fast() -# Preload the dialog UI resources -# -# #### Parameters -# -# - path: Path where the actual dialog UI resources are located -func preload_resources(path: String) -> void: - var dialog_folder := Directory.new() - if !path.empty() and dialog_folder.open(path) == OK: - dialog_folder.list_dir_begin() - var file_name = dialog_folder.get_next() - while file_name != "": - if !dialog_folder.current_is_dir() \ - and file_name.get_extension() == "tscn": - var extension = "." + file_name.get_extension() - var basename = file_name.replace(extension, "") - - if !has_resource(basename): - var file_path = "%s/%s" % [ - dialog_folder.get_current_dir(), - file_name - ] - var dialog_scene = load(file_path) - - if dialog_scene != null: - add_resource(basename, dialog_scene) - file_name = dialog_folder.get_next() - else: - escoria.logger.report_errors( - "dialog_player.gd:preload_resources()", - [ - "An error occurred when trying to access the path: %s." % path - ] - ) - - # A short one line dialog # # #### Parameters @@ -99,20 +78,26 @@ func finish_fast() -> void: # Display a list of choices +# +# #### Parameters +# +# - dialog: The dialog to start func start_dialog_choices(dialog: ESCDialog): if dialog.options.empty(): escoria.logger.report_errors( "dialog_player.gd:start_dialog_choices()", ["Received answers array was empty."] ) - _dialog_chooser_ui = get_resource("text_dialog_choice").instance() - get_parent().add_child(_dialog_chooser_ui) - - _dialog_chooser_ui.set_answers(dialog.options) + _dialog_chooser_ui.set_dialog(dialog) + _dialog_chooser_ui.show_chooser() -# Called when an option was chosen +# Called when an option was chosen and emits the option_chosen signal +# +# #### Parameters +# +# - option: Option, that was chosen. func play_dialog_option_chosen(option: ESCDialogOption): emit_signal("option_chosen", option) - _dialog_chooser_ui.hide() + _dialog_chooser_ui.hide_chooser() diff --git a/addons/escoria-core/game/scenes/dialogs/esc_dialog_options_chooser.gd b/addons/escoria-core/game/scenes/dialogs/esc_dialog_options_chooser.gd new file mode 100644 index 00000000..b20d7c33 --- /dev/null +++ b/addons/escoria-core/game/scenes/dialogs/esc_dialog_options_chooser.gd @@ -0,0 +1,34 @@ +# Base class for all dialog options implementations +extends Node +class_name ESCDialogOptionsChooser + + +# An option was chosen +# +# ##### Parameters +# +# - option: The dialog option that was chosen +signal option_chosen(option) + + +# The dialog to show +var dialog: ESCDialog + + +# Set the dialog used for the chooser +# +# #### Parameters +# +# - new_dialog: Dialog to set +func set_dialog(new_dialog: ESCDialog) -> void: + self.dialog = new_dialog + + +# Show the dialog chooser UI +func show_chooser() -> void: + escoria.logger.error("Dialog chooser did not implement the show method.") + + +# Hide the dialog chooser UI +func hide_chooser() -> void: + escoria.logger.error("Dialog chooser did not implement the hide method.") diff --git a/addons/escoria-core/plugin.gd b/addons/escoria-core/plugin.gd index 6023878f..7ca624d0 100644 --- a/addons/escoria-core/plugin.gd +++ b/addons/escoria-core/plugin.gd @@ -26,14 +26,15 @@ func set_escoria_ui_settings(): if !ProjectSettings.has_setting("escoria/ui/tooltip_follows_mouse"): ProjectSettings.set_setting("escoria/ui/tooltip_follows_mouse", true) - if !ProjectSettings.has_setting("escoria/ui/dialogs_folder"): - ProjectSettings.set_setting("escoria/ui/dialogs_folder", "") - var dialogs_folder_property_info = { - "name": "escoria/ui/dialogs_folder", + if !ProjectSettings.has_setting("escoria/ui/dialogs_chooser"): + ProjectSettings.set_setting("escoria/ui/dialogs_chooser", "") + var dialogs_chooser_property_info = { + "name": "escoria/ui/dialogs_chooser", "type": TYPE_STRING, - "hint": PROPERTY_HINT_DIR + "hint": PROPERTY_HINT_FILE, + "hint_string": "*.tscn, *.scn" } - ProjectSettings.add_property_info(dialogs_folder_property_info) + ProjectSettings.add_property_info(dialogs_chooser_property_info) if !ProjectSettings.has_setting("escoria/ui/default_dialog_scene"): ProjectSettings.set_setting("escoria/ui/default_dialog_scene", "") diff --git a/addons/escoria-core/template_scenes/dialog_scenes/dialog_choosers/text_dialog_choice.gd b/addons/escoria-core/template_scenes/dialog_scenes/dialog_choosers/text_dialog_choice.gd index c7a4a9ad..f9460cbb 100644 --- a/addons/escoria-core/template_scenes/dialog_scenes/dialog_choosers/text_dialog_choice.gd +++ b/addons/escoria-core/template_scenes/dialog_scenes/dialog_choosers/text_dialog_choice.gd @@ -1,53 +1,67 @@ -tool -extends Control +extends ESCDialogOptionsChooser export(Color, RGB) var color_normal = Color(1.0,1.0,1.0,1.0) export(Color, RGB) var color_hover = Color(165.0,42.0,42.0, 1.0) export(Font) var font -var commands -func _ready(): - for c in $ScrollContainer/VBoxContainer.get_children(): - c.queue_free() +func _ready() -> void: + hide_chooser() + + +func _process(delta: float) -> void: + if $MarginContainer.visible and self.dialog and self.dialog.timeout > 0: + $TimerProgress.value = ( + self.dialog.timeout - $Timer.time_left + ) / self.dialog.timeout * 100 -func set_answers(options : Array): - commands = options - for option in commands: - var new_answer_label = RichTextLabel.new() - new_answer_label.text = option.option - new_answer_label.fit_content_height = true - new_answer_label.add_font_override("normal_font", font) - - $ScrollContainer/VBoxContainer.add_child(new_answer_label) - new_answer_label.fit_content_height = true - new_answer_label.connect("focus_entered", self, "_on_answer_focus_entered", [new_answer_label]) # Focus entered - new_answer_label.connect("focus_exited", self, "_on_answer_focus_exited", [new_answer_label]) # Focus exited - new_answer_label.connect("mouse_entered", self, "_on_answer_mouse_entered", [new_answer_label]) # Mouse entered - new_answer_label.connect("mouse_exited", self, "_on_answer_mouse_exited", [new_answer_label]) # Mouse exited - new_answer_label.connect("gui_input", self, "_on_answer_gui_input", [option]) # Clicks +func show_chooser(): + var _vbox = $MarginContainer/ScrollContainer/VBoxContainer + for option_node in _vbox.get_children(): + _vbox.remove_child(option_node) + + _remove_avatar() + + for option in self.dialog.options: + var _option_node = Button.new() + _option_node.text = (option as ESCDialogOption).option + _option_node.flat = true + _option_node.add_color_override("font_color", color_normal) + _option_node.add_color_override("font_color_hover", color_hover) + _option_node.add_font_override("font", font) + _vbox.add_child(_option_node) + _option_node.connect("pressed", self, "_on_answer_selected", [option]) + + if self.dialog.avatar != "-": + $AvatarContainer.add_child( + ResourceLoader.load(self.dialog.avatar).instance() + ) + + $MarginContainer.show() + + if self.dialog.timeout > 0: + $Timer.start(self.dialog.timeout) -func _on_answer_gui_input(event : InputEvent, answer : ESCDialogOption): - if event is InputEventMouseButton and event.is_pressed(): - escoria.dialog_player.play_dialog_option_chosen(answer) -func _on_answer_mouse_entered(answer_node : Node): - var text = answer_node.text - answer_node.clear() - answer_node.push_color(color_hover.to_html(false)) - answer_node.append_bbcode(text) - answer_node.pop() +func hide_chooser(): + $MarginContainer.hide() + -func _on_answer_mouse_exited(answer_node : Node): - var text = answer_node.text - answer_node.clear() - answer_node.push_color(color_normal.to_html(false)) - answer_node.append_bbcode(text) - answer_node.pop() +func _option_chosen(option: ESCDialogOption): + _remove_avatar() + $TimerProgress.value = 0 + emit_signal("option_chosen", option) -func _on_answer_focus_entered(answer_node : Node): - pass -func _on_answer_focus_exited(answer_node : Node): - pass +func _on_answer_selected(option: ESCDialogOption): + _option_chosen(option) + + +func _on_Timer_timeout() -> void: + _option_chosen(self.dialog.options[self.dialog.timeout_option - 1]) + + +func _remove_avatar(): + if $AvatarContainer.get_child_count() > 0: + $AvatarContainer.remove_child($AvatarContainer.get_child(0)) diff --git a/addons/escoria-core/template_scenes/dialog_scenes/dialog_choosers/text_dialog_choice.tscn b/addons/escoria-core/template_scenes/dialog_scenes/dialog_choosers/text_dialog_choice.tscn index c4ea435f..5f425cb1 100644 --- a/addons/escoria-core/template_scenes/dialog_scenes/dialog_choosers/text_dialog_choice.tscn +++ b/addons/escoria-core/template_scenes/dialog_scenes/dialog_choosers/text_dialog_choice.tscn @@ -1,33 +1,44 @@ -[gd_scene load_steps=3 format=2] +[gd_scene load_steps=5 format=2] [ext_resource path="res://addons/escoria-core/template_scenes/dialog_scenes/dialog_choosers/text_dialog_choice.gd" type="Script" id=1] [ext_resource path="res://addons/escoria-core/game/assets/fonts/efmi/efmi_font.tres" type="DynamicFont" id=2] -[node name="text_dialog_choice" type="MarginContainer"] -anchor_right = 1.0 -anchor_bottom = 1.0 -custom_constants/margin_top = 20 -custom_constants/margin_left = 20 +[sub_resource type="Gradient" id=1] +colors = PoolColorArray( 1, 0, 0, 1, 1, 0, 0, 1 ) + +[sub_resource type="GradientTexture" id=2] +gradient = SubResource( 1 ) + +[node name="text_dialog_choice" type="Node"] script = ExtResource( 1 ) -__meta__ = { -"_edit_use_anchors_": false -} color_hover = Color( 0.647059, 0.164706, 0.164706, 1 ) font = ExtResource( 2 ) -[node name="ScrollContainer" type="ScrollContainer" parent="."] +[node name="MarginContainer" type="MarginContainer" parent="."] margin_left = 20.0 margin_top = 20.0 margin_right = 1280.0 -margin_bottom = 800.0 +margin_bottom = 900.0 +mouse_filter = 2 +custom_constants/margin_top = 20 +custom_constants/margin_left = 20 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer"] +margin_left = 20.0 +margin_top = 20.0 +margin_right = 1260.0 +margin_bottom = 880.0 scroll_horizontal_enabled = false __meta__ = { "_edit_use_anchors_": false } -[node name="VBoxContainer" type="VBoxContainer" parent="ScrollContainer"] -margin_right = 1260.0 -margin_bottom = 780.0 +[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/ScrollContainer"] +margin_right = 1240.0 +margin_bottom = 860.0 size_flags_horizontal = 3 size_flags_vertical = 3 custom_constants/separation = 20 @@ -35,9 +46,19 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="example" type="RichTextLabel" parent="ScrollContainer/VBoxContainer"] -margin_right = 1260.0 -margin_bottom = 25.0 -custom_fonts/normal_font = ExtResource( 2 ) -text = "This answer is an example for vizualisation purpose. You can safely keep it in the scene as it will be removed on game launch." -fit_content_height = true +[node name="Timer" type="Timer" parent="."] +one_shot = true + +[node name="TimerProgress" type="TextureProgress" parent="."] +anchor_right = 1.0 +rect_min_size = Vector2( 0, 20 ) +texture_progress = SubResource( 2 ) +nine_patch_stretch = true +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="AvatarContainer" type="Node2D" parent="."] +position = Vector2( 29.1458, 120.012 ) + +[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"] diff --git a/docs/api/ESCDialog.md b/docs/api/ESCDialog.md index 817d98c7..471026ce 100644 --- a/docs/api/ESCDialog.md +++ b/docs/api/ESCDialog.md @@ -21,25 +21,17 @@ A Regex that matches the end of a dialog ### REGEX ```gdscript -const REGEX: String = "^(\\s*)\\?( (?[^ ]+))?( (?[^ ]+))?( (?[^ ]+))?( (?.+))?$" +const REGEX: String = "^(\\s*)\\?( (?[^ ]+))?( (?[^ ]+))?( (?.+))?$" ``` Regex that matches dialog lines ## Property Descriptions -### type - -```gdscript -var type: String = "" -``` - -Dialog type - ### avatar ```gdscript -var avatar: String = "" +var avatar: String = "-" ``` Avatar used in the dialog @@ -84,7 +76,7 @@ Construct a dialog from a dialog string func is_valid() -> bool ``` -Dialogs have no conditions, just return true +Check if dialog is valid ### run diff --git a/docs/api/ESCDialogOptionsChooser.md b/docs/api/ESCDialogOptionsChooser.md new file mode 100644 index 00000000..e1db536c --- /dev/null +++ b/docs/api/ESCDialogOptionsChooser.md @@ -0,0 +1,57 @@ + + +# ESCDialogOptionsChooser + +**Extends:** [Node](../Node) + +## Description + +Base class for all dialog options implementations + +## Property Descriptions + +### dialog + +```gdscript +var dialog: ESCDialog +``` + +The dialog to show + +## Method Descriptions + +### set\_dialog + +```gdscript +func set_dialog(new_dialog: ESCDialog) -> void +``` + +Set the dialog used for the chooser + +#### Parameters + +- new_dialog: Dialog to set + +### show\_chooser + +```gdscript +func show_chooser() -> void +``` + +Show the dialog chooser UI + +### hide\_chooser + +```gdscript +func hide_chooser() -> void +``` + +Hide the dialog chooser UI + +## Signals + +- signal option_chosen(option): An option was chosen + +##### Parameters + +- option: The dialog option that was chosen diff --git a/docs/api/ESCDialogsPlayer.md b/docs/api/ESCDialogsPlayer.md index a61eeaad..f5281a70 100644 --- a/docs/api/ESCDialogsPlayer.md +++ b/docs/api/ESCDialogsPlayer.md @@ -20,18 +20,6 @@ Wether the player is currently speaking ## Method Descriptions -### preload\_resources - -```gdscript -func preload_resources(path: String) -> void -``` - -Preload the dialog UI resources - -#### Parameters - -- path: Path where the actual dialog UI resources are located - ### say ```gdscript @@ -62,13 +50,21 @@ func start_dialog_choices(dialog: ESCDialog) Display a list of choices +#### Parameters + +- dialog: The dialog to start + ### play\_dialog\_option\_chosen ```gdscript func play_dialog_option_chosen(option: ESCDialogOption) ``` -Called when an option was chosen +Called when an option was chosen and emits the option_chosen signal + +#### Parameters + +- option: Option, that was chosen. ## Signals diff --git a/docs/api/ESCLogger.md b/docs/api/ESCLogger.md index bc26fade..42c31951 100644 --- a/docs/api/ESCLogger.md +++ b/docs/api/ESCLogger.md @@ -13,7 +13,7 @@ Logging framework for Escoria ### LOG\_DEBUG ```gdscript -const LOG_WARNING: int = 1 +const LOG_ERROR: int = 0 ``` Valid log levels @@ -21,7 +21,7 @@ Valid log levels ### LOG\_ERROR ```gdscript -const LOG_WARNING: int = 1 +const LOG_ERROR: int = 0 ``` Valid log levels @@ -29,7 +29,7 @@ Valid log levels ### LOG\_INFO ```gdscript -const LOG_WARNING: int = 1 +const LOG_ERROR: int = 0 ``` Valid log levels @@ -37,7 +37,7 @@ Valid log levels ### LOG\_WARNING ```gdscript -const LOG_WARNING: int = 1 +const LOG_ERROR: int = 0 ``` Valid log levels diff --git a/docs/api/text_dialog_choice.gd.md b/docs/api/text_dialog_choice.gd.md index b93f7f70..885dba7a 100644 --- a/docs/api/text_dialog_choice.gd.md +++ b/docs/api/text_dialog_choice.gd.md @@ -2,7 +2,7 @@ # text\_dialog\_choice.gd -**Extends:** [Control](../Control) +**Extends:** [ESCDialogOptionsChooser](../ESCDialogOptionsChooser) < [Node](../Node) ## Description @@ -26,17 +26,17 @@ export var color_hover = "165,42,42,1" export var font = "[Object:null]" ``` -### commands - -```gdscript -var commands -``` - ## Method Descriptions -### set\_answers +### show\_chooser ```gdscript -func set_answers(options: Array) +func show_chooser() +``` + +### hide\_chooser + +```gdscript +func hide_chooser() ``` diff --git a/docs/esc.md b/docs/esc.md index 4dbdf234..8f1336dd 100644 --- a/docs/esc.md +++ b/docs/esc.md @@ -394,17 +394,16 @@ Dialogs are specified by writing `?` with optional parameters, followed by a lis The following parameters are available: -* type: (default value "default") the type of dialog menu to use. -* avatar: (default value "default") the avatar to use in the dialog ui. +* avatar: the path to a scene displaying an avatar used in the UI. Defaults to no avatar. To only set the remaining options, set this field to "-" * timeout: (default value 0) timeout to select an option. After the time has passed, the "timeout_option" will be selected automatically. If the value is 0, there's no timeout. -* timeout_option: (default value 0) option selected when timeout is reached. +* timeout_option: (default value 0) index of option (starting from 1) selected when timeout is reached. Example: ``` # character's "talk" event :talk -? type avatar timeout timeout_option +? avatar timeout timeout_option - "I'd like to buy a map." [!player_has_map] say player "I'd like to buy a map" say map_vendor "Do you know the secret code?" diff --git a/game/characters/mark/mark_talk.tscn b/game/characters/mark/mark_talk.tscn new file mode 100644 index 00000000..6f37c920 --- /dev/null +++ b/game/characters/mark/mark_talk.tscn @@ -0,0 +1,34 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://game/characters/mark/png/mark_talk_right.png" type="Texture" id=1] + +[sub_resource type="AtlasTexture" id=1] +atlas = ExtResource( 1 ) +region = Rect2( 0, 0, 24, 70 ) + +[sub_resource type="AtlasTexture" id=2] +atlas = ExtResource( 1 ) +region = Rect2( 24, 0, 24, 70 ) + +[sub_resource type="AtlasTexture" id=3] +atlas = ExtResource( 1 ) +region = Rect2( 48, 0, 24, 70 ) + +[sub_resource type="AtlasTexture" id=4] +atlas = ExtResource( 1 ) +region = Rect2( 72, 0, 24, 70 ) + +[sub_resource type="AtlasTexture" id=5] +atlas = ExtResource( 1 ) +region = Rect2( 96, 0, 24, 70 ) + +[sub_resource type="SpriteFrames" id=6] +animations = [ { +"frames": [ SubResource( 1 ), SubResource( 2 ), SubResource( 3 ), SubResource( 4 ), SubResource( 5 ) ], +"loop": true, +"name": "default", +"speed": 5.0 +} ] + +[node name="AnimatedSprite" type="AnimatedSprite"] +frames = SubResource( 6 ) diff --git a/game/rooms/room06/esc/worker.esc b/game/rooms/room06/esc/worker.esc old mode 100755 new mode 100644 index 25bad1cc..15406144 --- a/game/rooms/room06/esc/worker.esc +++ b/game/rooms/room06/esc/worker.esc @@ -12,7 +12,7 @@ say player "I don't think he'd like that." say worker "Yeah?" set_global talked_once true -? option1 1000 option2 true +? res://game/characters/mark/mark_talk.tscn 5 1 - "What are you doing here?" say player "What are you doing here?" say worker "I'm working! Can't you see that?" @@ -27,7 +27,7 @@ say player "I don't think he'd like that." say player "I've got better things to do." say worker "Eh! I'm not asking you anythin'!" stop - ! + ! - "I'm selling these fine leather jackets." say player "I'm selling these fine leather jackets." say worker "Go away, kid." diff --git a/game/translations/main_menu.en.translation b/game/translations/main_menu.en.translation index 7959765cca87e17d5fff412974df0ddb234b668e..c1f4dabb4baedf2c73794d8001b776f8fa4b874f 100644 GIT binary patch literal 921 zcmbW0y=xRf7{=eboO<<^~(&`cJyVEro_)nDyB{P%CxzcBBI!O@=euYP7bO=w#X z_M8hZf>GXsIU&|}rS!T8{dYVMKjk+a_)Iym>p#yu?Lz)@ueaaUo-e>>{3HvwXXHmV zTtaW-8C4fQG9RoE^5@)*wZ>U!J|^G8?tkY^4wRw!ZoKbUbNCDk!tQ6>Bj7QZRnDqZ zRNyA4J4ws)k1|(t;rE>1%}hypeey&zm79t29Jz(EOlx0fqVmvYF1*YYMVaYz{0EXQ xE)}!m<6C|GsgzXUXkV(K)NaT^;>A)4)xCnt5>IQ>&pxD5)%SNazF)^r`5XHBtGfUI literal 560 zcmV-00?++YQ$s@n000005C8zY0{{RR0ssIgwJ-f(yaII)0M^=GMgXxUjRAc1s};S1 z02&csvTptA^)`1nB&cgVeJ03Gz3ok?NTMvUiSJZ)&Co3T;42E(z!yhKGQ@Yi!n<=w zJHFRIv5^!(06zd-0F~Cg(LkFY{P3L;H3NgqCd2pT#X%-@k^~}l$rTOHa;AG%N0tcE^wg!(hu{q{0#mC|4GSzK-BsN z`~iN@U*ISCvFsGNDWF_WCAsKjv}WtYEz3qK|5aJsr_oJvUmj*+!Xup4I0{PmKl~#q z2t;a5{*aFqPK79iqtnyTVnH+k&CiUH&j_3tDK@l1$n;zuJ0TYxN=}g8uxcVnC>XIm zG)xfq1-!^XvBIli(rF1j1q?hTI#A975T_&*4eI|!i!jrzaL7Ug%PHKY!NhhzV!js` zr|_`GzzT%$-6FWjSjrG*>B@lM$7- zb8rPbAV2~nFjaR0V~4Tu{HBwD4a!t!1t28RVwQ$s_0AOjWv diff --git a/game/translations/main_menu.fr.translation b/game/translations/main_menu.fr.translation index 5aa2ec1d7423ea9777a0740c16df2e3424366b4b..c56bc02e5ff98f5a00129f38b7492f41cba3a245 100644 GIT binary patch literal 956 zcmbW0ziSjh6vy9PqMo^Ej3QA8CI@mw5;!%epr;Z~F_?H8*Fyp-%VZh%)@*jq{ZVM= zkHQodq7gfr2wo{6M6gh}Kfux=jR7lBOUpgK@3I3+NaetXnfIOd-n_RntKZNol#DLS zihitTCPh%M`N9nx5!#-s{Qi5+A@UILW#C1=DGkRng=2)C5t!1Iv^TxyiUmo#p)ANC z5S9#R7mQAXq&${&RA+=@&XKeS=3HdX%PDV2^> zFH0EP_S}sP{wO<=`L0ha4TAx|V<+eZ`$0Q3xK(8y!TM;*W_<+qF>nf$!9_3)bin(3 zA0|JzSH@zxH$K zg_-!We>T}0`knPWtkruhij!YCPNCvAnoG6Q&<}#cK*fKu$MZK~^ULW2BeVUZ&oJ{n z?gMcY3! YRVzRL5>s5g<-N(5wX4~fbo{sf08MbZ#{d8T literal 576 zcmV-G0>AxIQ$s@n000005C8z*0{{Rh0ssIgwJ-f(-vadz00v!VMgXxkYdEfU6tpre zkN}M0=f9Im>%uh@A{vOlWDX)*NxQPmP)XS)4J$^&rStXeA{{etOW@>G4|awx@$C+QnZ*rg|MdSm@Z-6Ahld<4e@PjHHS5Qq2 z7FohV(GC+43ksbaJ|H=-6EH!l9t@~N3XIcTt3+2s82tv8h{ubPKLL&%o*6g+r<8}( zbqvLs+8ebmjU1D9zYuzDp%t^?l(c?AuRmE`Kh*W3;W>6x%3NnxT>;9ESGP{i4V`nhe$=`<$gtI0X86Df+42NJOsIk_Y~lonJtqP zGO=}8n_>K+Cao<-k=fL|8!<_yS4s4KqM3AQ?4P^Gn?58Ui<3GDE4#Jty OGV(qnhJpoBQ$s_4pA1(3 diff --git a/game/ui/commons/dialogs/text_dialog_choice.gd b/game/ui/commons/dialogs/text_dialog_choice.gd new file mode 100644 index 00000000..f9460cbb --- /dev/null +++ b/game/ui/commons/dialogs/text_dialog_choice.gd @@ -0,0 +1,67 @@ +extends ESCDialogOptionsChooser + +export(Color, RGB) var color_normal = Color(1.0,1.0,1.0,1.0) +export(Color, RGB) var color_hover = Color(165.0,42.0,42.0, 1.0) +export(Font) var font + + +func _ready() -> void: + hide_chooser() + + +func _process(delta: float) -> void: + if $MarginContainer.visible and self.dialog and self.dialog.timeout > 0: + $TimerProgress.value = ( + self.dialog.timeout - $Timer.time_left + ) / self.dialog.timeout * 100 + + +func show_chooser(): + var _vbox = $MarginContainer/ScrollContainer/VBoxContainer + for option_node in _vbox.get_children(): + _vbox.remove_child(option_node) + + _remove_avatar() + + for option in self.dialog.options: + var _option_node = Button.new() + _option_node.text = (option as ESCDialogOption).option + _option_node.flat = true + _option_node.add_color_override("font_color", color_normal) + _option_node.add_color_override("font_color_hover", color_hover) + _option_node.add_font_override("font", font) + _vbox.add_child(_option_node) + _option_node.connect("pressed", self, "_on_answer_selected", [option]) + + if self.dialog.avatar != "-": + $AvatarContainer.add_child( + ResourceLoader.load(self.dialog.avatar).instance() + ) + + $MarginContainer.show() + + if self.dialog.timeout > 0: + $Timer.start(self.dialog.timeout) + + +func hide_chooser(): + $MarginContainer.hide() + + +func _option_chosen(option: ESCDialogOption): + _remove_avatar() + $TimerProgress.value = 0 + emit_signal("option_chosen", option) + + +func _on_answer_selected(option: ESCDialogOption): + _option_chosen(option) + + +func _on_Timer_timeout() -> void: + _option_chosen(self.dialog.options[self.dialog.timeout_option - 1]) + + +func _remove_avatar(): + if $AvatarContainer.get_child_count() > 0: + $AvatarContainer.remove_child($AvatarContainer.get_child(0)) diff --git a/game/ui/commons/dialogs/text_dialog_choice.tscn b/game/ui/commons/dialogs/text_dialog_choice.tscn index 38d7e047..5f425cb1 100644 --- a/game/ui/commons/dialogs/text_dialog_choice.tscn +++ b/game/ui/commons/dialogs/text_dialog_choice.tscn @@ -1,34 +1,64 @@ -[gd_scene load_steps=3 format=2] +[gd_scene load_steps=5 format=2] [ext_resource path="res://addons/escoria-core/template_scenes/dialog_scenes/dialog_choosers/text_dialog_choice.gd" type="Script" id=1] [ext_resource path="res://addons/escoria-core/game/assets/fonts/efmi/efmi_font.tres" type="DynamicFont" id=2] -[node name="text_dialog_choice" type="MarginContainer"] -anchor_right = 1.0 -anchor_bottom = 1.0 -custom_constants/margin_top = 20 -custom_constants/margin_left = 20 +[sub_resource type="Gradient" id=1] +colors = PoolColorArray( 1, 0, 0, 1, 1, 0, 0, 1 ) + +[sub_resource type="GradientTexture" id=2] +gradient = SubResource( 1 ) + +[node name="text_dialog_choice" type="Node"] script = ExtResource( 1 ) -__meta__ = { -"_edit_use_anchors_": false -} color_hover = Color( 0.647059, 0.164706, 0.164706, 1 ) font = ExtResource( 2 ) -[node name="ScrollContainer" type="ScrollContainer" parent="."] +[node name="MarginContainer" type="MarginContainer" parent="."] margin_left = 20.0 margin_top = 20.0 margin_right = 1280.0 margin_bottom = 900.0 +mouse_filter = 2 +custom_constants/margin_top = 20 +custom_constants/margin_left = 20 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer"] +margin_left = 20.0 +margin_top = 20.0 +margin_right = 1260.0 +margin_bottom = 880.0 scroll_horizontal_enabled = false __meta__ = { "_edit_use_anchors_": false } -[node name="VBoxContainer" type="VBoxContainer" parent="ScrollContainer"] -margin_right = 1260.0 +[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/ScrollContainer"] +margin_right = 1240.0 +margin_bottom = 860.0 size_flags_horizontal = 3 +size_flags_vertical = 3 custom_constants/separation = 20 __meta__ = { "_edit_use_anchors_": false } + +[node name="Timer" type="Timer" parent="."] +one_shot = true + +[node name="TimerProgress" type="TextureProgress" parent="."] +anchor_right = 1.0 +rect_min_size = Vector2( 0, 20 ) +texture_progress = SubResource( 2 ) +nine_patch_stretch = true +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="AvatarContainer" type="Node2D" parent="."] +position = Vector2( 29.1458, 120.012 ) + +[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"] diff --git a/project.godot b/project.godot index aee27860..b0d2c63b 100644 --- a/project.godot +++ b/project.godot @@ -169,6 +169,11 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://addons/escoria-core/game/core-scripts/esc/types/esc_dialog_option.gd" }, { +"base": "Node", +"class": "ESCDialogOptionsChooser", +"language": "GDScript", +"path": "res://addons/escoria-core/game/scenes/dialogs/esc_dialog_options_chooser.gd" +}, { "base": "ResourcePreloader", "class": "ESCDialogsPlayer", "language": "GDScript", @@ -512,6 +517,7 @@ _global_script_class_icons={ "ESCController": "", "ESCDialog": "", "ESCDialogOption": "", +"ESCDialogOptionsChooser": "", "ESCDialogsPlayer": "", "ESCDirectionAngle": "", "ESCEvent": "", @@ -635,6 +641,7 @@ main/settings_path="user://" main/escoria_version="" sound/speech_enabled=1 ui/game_scene="res://addons/escoria-ui-9verbs/game.tscn" +ui/dialogs_chooser="res://game/ui/commons/dialogs/text_dialog_choice.tscn" [input]