Page 1 of 1

Best way to add inline lua markup tag?

Posted: Sun Feb 02, 2020 4:45 am
by digiwombat
Hey!

I have a bit of in-line Lua that I use to check gender and return the appropriate pronoun or whatever word ("Hey young man/woman").

Code: Select all

You are a [lua(return Variable["Gender"] == "Male" and "male" or "female" )].
I'd really prefer to have that node's text look something like this:

Code: Select all

You are a [g("male", "female")].
I looked at registering functions and that doesn't seem to be where I want to go to achieve this so I'd appreciate any help because this will really help out writing dialogue and for localization as well.

EDIT:
Nevermind. Looking at FormattedText.cs, it's looking like adding my own tag would be messy so I'm just rolling it out into a function that ends up being [lua(g("male", "female"))], which is close enough.

Here's the code in case anyone else wants to do the same thing:

Code: Select all

public class LUAGenderCheck : MonoBehaviour
{

	public string playerGenderVariable = "Male";
	
	private void OnEnable()
	{
		Lua.RegisterFunction("g", this, SymbolExtensions.GetMethodInfo(() => GetPlayerGender(String.Empty, String.Empty)));
	}

	public string GetPlayerGender(string male, string female)
	{
		return playerGenderVariable == "Male" ? male : female;
	}
}
Then in a node, just do this wherever you want to have gendered dialogue:

Code: Select all

You are a [lua(g("male", "female"))].
EDIT2:
Better version in my reply below.

Re: Best way to add inline lua markup tag?

Posted: Sun Feb 02, 2020 10:55 am
by Tony Li
Thanks for sharing!

Re: Best way to add inline lua markup tag?

Posted: Sun Feb 02, 2020 3:38 pm
by digiwombat
I decided to go with an OnConversationLine version that properly adds the tag the way the other tags are added because I got sick of typing lua() after about two nodes of doing it. The syntax for a node now looks like this:

Code: Select all

[g=He/She] sure seems like a great [g=guy/girl]!
Here's that version:

Code: Select all

void OnConversationLine(Subtitle subtitle)
{
	const string genderStartTag = "[g=";
	const int maxReplacements = 100;

	if (subtitle.formattedText.text.Contains(genderStartTag))
	{
		Regex regex = new Regex(@"\[g=[^\]]*\]");
		int endPosition = subtitle.formattedText.text.Length - 1;
		int numReplacements = 0; // Sanity check to prevent infinite loops in case of bug.
		while ((endPosition >= 0) && (numReplacements < maxReplacements))
		{
			numReplacements++;
			int genderTagPosition = subtitle.formattedText.text.LastIndexOf(genderStartTag, endPosition, System.StringComparison.OrdinalIgnoreCase);
			endPosition = genderTagPosition - 1;
			if (genderTagPosition >= 0)
			{
				string firstPart = subtitle.formattedText.text.Substring(0, genderTagPosition);
				string secondPart = subtitle.formattedText.text.Substring(genderTagPosition);
				string secondPartVarReplaced = regex.Replace(secondPart, delegate (Match match)
				{
					Debug.Log(match.Value);
					string genderText = match.Value.Substring(3, match.Value.Length - 4).Trim(); // Remove "[var=" and "]"
					try
					{
						return GameData.Instance.playerGender == "Male" ? genderText.Split('/')[0] : genderText.Split('/')[1];
					}
					catch (System.Exception)
					{
						if (DialogueDebug.logWarnings) Debug.LogWarning(string.Format("{0}: Failed to get gender text: '{1}'", new System.Object[] { DialogueDebug.Prefix, genderText }));
						return string.Empty;
					}
				});
				subtitle.formattedText.text = firstPart + secondPartVarReplaced;
			}
		}			
	}
}
Minor side note: I'd hoped to use the pipe symbol as my separator (as is tradition), but I can only get the formatted text and pipe is reserved for Forced New Line, so it's a forward slash which is unlikely to show up in any give use of this function... in my game, anyway. Just something to keep in mind of if you use this and your text needs a slash for some reason.