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

Conversation

anthonyirwin82
Copy link
Contributor

@anthonyirwin82 anthonyirwin82 commented Oct 6, 2024

Many point and click adventure games say something different each time you interact with a game object. Some games have randomly chosen text and others go through a list of set dialog and have a default after all options have been said.

I have added the following functions to make this easy for Popochiu users to do:

  • queue_say_random(say_array: PackedStringArray)
  • say_random(say_array: PackedStringArray)
  • queue_say_next(say_array: PackedStringArray)
  • say_next(say_array: PackedStringArray)

Below is an example of usage used while I was testing this:

var use_random_array: PackedStringArray = [
	"First line",
	"Second line",
	"third line"
]

var use_next_array: PackedStringArray = [
	"First line",
	"Second line",
	"third line",
	"Last and default line"
]


func _on_click() -> void:
	await C.player.walk_to_clicked()
	await C.player.face_clicked()
	await C.player.say_random(use_random_array)


func _on_right_click() -> void:
	await C.player.walk_to_clicked()
	await C.player.face_clicked()
	await C.player.say_next(use_next_array)

say_random() will choose a random string from the array that is passed to it and makes sure it does not say the same thing twice in a row.

say_next() will say the first element in the array and remove the first element until only 1 element remains. Then it will say that each time say_next() is used.

…y) and say_next(say_array: PackedStringArray) functions.
…ay_array to be dialog_array to match say() function naming convention.
@anthonyirwin82
Copy link
Contributor Author

anthonyirwin82 commented Oct 6, 2024

I updated this to support emotions as well. If the emo_array is not the same length as the dialog_array then it will append blank strings to the emo_array to make them match. By default, the user does not need to provide any emo values, the same as the say() function.

I have tested this without passing any emo_array values and by providing an emo_array that does not match the dialog_array size to ensure that it works correctly.

var use_random_array: PackedStringArray = [
	"First line",
	"Second line",
	"third line"
]

var use_next_array: PackedStringArray = [
	"First line",
	"Second line",
	"third line",
	"Last and default line"
]

var use_emo_array: PackedStringArray = [
	'',
	'',
]


func _on_click() -> void:
	await C.player.walk_to_clicked()
	await C.player.face_clicked()
	await C.player.say_random(use_random_array, use_emo_array)


func _on_right_click() -> void:
	await C.player.walk_to_clicked()
	await C.player.face_clicked()
	await C.player.say_next(use_next_array, use_emo_array)

@stickgrinder
Copy link
Collaborator

Hi @anthonyirwin82. I was reviewing this PR of yours with @mapedorr.

First of all, thanks for that, it is a very good addition :) The only thing we think may be cumbersome is keeping emotions and strings in different arrays. It requires a bit of attention and it's error prone.

An easier solution for the dev would be to specify emotions alongside strings. Using a dictionary is a bit inconvenient, but a possible solution is this:

We can use a pipe character | as a marker to insert the emotion at the beginning of the string, like this:

angry|I don't want to pick THAT up!

And escape it if you REALLY want your character to say a pipe:

The password is "1234\|qwer"

This approach can be ported for consistency to the say functions we already have in place, maybe?

That way one has to populate just one array and each string will have its emotion attached, only where there are needed.
What do you think?

@anthonyirwin82
Copy link
Contributor Author

The two arrays is error prone which is why I had the code to create empty strings in the emo_array if the array sizes didn't match.

The | formatting is a nicer way to do it. I did it with the two arrays to try to match the existing say command.

I will update this.

… to allow 'emotion|dialog text' in the string
@anthonyirwin82
Copy link
Contributor Author

anthonyirwin82 commented Oct 7, 2024

In Godot \| throws an invalid escape character error and will not let you use it. I considered using a different character as an escape character but realised we only care about the first | character that separates the emotion.

So 'emotion|dialog text that has multiple | characters in it with another | for good measure will still work'

If the user wants to use pipe characters in a dialog text they will need to define an emotion even if they don't use it.

I left the say command with the same parameters so it still works with the old format, so people with existing games will not need to change anything but can also use the new | delimited strings.

I also strip out spaces and other non-printable characters from the beginning and end of strings, so users can also do 'emotion | dialog text' without any issues.

Below is an example of what I used in testing:

var use_random_array: PackedStringArray = [
	"emotion|First line",
	"emotion | Second line",
	"emotion | third line"
]

var use_next_array: PackedStringArray = [
	"emotion|First line",
	"emotion|Second line",
	"emotion|third line has multiple | characters",
	"emotion | Last and default line | has multiple | characters"
]


func _on_click() -> void:
	await C.player.walk_to_clicked()
	await C.player.face_clicked()
	await C.player.say_random(use_random_array)


func _on_right_click() -> void:
	await C.player.walk_to_clicked()
	await C.player.face_clicked()
	await C.player.say_next(use_next_array)

@anthonyirwin82
Copy link
Contributor Author

Actually you can do pipes in dialog without having an emotion by doing '|dialog text string with | pipe characters | another one for good measure'.

This will treat the first pipe as the emotion delimiter and will be a blank empty string and not used. The other pipes that are part of the dialog text will work as expected.

@stickgrinder
Copy link
Collaborator

stickgrinder commented Oct 19, 2024

Note to self: review the implementation in the light of what we have in popochiu_character_helper.gd from line 54.

@stickgrinder stickgrinder added the improvement New feature or request label Oct 20, 2024
@stickgrinder
Copy link
Collaborator

stickgrinder commented Nov 2, 2024

@anthonyirwin82 I took the time to review this PR again and I think before merging it we need to rethink a bit the say functions.

Here is a quick explanation, I'll go into more details after discussing this with @mapedorr.

The E.run() short syntax for dialogues accepts stuff link:

"Guybrush: I want to be a pirate!"
"Guybrush(happy): This is the happiest day of my life!"
"Guybrush[3]: Three seconds later..."
"Guybrush(sad)[5]: Why did the ship sink?"
"Guybrush[2](angry): That's the second time today!"

with the name of the character specified as the first element, a couple of optional params for duration and emotion in random order and the line after a : token.

My proposal to use a pipe to separate emotions was misinformed about what we already had in place. The current implementation of say() takes two params, one for the emotion, but the best option would be to make it support a similar syntax as we have for E.run(), just omitting the character name, like in these examples:

"I want to be a pirate!"
"(happy): This is the happiest day of my life!"
"[3]: Three seconds later..."
"(sad)[5]: Why did the ship sink?"
"[2](angry): That's the second time today!"

This way we can have a consistent use across all the plugin. Since we're messing with strings in a way that may collide with the devs intentions (even if it's very unlikely), we need to understand how to escape this whole thing. We also need to decide if we want to have more emotions or timings in the same say command, like:

"Guybrush: I want to be a pirate! (happy): A happy one! [2]: And a very fast talking one, too!"

This is a bit of a stretch, but once we have this nailed down I would ask you if you want to help us implement this as god intended.

@stickgrinder
Copy link
Collaborator

@anthonyirwin82 sorry for letting this stale, I'm not ignoring it, just need some time to wrap my head over this topic and talk to @mapedorr about it.

The contribution is still valuable, we just need to make it organic with the rest of the code.
Thanks for your patience.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
improvement New feature or request
Projects
Status: In progress
Development

Successfully merging this pull request may close these issues.

2 participants