Working on updating from Ren’Py version 6.99 to 7.22, which has loads of optimizations. First feature to fix: menus appearing in NVL mode (the large textbox that covers half the screen)! Thumbnail art by Discord member Dally.
NVL Menu

NVL menu example
Prior to 7.22, we had to override a built-in function to get the NVL menu to display properly. Without proper display, it would do something silly like showing the ADV-styled menu even during NVL mode.

Choices are hidden behind the NVL window

NVL menu disappeared and the choices are floating free-form
Those are just two such examples of bad menu behavior.
Overridden function below, adapted from a code snippet found somewhere on the Internet.
# def menu(items, interact=True, screen="choice"):
# if use_nvl_menu:
# #overwriting the NVL_MENU FUNCTION BUT WITHIN THE NORMAL ONE
# renpy.mode('nvl_menu')
# if nvl_list is None:
# store.nvl_list = []
# screen = None
# if renpy.has_screen("nvl_choice"):
# screen = "nvl_choice"
# elif renpy.has_screen("nvl"):
# screen = "nvl"
# if screen is not None:
# widget_properties, dialogue = nvl_screen_dialogue()
# for i in dialogue:
# print(i)
# rv = renpy.display_menu(
# items,
# widget_properties=widget_properties,
# screen=screen,
# scope={"dialogue": dialogue},
# window_style=style.nvl_menu_window,
# choice_style=style.nvl_menu_choice,
# choice_chosen_style=style.nvl_menu_choice_chosen,
# choice_button_style=style.nvl_menu_choice_button,
# choice_chosen_button_style=style.nvl_menu_choice_chosen_button,
# type="nvl",
# )
# for label, val in items:
# if rv == val:
# choice = label
# choice = "{u}" + str(choice) + "{/u}"
# mc.add_history(kind="adv", who="", what=choice)
# return rv
# # Traditional version.
# ui.layer("transient")
# ui.clear()
# ui.close()
# ui.window(style=__s(style.nvl_window))
# ui.vbox(style=__s(style.nvl_vbox))
# for i in nvl_list:
# if not i:
# continue
# who, what, kw = i
# rv = renpy.show_display_say(who, what, **kw)
# renpy.display_menu(items, interact=False,
# window_style=__s(style.nvl_menu_window),
# choice_style=__s(style.nvl_menu_choice),
# choice_chosen_style=__s(style.nvl_menu_choice_chosen),
# choice_button_style=__s(style.nvl_menu_choice_button),
# choice_chosen_button_style=__s(style.nvl_menu_choice_chosen_button),
# )
# ui.close()
# roll_forward = renpy.roll_forward_info()
# rv = ui.interact(roll_forward=roll_forward)
# renpy.checkpoint(rv)
# for label, val in items:
# if rv == val:
# choice = label
# choice = "{u}" + str(choice) + "{/u}"
# mc.add_history(kind="adv", who="", what=choice)
# return rv
# else:
# newitems = []
# for label, val in items:
# if val == None:
# narrator(label, interact=False)
# else:
# newitems.append((label, val))
# rv = renpy.display_menu(newitems, interact=interact, screen=screen)
# # # logging menu choice label.
# for label, val in items:
# if rv == val:
# choice = label
# choice = "{u}" + str(choice) + "{/u}"
# mc.add_history(kind="adv", who="", what=choice)
# return rv
# def nvl_screen_dialogue():
# """
# Returns widget_properties and dialogue for the current NVL
# mode screen.
# """
# widget_properties = {}
# dialogue = []
# for i, entry in enumerate(nvl_list):
# if not entry:
# continue
# who, what, kwargs = entry
# if i == len(nvl_list) - 1:
# who_id = "who"
# what_id = "what"
# window_id = "window"
# else:
# who_id = "who%d" % i
# what_id = "what%d" % i
# window_id = "window%d" % i
# widget_properties[who_id] = kwargs["who_args"]
# widget_properties[what_id] = kwargs["what_args"]
# widget_properties[window_id] = kwargs["window_args"]
# dialogue.append((who, what, who_id, what_id, window_id))
# return widget_properties, dialogue
Whenever we wanted to use an NLV-styled menu, we would set the flag use_nvl_menu=True
and then have to remember to set it back to False after the player has made a choice (this step could be automated…).
Now, 7.22 has native-support for NVL-menus within the default menu function. That means that our previous overriden menu function acts unexpectedly (everything breaks again). To use the new native NVL-menu, we do:
nn "A few moments later, he leaned towards me, this time sniffing close to my neck."
$_window_hide(trans=None) #forces the nvl menu to show up without blinking; window hide would make it blink b/c of using default window hide trans
menu(nvl=True):
"What are you—":
window show #makes it so that the window doesn't blink since it is technically not showing yet
nvl clear
"Get the hell away from—":
window show
nvl clear
$ renpy.pause(0.4, hard=False)
mn "Heh, heh. A little on edge, aren't we?"
nvl clear
$ renpy.pause(0.4, hard=False)
show markus 1_nvl with Dissolve (0.2)
There are a couple issues in the above version, namely with all the window blinking. You may recall this Blinking effect in a previous version of the game (or maybe in one of our other games–it’s a bit difficult to remember exactly where it appeared previously). The window blinks because it’s technically in a hidden state, and then a default transition says to Hide the window, which makes it appear before applying the hiding transition.
Default transitions:
config.window_show_transition = Dissolve(.2)
config.window_hide_transition = Dissolve(.2)
$_window_hide(trans=None)
overrides the default transition to make it so that nothing happens (which keeps the current NVL screen up in its current/earlier state).
If we were only using NVL mode in the entire game, then we could switch the transition code to something like:
config.window_show_transition = None
config.window_hide_transition = None
But we switch back and forth between the two dialogue layouts, so we made a small function for changing the transition type based on which sort of layout we’re in. It’s a bit similar to having to set the use_nvl_menu
flag before.
init python:
def n_mode(mode):
if mode == "nvl":
config.window_show_transition = None
config.window_hide_transition = None
config.empty_window = nvl_show_core
else:
config.window_show_transition = Dissolve(.2)
config.window_hide_transition = Dissolve(.2)
config.empty_window = _default_empty_window
Now, whenever we switch between ADV and NVL modes, we just have to remember to add the line $n_mode("nvl")
or $n_mode("adv")
.
You may notice that after both choices, we still have to manually add the line window show
to prevent yet another blinking problem. One way around that is to define a “callback” function that is run as soon as a player makes a choice. That’s still on the TO-DO list though, so we won’t be talking about how to do that this time around!
Game dev poem
Where have all the artists gone?
Why won’t the code cooperate;
Where did I leave off in that script?
This GUI is not first rate…
Oh, woooes of a dev,
Oh, oh, oh, wooooes of a dev…
Assets are overdue, my VA missed their cue,
Ohhh the woooooes of a dev!
Late last night, a bug arose;
When it was fixed, our new build crashed!
I couldn’t find a proper font;
My new sprite files all got trashed…
This bug request’s not for our game;
Why won’t this mobile build install?
The OP makes my laptop crash;
These background files are all too small…
Oh, woooes of a dev,
Oh, oh, oh, woooes of a dev…
Last update broke our code, these files won’t upload,
Ohhh the woooooes of a dev!
Oh, woooes of a dev,
Oh, oh, oh, woooes of a dev…
Someday it all will end, and then we’ll start again,
Ohhh the woooooes of a dev!
– glasses garden
Inspired by: