I’ve been having a few discussions with people lately about custom RenPy commands, and generally recommending them because you get the ability to lint your game scripts.
For example, the fact that I have lint checks on my commands to show sprites, and change their expressions, helped me catch a bunch of typos and misordered arguments during sprite staging, which would have been a huge pain to track down later (and that would have resulted in exceptions during gameplay).
Given the benefits of lint, I wanted to share an extremely small example for something that I could have easily done manually: Changing characters’ facial hair in the game.
First off, the code:
python early:
def parse_showstubble(lex):
who = lex.simple_expression()
level = lex.rest()
return (who, level)
def lint_showstubble(o):
who, level = o
if len(o) != 2 or who is None or level is None:
renpy.error("Invalid showstubble declaration")
return
if who != "adam" and who != "james":
renpy.error("Invalid person " + who)
return
try:
lvlint = int(level)
if lvlint < 0 or lvlint > 3:
renpy.error("Invalid level " + level)
except ValueError:
renpy.error("Invalid level " + level)
def execute_showstubble(o):
who, level = o
if not who in store.spposes_data:
store.spposes_data[who] = CharPoses()
lvlint = int(level)
if lvlint == 1:
store.spposes_data[who].stubble = "_sblight"
elif lvlint == 2:
store.spposes_data[who].stubble = "_sbheavy"
elif lvlint == 3:
store.spposes_data[who].stubble = "_sbbeard"
else:
store.spposes_data[who].stubble = ""
renpy.register_statement("showstubble", parse=parse_showstubble, execute=execute_showstubble, lint=lint_showstubble)
This then gets used in game code like
showstubble adam 1
It’s worth noting I could have easily not added this command, and simply written
$ sposes_data['adam'].stubble = "_sblight"
However. the benefit of doing it this way, again, is the lint checks. If you accidentally try to set stubble on someone else (say, Jake), or if you fat-finger the stubble value (23), you’ll get a pre-runtime error. Versus if you do that directly (say, “sblightr”), you’ll get an ugly runtime error only when you hit that line of code.
I’d argue there’s very little that isn’t worth making a custom command for. In addition to this, I have them for Instant Messaging in addition to Sprites and even the day transition code. In addition to linting, this gives you the ability to easily change something en masse (like when I wanted a day transition to also update the save identifier string).