You seem to be mixing a couple of separate solutions.
Firstly... your use of variables.
For "normal" operations, people tend to explicitly use two difference datastores for variables.
store
and
persistent
.
store
variables are the ones you'd normally access during a game. If you code
$ tips = False
, that's actually
store.tips
. Likewise if you have
define tips = False
or
default tips = False
- those are both using
store.tips
too.
The
store
datastore is effectively dumped to the save files (sort of) when you save. It is used to hold variables that will change per playthrough. Just because a value is True now, doesn't mean it will be True when a player restarts a new game.
persistent
variables exist outside of the current gameplay loop. They hold values that aren't tied to choices made by the player. An unlocked achievement for example will still be unlocked if the player starts a new game.
However, these aren't the only two datastores. There is also a
preferences
datastore, which is VERY like the
persistent
datastore. Values set now will persist, even if the player starts a new playthrough. Otherwise, you'd end up with annoying stuff like having to set fullscreen on/off when you started the game up... or set the music volume or any of that stuff.
Your mix of
action SetVariable("tips")
and
action SetPreference("tips")
means you are using two entirely separate variables to control the same thing (
store.tips
and
preferences.tips
). Using
action SetVariable()
doesn't make sense here at all, since it isn't something that you'd want to reset if the player started a new game.
It isn't clear to me that developers are supposed to add their own custom preferences. The reason I say that is because there is a finite
You must be registered to see the links
. But the screen action
You must be registered to see the links
doesn't use those exact same names. For example,
preferences.afm_time
controls how fast or slow the auto text advance feature works. But the screen action to control that is
action Preference("auto-forward time")
. Exactly how it makes a connection between "auto-forward time" and
"afm_time
isn't clear to me. Plus while testing, RenPy threw an exception whenever I tried to reference my custom preference variable that way. That said, whilst
action Preference()
doesn't work with unrecognized preferences...
You must be registered to see the links
and
You must be registered to see the links
work just fine. As does accessing the current value using
gui.preference("myprefhere")
. Given that
action Preference()
is supposed to be the preferred method and it doesn't support custom preferences, I'm leaning toward "it's likely not supposed to be done that way".
For that reason only, you might consider storing your custom preferences in
persistent
rather than
preferences
. Though I can see the temptation. Clearly there are mechanisms to make it work with
preferences
though, so maybe I'm just being overly cautious about some legacy code that doesn't fit how I think it should work.
Edit: The article linked below by
crabsinthekitchen by the RenPy author himself implies I'm wrong though. I do note however he uses
action Preference()
for all the existing preferences and
action SetField(preferences, ...)
for his custom stuff. That article may or may not pre-date
You must be registered to see the links
).
But who am I to say PyTom is inconsistent.
You must be registered to see the links
Secondly, how things like preferences show as toggled on/off.
A somewhat hidden function of what a screen action does is how it deals with a screen object property
.selected
. If when displaying something as part of a screen, RenPy decides that the screen action is already
True
, then it flags that text/image/button as
selected
(unless explicitly overridden). This has a knock-on effect to the text/image/button's use of
style
. And since styles for the majority of the pre-existing RenPy screens are all inherited, it's not always obvious where the actual display style came from.
For example, the
screen quick_menu()
includes a toggle for text auto-forward/auto-advance. It shows as "Auto" in most games.
It's simply
textbutton _("Auto") action Preference("auto-forward", "toggle")
Yet, when playing a game, clicking this text button often changes the color of the word "Auto" to indicate whether it is On or Off.
It takes some backtracking of
style quick_button_text:
to link things back to two lines in the
gui.rpy
:
define gui.quick_button_text_idle_color = gui.idle_small_color
define gui.quick_button_text_selected_color = gui.accent_color
The
selected_color
and
idle_color
affect the colors, but there is no obvious connection between
action Preference()
and whether the
.selected
property is set
True
or
False
. And if it's mentioned in the documentation, I've not seen it. But... all screen actions set
.selected
to be True or False... it's just a bit of a leap of faith as to how.
The same mechanism controls whether radio buttons are shown with a mark (bar or tick or something) next to them.
My guess is that your buttons are locked to showing as True because you've coded multiple actions (due to using multiple variables). Once you simplify that, it should end up working as intended.