As usual,
@anne O'nymous has given a nice, detailed description.
Just for discussion's sake, it's probably worth noting that, when implementing a "straight replacement" say_menu_text_filter as described by
@anne O'nymous, you're essentially doing something similar to what Ren'py does itself when applying a
You must be registered to see the links
- taking the original text and transforming it into some alternate text. The Ren'py translation support is more sophisticated, of course, in that you can replace a single line of dialog with multiple or vice versa. (Note that I'm
not saying that the underlying mechanisms are the same - they're actually quite different - just that the concepts are at least vaguely similar.)
So, to echo some of the issues:
- In the "look the entire line up in a map or an if statement and find the replacement line" approach, you potentially end up with a very large list of strings to replace. In addition, the input strings have to exactly match those in the dialog. Change a space or a capital letter, and the line won't match. This can make for some tedious work in creating and maintaining the replacement map. Doable, just tedious.
- Taking a "use a regex to replace 'Landlady' with 'Mom'" approach, you can cut down on the amount of work you have to do, because you don't have to "map replace" every single line of text that uses "Landlady" and wants to be changed to "Mom." However, depending on the exact text you're working with, you can sometime run into problems with designing the replacements. Plurals and articles and things like that.
- Neither of these approaches allow you to add additional lines of dialog, or remove them. To do that, you're going to have to resort to either putting labels around the block and using label replacement, or else use the language translation features. (Which can map N lines of input to M lines of output.)
As just an example of the second issue, consider the line
Code:
e "Hey, did you talk to the landlady?"
e "We both have hot landladies, don't we?"
In this case, you probably want the replacement to be
Code:
e "Hey, did you talk to Mom?"
e "We both have hot Moms, don't we?"
so you have to factor in the "the" and the plural in your replacement strategy. This is all doable, of course, it's just stuff you have to watch out for, particularly if you're using "word replacement" instead of "line replacement".
One other thing to point out is that the say_menu_text_filter is called
before any text substitution is performed on the string. So if you have:
Code:
$ var = 'Monday'
e "Today is [var]"
the string your filter function will receive is
"Today is [var]"
, not
"Today is Monday"
. This is a good thing, because if you have something like:
Code:
e "Hey, [player_name], did you talk to the landlady?"
you can still potentially do the "replace the entire string using a map" without having to worry about all the potential values that
player_name
could take on.
So, what about using Ren'py's translation support for this? Theoretically doable. The basic steps would be:
- Create a "translation" for a language. Maybe call the language "uncensored."
- Update the text where necessary
- Include the "uncensored language" files in your patch. (i.e. the files in
game/tl/uncensored
- Have your patch include (probably as a late-stage init) a call to
renpy.change_language()
This approach has some power, but also some pitfalls
Pros:
- Ren'py generates files for you with all the items that have to be reviewed. So this partially automates the process of generating the "input" strings.
- You can alter the number of lines spoken in places, if you need to.
Cons:
There are some ways to get around the second issue, but they can be just as much of a pain. So while using an "uncensored translation" is a theoretically viable approach, it has its own set of issues. One of its few redeeming features is the "change the number of lines" feature, but you can get around that with the label replacement approach.
All of this assumes you're trying to 100% completely squeaky clean and have no trace whatsoever of your intent to publish uncensored text. There is an interim approach, in which you could set up replaceable text as variables, and have your patch change the values of the variables. So you use something like:
Code:
e "Hey, [player_name], did you talk to [the_landlady_name]?"
and then have your base code set
the_landlady_name
to "the landlady" and your patch overwrite it to "Mom" later in the init sequence. Now, this does, to a small extent, expose the fact that you intended to muck about with text. But if you ever got called out on this (very unlikely) you could probably defend having coded that way by saying "Oh, we originally planned to allow people to change the names of the characters, and then abandoned that, but didn't go back and rewrite everything." Hard for someone to prove otherwise. Of course, if you take this approach, you want to make sure that your variable names are benign. Like, use "landlady_name" instead of "mom_name", since the latter kind of exposes your intent.
Anyway, since the thread title asked about approaches to patches, not just say_menu_text_filters, that's my $0.02 or $0.03 on the issue, over and above what
@anne O'nymous gave you.