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
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.
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: