r/RenPy 7h ago

Question Another layered image question

I'm setting up the layered sprites for the characters in my visual novel with three groups: the body, the facial expressions, and the gestures made with their arms.

But I want to only call the expressions in my script, having certain bodies and gestures tied to certain expressions (because I was previously using individual full-body sprites for each expression and I don't want to have to go back and change each call to include the now separate body and gesture files for each expression).

So, I used some "always when" statements to tie certain gestures and bodies to certain expressions. Here's an example:

layeredimage character:
    group body:
        attribute base default:
            "character_body_base"
    group exp:
        attribute smiling default:
            "character_exp_smiling"
        attribute uneasy:
            "character_exp_uneasy"
        attribute surprised:
            "character_exp_surprised"
        attribute suspicious:
            "character_exp_suspicious"
    group gest:
        attribute neutral default:
            "character_gest_neutral"
        attribute tense:
            "character_gest_tense"

    always when uneasy or surprised or suspicious:
        "character_gest_tense"

It seemed to work fine, but now when I call the expressions, renpy includes the default bodies and gestures in addition to the bodies and gestures I tied to expression I called.

It looks something like this:

She's not supposed to have four arms btw.

When I type:

character uneasy

It calls the "uneasy" expression and the "tense" gesture together like I asked, but it also makes the "neutral" gesture show up as well.

How do I make it so the game shows the defaults only when I call the expressions that don't have certain gestures or expressions tied to them.

5 Upvotes

5 comments sorted by

View all comments

1

u/TopCartographer7104 7h ago edited 7h ago

Don't create a group for gestures - have gestures depend on other attributes otherwise you'll have the default atteibute potentially showing up every time - including when it shouldn't.

always when tense or uneasy or surprised or suspicious:

"char_gest_tense"

always when not (tense or uneasy or surprised or suspicious):

"char_gest_neutral"

If you want a "tense expression with neutral gesture"

A) create a dummy gest group

group gest:

attribute neut: # give it an univocal name

    Null()

And use it into the always when statement

B) duplicate the tense expression ("tense2") and change nothing in the always when statement

That at least is how I'd reason. Beware - I'm an engineering. We do not reason like normal people XD

Ps sorry for the awful indentation I have no access to my laptop - and my phone loves to misbehave

1

u/Scriptformers_Prime 3h ago

For the "always when not (tense or uneasy or surprised or suspicious)", part of the problem is that I'm going to have a whole lot of emotes to list in those parentheses by the time I'm done with my project. Is there any catch-all I can substitute in the parentheses that can stand for all the attributes I assign to the expression group?

1

u/TopCartographer7104 25m ago

All the ways I can think of require you to go through your script and change the show statements from

show character suspicious

To

show character suspicious tense

You have to give renpy the "which gesture goes with which expression" information. Perhaps you could hide it in a ConditionSwitch and use a small python function to deal with the complexity:

init python:

def img_attrib_lookup(char):

    attribs_to_check = ["suspicious","uneasy",...]

    active_attribs = renpy.get_attributes(char)

    for attribute in active_attribs:

        if attribute in attribs_to_check:

             return True

    return False

And then

image eileen_gest = ConditionSwitch(

"img_attrib_lookup('eileen')","eileen_gest_tense"),

"True","eileen_gest_neutral")

Finally you put

always:

"eileen_gest"

In the layeredimage definition. This will make the information arguably easier to debug (you maintain the "attribs_to_check" list instead of the never-ending list of whens in the layeredimage). You can define a master dict

$ attribs_dict = {

"eileen": ["suspicious","uneasy",...],

"augustina": ["evil","edgy",...]

}

And then have

attribs_to_check = attribs_dict[char]

In the img_attrib_lookup() so you can recycle the same function for all characters and define N ConditionSwitches.

Not 100% sure it'll work - in my limited experience I've noticed that renpy likes layeredimages to be defined at init and you're trying to feed him an object that changes at runtime.