Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added additional say commands #304

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
119 changes: 112 additions & 7 deletions addons/popochiu/engine/objects/character/popochiu_character.gd
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ var default_walk_speed := 0
var default_scale := Vector2.ONE

var _looking_dir: int = Looking.DOWN

# Used to prevent the say_random function saying the same dialog twice in a row.
var _last_random_say_value: int = -1


#region Godot ######################################################################################
Expand Down Expand Up @@ -408,24 +409,67 @@ func face_clicked() -> void:
await face_right()


## Checks if the [param dialog_emotion] string has emotion and dialog elements in it. The function
## splits the [param dialog_emotion] string into 2 array elements if it has a | (pipe) character.
## The string format should be 'emotion|dialog string text'
## The returned array has element 0 as the dialog string, element 1 is the emotion
## This also strips non-printable characters from the start and end of the strings it returns.
## 'emotion|dialog text string' and 'emotion | dialog text string' will be returned the same.
func _return_dialog_emotion_array(dialog_emotion: String) -> PackedStringArray:
var dialog_emotion_array: PackedStringArray = ['','']
var pipe_count: int = dialog_emotion.count('|', 0, 0)

if pipe_count == 0:
# no pipe so string is dialog only
dialog_emotion_array[0] = dialog_emotion.strip_edges()
else:
if pipe_count == 1:
# Only contains 1 | character so split the string into arrays without further checks needed
dialog_emotion_array[0] = dialog_emotion.get_slice('|', 1).strip_edges()
dialog_emotion_array[1] = dialog_emotion.get_slice('|', 0).strip_edges()
else:
# emotion
var emotion := dialog_emotion.get_slice('|', 0)
dialog_emotion_array[1] = emotion.strip_edges()

# dialog
# erase the emotion string text and pipe character
dialog_emotion_array[0] = dialog_emotion.erase(0, emotion.length() + 1).strip_edges()

return dialog_emotion_array


## Calls [method _play_talk] and emits [signal character_spoke] sending itself as parameter, and the
## [param dialog] line to show on screen. You can specify the emotion to use with [param emo]. If an
## [AudioCue] is defined for the emotion, it is played. Once the talk animation finishes, the
## characters return to its idle state.[br][br]
## [param dialog] line to show on screen. If an [AudioCue] is defined for the emotion, it is played.
## Once the talk animation finishes, the characters return to its idle state.[br][br]
## You can define emotions at the start of a dialog string followed by a | (pipe) character.
## Emotion Dialog String example: 'emotion|dialog text you want to say'
## [Obsolete/Deprecated] You can optionally specify the emotion to use with [param emo].
## [i]This method is intended to be used inside a [method Popochiu.queue] of instructions.[/i]
func queue_say(dialog: String, emo := "") -> Callable:
return func (): await say(dialog, emo)


## Calls [method _play_talk] and emits [signal character_spoke] sending itself as parameter, and the
## [param dialog] line to show on screen. You can specify the emotion to use with [param emo]. If an
## [AudioCue] is defined for the emotion, it is played. Once the talk animation finishes, the
## characters return to its idle state.
## [param dialog] line to show on screen. If an [AudioCue] is defined for the emotion, it is played.
## Once the talk animation finishes, the characters return to its idle state.[br][br]
## You can define emotions at the start of a dialog string followed by a | (pipe) character.
## Emotion Dialog String example: 'emotion|dialog text you want to say'
## [Obsolete/Deprecated] You can optionally specify the emotion to use with [param emo].
func say(dialog: String, emo := "") -> void:
if E.cutscene_skipped:
await get_tree().process_frame
return

# splits dialog string into 2 array elements if it has a | character 'emotion|dialog string text'
# array element 0 is the dialog string, array element 1 is the emotion
var dialog_emotion_array: PackedStringArray = _return_dialog_emotion_array(dialog)
dialog = dialog_emotion_array[0]

# only set emo value if the array element is not empty/blank ''
if not dialog_emotion_array[1].is_empty():
emo = dialog_emotion_array[1]

if not emo.is_empty():
emotion = emo

Expand All @@ -449,6 +493,67 @@ func say(dialog: String, emo := "") -> void:
idle()


## Says a random string from the [param dialog_array] PackedStringArray, calling the say function with
## a randomly chosen element of the [param dialog_array]. The function also prevents the same string
## from being said twice in a row. This is useful if you want to say different things each time the
## player interacts with something in the game.
## You can define emotions at the start of a dialog string followed by a | (pipe) character.
## Emotion Dialog String example: 'emotion|dialog text you want to say'
## [i]This method is intended to be used inside a [method Popochiu.queue] of instructions.[/i]
func queue_say_random(dialog_array: PackedStringArray) -> Callable:
return func (): await say_random(dialog_array)


## Says a random string from the [param dialog_array] PackedStringArray, calling the say function with
## a randomly chosen element of the [param dialog_array]. The function also prevents the same string
## from being said twice in a row. This is useful if you want to say different things each time the
## player interacts with something in the game.
## You can define emotions at the start of a dialog string followed by a | (pipe) character.
## Emotion Dialog String example: 'emotion|dialog text you want to say'
func say_random(dialog_array: PackedStringArray) -> void:
var say_value: int = randi_range(0, dialog_array.size() -1)

# make sure new say value has not been used previously
while (say_value == _last_random_say_value):
say_value = randi_range(0, dialog_array.size() -1)

_last_random_say_value = say_value
await say(dialog_array[say_value])


## Says the next string from the [param dialog_array] PackedStringArray, calling the say function with
## first element of the [param dialog_array]. The function will remove the first element of the array
## each time it is called until there is only one element left. The last element of the array
## should be what you want to say when all the other array elements have been said.
## This is useful if you want to say different things each time the player interacts with something
## in the game and then have a final default which is said each time once all the other options are
## said.
## You can define emotions at the start of a dialog string followed by a | (pipe) character.
## Emotion Dialog String example: 'emotion|dialog text you want to say'
## [i]This method is intended to be used inside a [method Popochiu.queue] of instructions.[/i]
func queue_say_next(dialog_array: PackedStringArray) -> Callable:
return func (): await say_next(dialog_array)


## Says the next string from the [param dialog_array] PackedStringArray, calling the say function with
## first element of the [param dialog_array]. The function will remove the first element of the array
## each time it is called until there is only one element left. The last element of the array
## should be what you want to say when all the other array elements have been said.
## This is useful if you want to say different things each time the player interacts with something
## in the game and then have a final default which is said each time once all the other options are
## said.
## You can define emotions at the start of a dialog string followed by a | (pipe) character.
## Emotion Dialog String example: 'emotion|dialog text you want to say'
func say_next(dialog_array: PackedStringArray) -> void:
var dialog_text: String = dialog_array[0]

if (dialog_array.size() > 1):
# Arrays are passed by reference so this is removing value from the array passed to the function
dialog_array.remove_at(0)

await say(dialog_text)


## Calls [method _play_grab] and waits until the [signal grab_done] is emitted, then goes back to
## [method idle].[br][br]
## [i]This method is intended to be used inside a [method Popochiu.queue] of instructions.[/i]
Expand Down