Codes: Sprite expression changes

Last time, we added a custom showsp command to easily show sprites that obey game settings automatically. But that can be tedious to use if all you want to do in a scene is change a character’s expression when they’re already onscreen. Cue showexp!

A couple of changes to the old code are necessary. First of all, we need to store the raw names for the clothing (you’ll see why in a moment).

python early:
class CharPoses:
pose = ""
pants = ""
shirt = ""
expression = ""
extras = ""
oldclothes = ""
basepantsstr = ""
baseshirtstr = ""
baseextrasstr = ""
def execute_showsp(o):
…same as before…
if not who in store.spposes_data:
store.spposes_data[who] = CharPoses()
store.spposes_data[who].pose = pose
store.spposes_data[who].baseshirtstr = shirt
store.spposes_data[who].basepantsstr = pants
store.spposes_data[who].baseextrasstr = extras
store.spposes_data[who].shirt = help_get_filepathsp(who, pose, "s", shirt)
store.spposes_data[who].pants = help_get_filepathsp(who, pose, "p", pants)
store.spposes_data[who].expression = help_get_filepathsp(who, pose, "e", expr)
store.spposes_data[who].extras = help_get_filepathsp(who, pose, "x", extras)
…same as before…

Next, we define the parser and lint for showexp. Note that we’re allowing changes to the pose, as well, so this can be called as either showexp adam happy or showexp adam happy crossed.

python early:
def parse_showexp(lex):
who = lex.simple_expression()
expr = lex.simple_expression()
if lex.eol():
return (who, None, expr)
pose = lex.simple_expression()
return (who, pose, expr)
def lint_showexp(o):
who, pose, expr = o
if len(o) != 3 or expr is None:
renpy.error("Invalid showsp declaration")
return
if not who in showsp_valid_combos:
renpy.error("Invalid person " + who)
return
if pose is None:
# don't know the pose so check across poses
# may fail if a given expr only exists for one pose
# but we can't track current pose state
hasExpr = "e_" + expr in showsp_valid_combos[who]["!any"]
if not hasExpr:
for pose in showsp_valid_combos[who]:
hasExpr = "e_" + expr in showsp_valid_combos[who][pose]
if hasExpr:
break
if not hasExpr:
renpy.error("Invalid expression " + expr + " for " + who)
else:
if not pose in showsp_valid_combos[who]:
renpy.error("Invalid pose " + pose + " for " + who)
return
if not "e_" + expr in showsp_valid_combos[who][pose] and not "e_" + expr in showsp_valid_combos[who]["!any"]:
renpy.error("Invalid expression " + expr + " for " + who + pose)

Note the documented limitation in linting. Since we don’t always have the pose information, if you have an expression that exists only for one pose, this will be missed by linting. (So make sure all expressions exist in some base form, and override them on a per-pose basis as necessary, to prevent this.)

Finally, the actual execute command, where we use the information we’d previously stored in the new fields:

    def execute_showexp(o):
who, pose, expr = o
if not who in store.spposes_data:
renpy.error("Invalid person " + who)
if pose is not None:
if store.spposes_data[who].pose != pose:
# force all other components to re-render as necessary when pose changes
store.spposes_data[who].shirt = help_get_filepathsp(who, pose, "s", store.spposes_data[who].baseshirtstr)
store.spposes_data[who].pants = help_get_filepathsp(who, pose, "p", store.spposes_data[who].basepantsstr)
store.spposes_data[who].extras = help_get_filepathsp(who, pose, "x", store.spposes_data[who].baseextrasstr)
store.spposes_data[who].pose = pose
else:
pose = store.spposes_data[who].pose
store.spposes_data[who].expression = help_get_filepathsp(who, pose, "e", expr)
renpy.register_statement("showexp", parse=parse_showexp, execute=execute_showexp, lint=lint_showexp)

This will probably also fail if a particular shirt, pants, or extra exists only for one pose and you change pose as part of the command. Again, to be safe, make sure everything a character could be wearing exists at some form at the base level, or just don’t change poses around when using the command.

In any case, now you can more easily carry on a conversation without having to remember what a character was wearing in the same scene (or even where they’re standing, which is an improvement over the basic game’s show command, as well).

showsp adam sides greent jeans happy
adam "This is only a test. How do I look?"
showexp adam worried
adam "Does this look okay?"
showsp adam crossed bluet slacks curious jacket left
adam "Now I'm over here, and in blue. Huh."
showexp adam confused
adam "Strange."
showexp adam default crossed
adam "Oh well."
showexp adam grin sides
adam "It's nice to meet you anyway."

Yay! One last thing: Calling showexp before showsp will probably do nothing, since changing variables around while a sprite is offscreen has no effect. So if your script has a lot of jumps in it, you probably want to lead each label with a showsp for all of your characters, again, just to be safe.

Join the Conversation

1 Comment

Leave a comment

Your email address will not be published. Required fields are marked *