Issue 315 (#341)

* feat: accept_input implemented

* feat: More fixes for accept_input and tests for it

* feat: play_snd implemented

* fix: Removed game_over and queue_animation commands

* docs: Automatic update of API docs

* fix: FIxes schedule_event command

* feat: Implemented slide and slide_block

* feat: Implemented turn_to

* docs: Automatic update of API docs

Co-authored-by: Dennis Ploeger <develop@dieploegers.de>
Co-authored-by: dploeger <dploeger@users.noreply.github.com>
This commit is contained in:
Dennis Ploeger
2021-07-29 23:05:24 +02:00
committed by GitHub
parent df1ec0c814
commit 90f880d090
38 changed files with 622 additions and 480 deletions

View File

@@ -9,7 +9,6 @@
# skipped, but also initiate locked#### down cutscenes with accept_input
# NONE in :setup and accept_input ALL later in :ready.
#
# @STUB
# @ESC
extends ESCBaseCommand
class_name AcceptInputCommand
@@ -40,8 +39,12 @@ func validate(arguments: Array):
# Run the command
func run(command_params: Array) -> int:
escoria.logger.report_errors(
"accept_input: command not implemented",
[]
)
return ESCExecution.RC_ERROR
var mode = escoria.inputs_manager.INPUT_ALL
match command_params[0]:
"NONE":
mode = escoria.inputs_manager.INPUT_NONE
"SKIP":
mode = escoria.inputs_manager.INPUT_SKIP
escoria.inputs_manager.input_mode = mode
return ESCExecution.RC_OK

View File

@@ -1,29 +0,0 @@
# `game_over continue_enabled show_credits`
#
# Ends the game. Use the "continue_enabled" parameter to enable or disable the
# continue button in the main menu afterwards. The "show_credits" parameter
# loads the ui/end_credits scene if true. You can configure it to your regular
# credits scene if you want.
#
# @STUB
# @ESC
extends ESCBaseCommand
class_name GameOverCommand
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new(
0,
[TYPE_BOOL, TYPE_BOOL],
[false, true]
)
# Run the command
func run(command_params: Array) -> int:
escoria.logger.report_errors(
"game_over: command not implemented",
[]
)
return ESCExecution.RC_ERROR

View File

@@ -1,10 +1,8 @@
# `play_snd object file [loop]`
# `play_snd file [player]`
#
# Plays the sound specificed with the "file" parameter on the object, without
# blocking. You can play background sounds, eg. during scene changes, with
# `play_snd bg_snd res://...`
# Plays the sound specificed with the "file" parameter on the sound player
# `player`, without blocking. (player defaults to bg_sound)
#
# @STUB
# @ESC
extends ESCBaseCommand
class_name PlaySndCommand
@@ -14,15 +12,31 @@ class_name PlaySndCommand
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new(
2,
[TYPE_STRING, TYPE_STRING, TYPE_BOOL],
[null, null, false]
[TYPE_STRING, TYPE_STRING],
[null, "bg_sound"]
)
# Validate wether the given arguments match the command descriptor
func validate(arguments: Array):
if not escoria.object_manager.has(arguments[0]):
escoria.logger.report_errors(
"play_snd: invalid sound player",
["Sound player %s not registered" % arguments[0]]
)
return false
if not ResourceLoader.exists(arguments[1]):
escoria.logger.report_errors(
"play_snd: invalid parameter",
["File %s not found" % arguments[1]]
)
return false
return .validate(arguments)
# Run the command
func run(command_params: Array) -> int:
escoria.logger.report_errors(
"play_snd: command not implemented",
[]
escoria.object_manager.get_object(command_params[1]).node.set_state(
command_params[0]
)
return ESCExecution.RC_ERROR
return ESCExecution.RC_OK

View File

@@ -1,42 +0,0 @@
# `queue_animation object animation`
#
# Similar to queue_resource, queues the resources necessary to have an
# animation loaded on an item. The resource paths are taken from the item
# placeholders.
#
# @STUB
# @ESC
extends ESCBaseCommand
class_name QueueAnimationCommand
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new(
2,
[TYPE_STRING, TYPE_STRING],
[null, null]
)
# Validate wether the given arguments match the command descriptor
func validate(arguments: Array):
if not escoria.object_manager.objects.has(arguments[0]):
escoria.logger.report_errors(
"queue_animation: invalid first object",
[
"Object with global id %s not found" % arguments[0]
]
)
return false
# TODO: Check if animation is valid
return .validate(arguments)
# Run the command
func run(command_params: Array) -> int:
escoria.logger.report_errors(
"queue_animation: command not implemented",
[]
)
return ESCExecution.RC_ERROR

View File

@@ -53,21 +53,6 @@ func run(command_params: Array) -> int:
if command_params.size() > 2:
dialog_scene_name = command_params[2]
# Manage translation/voice lines keys in the form of:
# line_key:"Default line text"
# If a line_key exists, we'll set it a label as it will automatically be
# translated
var dialog_key_line = command_params[1].split(":", true, 1)
if dialog_key_line.size() > 1:
dialog_key_line[1] = dialog_key_line[1].trim_prefix("\"")
dict = {
"key": dialog_key_line[0],
"line": dialog_key_line[1] if dialog_key_line.size() > 1 \
else dialog_key_line[0],
"ui": dialog_scene_name
}
escoria.current_state = escoria.GAME_STATE.DIALOG
if !escoria.dialog_player:
@@ -80,6 +65,10 @@ func run(command_params: Array) -> int:
)
return ESCExecution.RC_ERROR
escoria.dialog_player.say(command_params[0], dict)
escoria.dialog_player.say(
command_params[0],
dialog_scene_name,
command_params[1]
)
yield(escoria.dialog_player, "dialog_line_finished")
return ESCExecution.RC_OK

View File

@@ -20,7 +20,7 @@ func configure() -> ESCCommandArgumentDescriptor:
# Validate wether the given arguments match the command descriptor
func validate(arguments: Array):
if not escoria.object_manager.objects.has(arguments[1]):
if not escoria.object_manager.has(arguments[1]):
escoria.logger.report_errors(
"sched_event: invalid object",
[

View File

@@ -11,12 +11,16 @@ extends ESCBaseCommand
class_name SlideCommand
# A hash of tweens currently active for animated items
var _tweens: Dictionary
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new(
2,
[TYPE_STRING, TYPE_STRING, TYPE_INT],
[null, null, null]
[null, null, -1]
)
@@ -34,17 +38,64 @@ func validate(arguments: Array):
escoria.logger.report_errors(
"slide: invalid second object",
[
"Object with global id %s not found" % arguments[0]
"Object with global id %s not found" % arguments[1]
]
)
return false
return .validate(arguments)
# Slide the object by generating a tween
#
# #### Parameters
#
# - source: The item to slide
# - destination: The destination item to slide to
# - speed: The speed at which to slide (will default to the
#
# **Returns** The generated (and started) tween
func _slide_object(
source: ESCObject,
destination: ESCObject,
speed: int = -1
) -> Tween:
if speed == -1:
speed = source.node.speed
if _tweens.has(source.global_id):
var tween = (_tweens.get(source.global_id) as Tween)
tween.stop_all()
if (escoria.main as Node).has_node(tween.name):
(escoria.main as Node).remove_child(tween)
var tween = Tween.new()
(escoria.main as Node).add_child(tween)
var duration = source.node.position.distance_to(
destination.node.position
) / speed
tween.interpolate_property(
source.node,
"global_position",
source.node.global_position,
destination.node.global_position,
duration
)
tween.start()
_tweens[source.global_id] = tween
return tween
# Run the command
func run(command_params: Array) -> int:
escoria.logger.report_errors(
"slide: command not implemented",
[]
_slide_object(
escoria.object_manager.get_object(command_params[0]),
escoria.object_manager.get_object(command_params[1]),
command_params[2]
)
return ESCExecution.RC_ERROR
return ESCExecution.RC_OK

View File

@@ -7,44 +7,16 @@
#
# @STUB
# @ESC
extends ESCBaseCommand
extends SlideCommand
class_name SlideBlockCommand
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new(
2,
[TYPE_STRING, TYPE_STRING, TYPE_INT],
[null, null, null]
)
# Validate wether the given arguments match the command descriptor
func validate(arguments: Array):
if not escoria.object_manager.objects.has(arguments[0]):
escoria.logger.report_errors(
"slide_block: invalid first object",
[
"Object with global id %s not found" % arguments[0]
]
)
return false
if not escoria.object_manager.objects.has(arguments[1]):
escoria.logger.report_errors(
"slide_block: invalid second object",
[
"Object with global id %s not found" % arguments[0]
]
)
return false
return .validate(arguments)
# Run the command
func run(command_params: Array) -> int:
escoria.logger.report_errors(
"slide_block: command not implemented",
[]
var tween = _slide_object(
escoria.object_manager.get_object(command_params[0]),
escoria.object_manager.get_object(command_params[1]),
command_params[2]
)
return ESCExecution.RC_ERROR
yield(tween, "tween_all_completed")
return ESCExecution.RC_OK

View File

@@ -1,4 +1,4 @@
# `turn_to object degrees`
# `turn_to object degrees [immediate]`
#
# Turns object to a degrees angle with a directions animation.
#
@@ -6,6 +6,9 @@
# When turning to the destination angle, animations are played if they're
# defined in animations. object must be player or interactive. degrees must
# be between [0, 360] or an error is reported.
#
# Set immediate to true to show directly switch to the direction and not
# show intermediate angles
#
# @STUB
# @ESC
@@ -17,8 +20,8 @@ class_name TurnToCommand
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new(
2,
[TYPE_STRING, TYPE_INT],
[null, true]
[TYPE_STRING, TYPE_INT, TYPE_BOOL],
[null, null, false]
)
@@ -32,13 +35,22 @@ func validate(arguments: Array):
]
)
return false
if arguments[1] < 0 or arguments[1] > 360:
escoria.logger.report_errors(
"turn_to: invalid degrees",
[
"Degree %d not between 0 and 360" % arguments[1]
]
)
return false
return .validate(arguments)
# Run the command
func run(command_params: Array) -> int:
escoria.logger.report_errors(
"turn_to: command not implemented",
[]
)
return ESCExecution.RC_ERROR
(escoria.object_manager.get_object(command_params[0]).node as ESCItem)\
.set_angle(
command_params[1],
command_params[2]
)
return ESCExecution.RC_OK

View File

@@ -15,3 +15,10 @@ var timeout: float
func _init(p_event: ESCEvent, p_timeout: float):
self.event = p_event
self.timeout = p_timeout
# Run the event
#
# **Returns** The execution code
func run() -> int:
return event.run()

View File

@@ -318,7 +318,9 @@ func has_moved() -> bool:
#
# #### Parameters
#
# Set the angle
# - deg: The angle degree to set
# - immediate: Set the angle immediately. If false will show intermediate
# angles
func set_angle(deg: int, immediate = true):
_movable.set_angle(deg, immediate)

View File

@@ -52,7 +52,7 @@ var main_menu_instance
var room_terrain
# Dialog player instantiator. This instance is called directly for dialogs.
var dialog_player
var dialog_player: ESCDialogsPlayer
# Inventory scene
var inventory
@@ -71,7 +71,7 @@ onready var game_size = get_viewport().size
onready var main = $main
# The escoria inputs manager
onready var inputs_manager = $inputs_manager
var inputs_manager: ESCInputsManager
# Savegames and settings manager
var save_manager: ESCSaveManager
@@ -92,6 +92,7 @@ func _init():
self.resource_cache = ESCResourceCache.new()
self.resource_cache.start()
self.save_manager = ESCSaveManager.new()
self.inputs_manager = ESCInputsManager.new()
# Load settings

View File

@@ -1,15 +1,11 @@
[gd_scene load_steps=4 format=2]
[gd_scene load_steps=3 format=2]
[ext_resource path="res://addons/escoria-core/game/main.tscn" type="PackedScene" id=2]
[ext_resource path="res://addons/escoria-core/game/escoria.gd" type="Script" id=3]
[ext_resource path="res://addons/escoria-core/game/inputs_manager.gd" type="Script" id=5]
[node name="escoria" type="Node"]
script = ExtResource( 3 )
[node name="inputs_manager" type="Node" parent="."]
script = ExtResource( 5 )
[node name="main" parent="." instance=ExtResource( 2 )]
[editable path="main"]

View File

@@ -1,14 +1,29 @@
# Escoria inputs manager
# Catches, handles and distributes input events for the game
tool
extends Node
class_name ESCInputsManager
# Valid input flags
# * INPUT_ALL: All input is allowed
# * INPUT_NONE: No input is allowed at all
# * INPUT_SKIP: Only skipping dialogs is allowed
enum {
INPUT_ALL,
INPUT_NONE,
INPUT_SKIP,
}
# The current input mode
var input_mode = INPUT_ALL
# A LIFO stack of hovered items
onready var hover_stack: Array = []
var hover_stack: Array = []
# The global id fo the topmost item from the hover_stack
onready var hotspot_focused: String = ""
var hotspot_focused: String = ""
# Input event handler
@@ -20,7 +35,7 @@ func _input(event: InputEvent) -> void:
if event.is_action_pressed("esc_show_debug_prompt"):
escoria.main.get_node("layers/debug_layer/esc_prompt_popup").popup()
if event.is_action_pressed("ui_cancel"):
if input_mode == INPUT_ALL and event.is_action_pressed("ui_cancel"):
_on_pause_menu_requested()
if ProjectSettings.get_setting("escoria/ui/tooltip_follows_mouse"):
@@ -35,7 +50,7 @@ func _input(event: InputEvent) -> void:
#
# - position: Position of the click
func _on_left_click_on_bg(position: Vector2) -> void:
if hotspot_focused.empty():
if input_mode == INPUT_ALL and hotspot_focused.empty():
escoria.logger.info("Left click on background at ", [str(position)])
escoria.main.current_scene.game.left_click_on_bg(position)
@@ -46,8 +61,10 @@ func _on_left_click_on_bg(position: Vector2) -> void:
#
# - position: Position of the click
func _on_double_left_click_on_bg(position: Vector2) -> void:
if hotspot_focused.empty():
escoria.logger.info("Double left click on background at ", [str(position)])
if input_mode == INPUT_ALL and hotspot_focused.empty():
escoria.logger.info(
"Double left click on background at %s" % str(position)
)
escoria.main.current_scene.game.left_double_click_on_bg(position)
@@ -57,7 +74,7 @@ func _on_double_left_click_on_bg(position: Vector2) -> void:
#
# - position: Position of the click
func _on_right_click_on_bg(position: Vector2) -> void:
if hotspot_focused.empty():
if input_mode == INPUT_ALL and hotspot_focused.empty():
escoria.logger.info("Right click on background at ", [str(position)])
escoria.main.current_scene.game.right_click_on_bg(position)
@@ -68,9 +85,17 @@ func _on_right_click_on_bg(position: Vector2) -> void:
#
# - inventory_item_global_id: The global id of the clicked inventory item
# - event: The input event received
func _on_mouse_left_click_inventory_item(inventory_item_global_id: String, event: InputEvent) -> void:
escoria.logger.info("Inventory item left clicked ", [inventory_item_global_id])
escoria.main.current_scene.game.left_click_on_inventory_item(inventory_item_global_id, event)
func _on_mouse_left_click_inventory_item(
inventory_item_global_id: String,
event: InputEvent
) -> void:
escoria.logger.info(
"Inventory item left clicked %s " % inventory_item_global_id
)
escoria.main.current_scene.game.left_click_on_inventory_item(
inventory_item_global_id,
event
)
# An inventory item was clicked with the RMB
@@ -79,9 +104,18 @@ func _on_mouse_left_click_inventory_item(inventory_item_global_id: String, event
#
# - inventory_item_global_id: The global id of the clicked inventory item
# - event: The input event received
func _on_mouse_right_click_inventory_item(inventory_item_global_id: String, event: InputEvent) -> void:
escoria.logger.info("Inventory item right clicked ", [inventory_item_global_id])
escoria.main.current_scene.game.right_click_on_inventory_item(inventory_item_global_id, event)
func _on_mouse_right_click_inventory_item(
inventory_item_global_id: String,
event: InputEvent
) -> void:
if input_mode == INPUT_ALL:
escoria.logger.info(
"Inventory item right clicked " % inventory_item_global_id
)
escoria.main.current_scene.game.right_click_on_inventory_item(
inventory_item_global_id,
event
)
# An inventory item was doublce-clicked with the LMB
@@ -90,19 +124,33 @@ func _on_mouse_right_click_inventory_item(inventory_item_global_id: String, even
#
# - inventory_item_global_id: The global id of the clicked inventory item
# - event: The input event received
func _on_mouse_double_left_click_inventory_item(inventory_item_global_id: String, event: InputEvent) -> void:
escoria.logger.info("Inventory item double left clicked ", [inventory_item_global_id])
escoria.main.current_scene.game.left_double_click_on_inventory_item(inventory_item_global_id, event)
func _on_mouse_double_left_click_inventory_item(
inventory_item_global_id: String,
event: InputEvent
) -> void:
if input_mode == INPUT_ALL:
escoria.logger.info(
"Inventory item double left clicked " % inventory_item_global_id
)
escoria.main.current_scene.game.left_double_click_on_inventory_item(
inventory_item_global_id,
event
)
# The mouse entered an inventory item
#
# #### Parameters
#
# - inventory_item_global_id: The global id of the inventory item that is hovered
# - inventory_item_global_id: The global id of the inventory item
# that is hovered
func _on_mouse_entered_inventory_item(inventory_item_global_id: String) -> void:
escoria.logger.info("Inventory item focused ", [inventory_item_global_id])
escoria.main.current_scene.game.inventory_item_focused(inventory_item_global_id)
escoria.logger.info(
"Inventory item focused " % inventory_item_global_id
)
escoria.main.current_scene.game.inventory_item_focused(
inventory_item_global_id
)
# The mouse exited an inventory item
@@ -155,9 +203,13 @@ func _on_mouse_exited_item(item: ESCItem) -> void:
# - item: The Escoria item clicked
# - event: The input event from the click
func _on_mouse_left_clicked_item(item: ESCItem, event: InputEvent) -> void:
if hover_stack.empty() or hover_stack.back() == item:
escoria.logger.info("Item left clicked", [item.global_id, event])
escoria.main.current_scene.game.left_click_on_item(item.global_id, event)
if input_mode == INPUT_ALL:
if hover_stack.empty() or hover_stack.back() == item:
escoria.logger.info("Item left clicked", [item.global_id, event])
escoria.main.current_scene.game.left_click_on_item(
item.global_id,
event
)
# An Escoria item was double-clicked with the LMB
@@ -166,9 +218,16 @@ func _on_mouse_left_clicked_item(item: ESCItem, event: InputEvent) -> void:
#
# - item: The Escoria item clicked
# - event: The input event from the click
func _on_mouse_left_double_clicked_item(item: ESCItem, event: InputEvent) -> void:
escoria.logger.info("Item left double clicked", [item.global_id, event])
escoria.main.current_scene.game.left_double_click_on_item(item.global_id, event)
func _on_mouse_left_double_clicked_item(
item: ESCItem,
event: InputEvent
) -> void:
if input_mode == INPUT_ALL:
escoria.logger.info("Item left double clicked", [item.global_id, event])
escoria.main.current_scene.game.left_double_click_on_item(
item.global_id,
event
)
# An Escoria item was clicked with the RMB
@@ -178,8 +237,12 @@ func _on_mouse_left_double_clicked_item(item: ESCItem, event: InputEvent) -> voi
# - item: The Escoria item clicked
# - event: The input event from the click
func _on_mouse_right_clicked_item(item: ESCItem, event: InputEvent) -> void:
escoria.logger.info("Item right clicked", [item.global_id, event])
escoria.main.current_scene.game.right_click_on_item(item.global_id, event)
if input_mode == INPUT_ALL:
escoria.logger.info("Item right clicked", [item.global_id, event])
escoria.main.current_scene.game.right_click_on_item(
item.global_id,
event
)
# The mousewheel was turned

View File

@@ -32,6 +32,13 @@ func _ready():
preload_resources(ProjectSettings.get_setting("escoria/ui/dialogs_folder"))
# Trigger the finish fast function on the dialog ui
func _input(event):
if event is InputEventMouseButton and \
event.pressed:
finish_fast()
# Preload the dialog UI resources
#
# #### Parameters
@@ -72,20 +79,23 @@ func preload_resources(path: String) -> void:
# #### Parameters
#
# - character: Character that is talking
# - params: A dictionary of parameters. Currently only "line" is supported and
# holds the line the character should say
func say(character: String, params: Dictionary) -> void:
# - ui: UI to use for the dialog
# - line: Line to say
func say(character: String, ui: String, line: String) -> void:
is_speaking = true
_dialog_ui = get_resource(params.ui).instance()
_dialog_ui = get_resource(ui).instance()
get_parent().add_child(_dialog_ui)
_dialog_ui.say(character, params)
_dialog_ui.say(character, line)
yield(_dialog_ui, "dialog_line_finished")
is_speaking = false
emit_signal("dialog_line_finished")
# Called when a dialog line is skipped
func finish_fast() -> void:
_dialog_ui.finish_fast()
if is_speaking and\
escoria.inputs_manager.input_mode != escoria.inputs_manager.INPUT_NONE:
_dialog_ui.finish_fast()
# Display a list of choices

View File

@@ -1,19 +1,42 @@
# A dialog GUI showing a dialog box and character portraits
tool
extends PanelContainer
# Signal emitted when a dialog line has started
signal dialog_line_started
# Signal emitted when a dialog line has finished
signal dialog_line_finished
export(String) var current_character setget set_current_character
onready var avatar_node = $MarginContainer/HSplitContainer/VBoxContainer/avatar
onready var name_node = $MarginContainer/HSplitContainer/VBoxContainer/name
onready var text_node = $MarginContainer/HSplitContainer/text
onready var tween = text_node.get_node("Tween")
# The currently speaking character
export(String) var current_character setget set_current_character
# The text speed per character for normal display
export(float, 0.0, 0.3) var text_speed_per_character = 0.1
# The text speed per character if the dialog line is skipped
export(float) var fast_text_speed_per_character = 0.25
# The time to wait before the dialog is finished
export(float) var max_time_to_text_disappear = 1.0
# The node holding the avatar
onready var avatar_node = $MarginContainer/HSplitContainer/VBoxContainer/avatar
# The node holding the player name
onready var name_node = $MarginContainer/HSplitContainer/VBoxContainer/name
# The node showing the text
onready var text_node = $MarginContainer/HSplitContainer/text
# The tween node for text animations
onready var tween = text_node.get_node("Tween")
# Build up the UI
func _ready():
var centered_position_on_screen = Vector2(
ProjectSettings.get_setting("display/window/size/width") / 2,
@@ -21,8 +44,17 @@ func _ready():
) - rect_size / 2
rect_position = centered_position_on_screen
text_node.bbcode_enabled = true
$MarginContainer/HSplitContainer/text/Tween.connect("tween_completed", self, "_on_dialog_line_typed")
$MarginContainer/HSplitContainer/text/Tween.connect(
"tween_completed",
self,
"_on_dialog_line_typed"
)
# Switch the current character
#
# #### Parameters
# - name: The name of the current character
func set_current_character(name: String):
current_character = name
if $dialog_avatars:
@@ -32,32 +64,28 @@ func set_current_character(name: String):
avatar_node.texture = null
"""
Make a character say something.
character: global id of the character who speaks
params: Dictionary
line: line of dialog to say
"""
func say(character : String, params : Dictionary) :
# Make a character say something
#
# #### Parameters
# - character: The global id of the character speaking
# - line: Line to say
func say(character: String, line: String) :
show()
emit_signal("dialog_line_started")
set_current_character(character)
if !params["line"]:
escoria.logger.report_errors("dialog_box_inset.gd:say()", ["No line field in params!"])
return
text_node.bbcode_text = params["line"]
text_node.bbcode_text = tr(line)
text_node.percent_visible = 0.0
var time_show_full_text = text_speed_per_character * len(params["line"])
var time_show_full_text = text_speed_per_character * len(line)
tween.interpolate_property(text_node, "percent_visible",
0.0, 1.0, time_show_full_text,
Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
tween.start()
# Called by the dialog player when the
func finish_fast():
tween.stop(text_node)
tween.interpolate_property(text_node, "percent_visible",
@@ -66,18 +94,18 @@ func finish_fast():
tween.start()
# The dialog line was printed, start the waiting time and then finish
# the dialog
func _on_dialog_line_typed(object, key):
text_node.visible_characters = -1
$Timer.start(max_time_to_text_disappear)
$Timer.connect("timeout", self, "_on_dialog_finished")
# Ending the dialog
func _on_dialog_finished():
escoria.current_state = escoria.GAME_STATE.DEFAULT
emit_signal("dialog_line_finished")
queue_free()
func _input(event):
if event is InputEventMouseButton:
if event.pressed:
finish_fast()

View File

@@ -1,39 +1,51 @@
# A dialog UI using a label above the head of the character
extends RichTextLabel
# Signal emitted when a dialog line has started
signal dialog_line_started
# Signal emitted when a dialog line has finished
signal dialog_line_finished
onready var tween = $Tween
onready var text_node = self
# The text speed per character for normal display
export(float, 0.0, 0.3) var text_speed_per_character = 0.1
# The text speed per character if the dialog line is skipped
export(float) var fast_text_speed_per_character = 0.25
# The time to wait before the dialog is finished
export(float) var max_time_to_text_disappear = 2.0
# Current character speaking, to keep track of reference for animation purposes
var current_character
# Tween node for text animation
onready var tween = $Tween
# The node showing the text
onready var text_node = self
# Enable bbcode and catch the signal when a tween completed
func _ready():
bbcode_enabled = true
$Tween.connect("tween_completed", self, "_on_dialog_line_typed")
"""
Make a character say something.
character: global id of the character who speaks
params: Dictionary
line: line of dialog to say
"""
func say(character: String, params: Dictionary) :
# Make a character say something
#
# #### Parameters
# - character: The global id of the character speaking
# - line: Line to say
func say(character: String, line: String) :
show()
emit_signal("dialog_line_started")
if !params["line"]:
escoria.logger.report_errors("dialog_box_inset.gd:say()", ["No line field in params!"])
return
# Position the RichTextLabel on the character's dialog position, if any.
current_character = escoria.object_manager.get_object(character).node
rect_position = current_character.get_node("dialog_position").get_global_transform_with_canvas().origin
@@ -45,21 +57,19 @@ func say(character: String, params: Dictionary) :
var text_color = current_character.dialog_color
var text_color_html = text_color.to_html(false)
if params["key"] != params["line"]:
text_node.bbcode_text = "[center][color=#" + text_color_html + "]" \
.format([text_color_html]) + tr(params["key"]) + "[/color][center]"
else:
text_node.bbcode_text = "[center][color=#" + text_color_html + "]" \
.format([text_color_html]) + params["line"] + "[/color][center]"
text_node.bbcode_text = "[center][color=#" + text_color_html + "]" \
.format([text_color_html]) + tr(line) + "[/color][center]"
text_node.percent_visible = 0.0
var time_show_full_text = text_speed_per_character * len(params["line"])
var time_show_full_text = text_speed_per_character * len(line)
tween.interpolate_property(text_node, "percent_visible",
0.0, 1.0, time_show_full_text,
Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
tween.start()
# Called by the dialog player when the
func finish_fast():
tween.stop(text_node)
tween.interpolate_property(text_node, "percent_visible",
@@ -68,11 +78,15 @@ func finish_fast():
tween.start()
# The dialog line was printed, start the waiting time and then finish
# the dialog
func _on_dialog_line_typed(object, key):
text_node.visible_characters = -1
$Timer.start(max_time_to_text_disappear)
$Timer.connect("timeout", self, "_on_dialog_finished")
# Ending the dialog
func _on_dialog_finished():
current_character.stop_talking()
emit_signal("dialog_line_finished")