Interaction Afterlife (restart interaction after it ended)

A place for Ren'Py tutorials and reusable Ren'Py code.
Forum rules
Do not post questions here!

This forum is for example code you want to show other people. Ren'Py questions should be asked in the Ren'Py Questions and Announcements forum.
Post Reply
Message
Author
jeffster
Veteran
Posts: 250
Joined: Wed Feb 03, 2021 9:55 pm
Contact:

Interaction Afterlife (restart interaction after it ended)

#1 Post by jeffster »

Let's suppose we want to open an additional "screen" to do some extra functionality, and then return to our dialog or menu screens.

We can do that by show/hide screen. But if we need there some complex algorithm, or for example drag-dropping, then it's hard to avoid things like "jump", "call" or "return" (e.g. return not None when dropping). And those things finalize the current interaction, so our dialog or menu progresses to the next statement.

How to come back to the same line of dialog or the same screen "choice" (that we started our additional actions from)?

There is a solution like renpy.call_in_new_context(), but it loses the current context. It hides the dialog screen and the like. What if we want to have both dialog or menu AND additional elements with complex logic or interactions like drag-and-drop?

After many hours of research I haven't found a good documented way, so here's how I did it using undocumented Ren'Py innards.

In this example, a button shows the additional screen. That screen polls undocumented renpy.game.context().current to get the address of the current statement (like "say" or "choice"). We repeatedly store that current address to a variable, and at the same time we can click and progress with dialog or menu, as much as we want.

Then if some actions are necessary that would perform additional tasks (and eventually finalize the current interaction), we stop polling the current address. Later, after we have done what we needed, we jump back to our saved address. This way we can see again the previous dialog line or choice menu.

The only drawback is that there will be a double record in History, but that can be mended (or ignored). Here's a complete test code with some additional bells and whistles. Just replace "some_picture" with some picture, or remove that scene statement. It's there just to show that things like changed background might need to be addressed.

Code: Select all

default currAddr = None
default currAddrLast = None
default inCall = None
default inCallLast = None

screen additional():
    if not inCall:
        $ currAddr = renpy.game.context().current
        $ currAddrLast = currAddr[-1]
        button:
            text "Leave statement [currAddrLast!q]"
            pos (0, 0)
            action [
                SetVariable("inCall", currAddr),
                SetVariable("inCallLast", currAddrLast),
                Jump("called")
                ]
    else:
        button:
            text "Return to statement [inCallLast!q]"
            pos (0, 100)
            action [
                Hide("additional"),
                Jump(inCall)
                ]

screen myButt():
    button:
        text "Open Additional"
        align (1.0, 0.0)
        action [
            SetVariable("inCall", None),
            Show("additional")
            ]

label start:
    show screen myButt
    scene some_picture

    "Starting"
    menu:
        "Menu"
        "1":
            "1"
        "2":
            "2"
label ending:
    "Ending"
    jump start

label called:
    scene black
    """1. You don't ask questions.

    2. You don't ask questions.

    3. No excuses.

    4. No lies.

    5. You have to trust Dyler Turden.
    """
    jump called

Now I don't know if that's the best way to do it, but it works.

User avatar
Alex
Lemma-Class Veteran
Posts: 3089
Joined: Fri Dec 11, 2009 5:25 pm
Contact:

Re: Interaction Afterlife (restart interaction after it ended)

#2 Post by Alex »

jeffster wrote: Thu Jun 22, 2023 9:22 pm ...
Try to use Call action with 'from_current' property - https://www.renpy.org/doc/html/statemen ... renpy.call

Code: Select all

screen test_scr():
    vbox:
        align(0.05, 0.05)
        text "Title"
        textbutton "Some call..." action Call("called_lbl", from_current=True)

label start:
    "..."
    show screen test_scr

    "Starting"
    menu:
        "Menu"
        "1":
            "1"
        "2":
            "2"
label ending:
    "Ending"
    jump start

label called_lbl:
    scene black
    """1. You don't ask questions.

    2. You don't ask questions.

    3. No excuses.

    4. No lies.

    5. You have to trust Dyler Turden.
    """
    return

jeffster
Veteran
Posts: 250
Joined: Wed Feb 03, 2021 9:55 pm
Contact:

Re: Interaction Afterlife (restart interaction after it ended)

#3 Post by jeffster »

Alex wrote: Fri Jun 23, 2023 1:02 pm Try to use Call action with 'from_current' property - https://www.renpy.org/doc/html/statemen ... renpy.call
I recall trying to use from_current=True, and there was a number of problems.

In my example above, you can both click through the original dialog lines or do some other actions, that would eventually lead to finalizing an interaction. And after those actions you would be back on the last dialog line achieved by clicking the lines.

How would you do that with from_current=True? If you store the return address by first calling some other place, then you either only do those actions but can not progress through the original dialog, because you are not in the place of the original dialog... Or you need to update the return address on each dialog line, which is what I am doing there with that undocumented variable. AFAICR trying to do that with from_current=True-calls was more complex and also problematic. Something didn't work with getting the call stack or returning into the original function or to the original address.

I may be wrong, so if you could solve the task with another method, it might be interesting.

PS. Let's assume we have screen "say" or "choice" on display. And there's some other GUI that leads to ending the current interaction. How can we instead of finalizing the interaction restart it?

User avatar
Alex
Lemma-Class Veteran
Posts: 3089
Joined: Fri Dec 11, 2009 5:25 pm
Contact:

Re: Interaction Afterlife (restart interaction after it ended)

#4 Post by Alex »

jeffster wrote: Fri Jun 23, 2023 3:46 pm ...
Hm, in your sample player can click "Open Additional" while in 'called' label and click "Leave statement..." to get 'called' label once again, but return will work only once...

I've changed my sample a bit - check if it suits for your needs (and works right with save/load/rollback).

Code: Select all

screen test_scr():
    default in_called_lbl = 0

    vbox:
        align(0.05, 0.05)
        text "Title (call depth = [in_called_lbl])"
        textbutton "Some call..." action [SetScreenVariable("in_called_lbl", in_called_lbl + 1), Call("called_lbl", from_current=True)]
        if in_called_lbl > 0:
            textbutton "Return..." action [SetScreenVariable("in_called_lbl", max(0, in_called_lbl - 1)), Jump("return_from_any_lbl")]

label start:

    scene some_picture

    show screen test_scr

    "Starting"
    menu:
        "Menu"
        "1":
            "1"
        "2":
            "2"
label ending:
    "Ending"
    jump start

label called_lbl:
    scene black
    """1. You don't ask questions.

    2. You don't ask questions.

    3. No excuses.

    4. No lies.

    5. You have to trust Dyler Turden.
    """
    jump called_lbl

label return_from_any_lbl:
    return

jeffster
Veteran
Posts: 250
Joined: Wed Feb 03, 2021 9:55 pm
Contact:

Re: Interaction Afterlife (restart interaction after it ended)

#5 Post by jeffster »

Alex wrote: Fri Jun 23, 2023 7:04 pm Hm, in your sample player can click "Open Additional" while in 'called' label and click "Leave statement..." to get 'called' label once again, but return will work only once...
The purpose of the trick was to return to the original interaction, instead of losing it by standard Ren'Py ways.

It's not about having different threads of dialogue and jumping here and there. (Which is a different idea, though interesting too, and I can imagine games that could use it... Affecting the present with time travel to the past?)...

That's not the problem I was talking about though. The second set of dialog was there just as easy means to demonstrate leaving the previous interaction. (I thought if I used drag-dropping or some other GUI action finalizing the interaction, it wouldn't show such an apparent effect in the demo).

User avatar
Alex
Lemma-Class Veteran
Posts: 3089
Joined: Fri Dec 11, 2009 5:25 pm
Contact:

Re: Interaction Afterlife (restart interaction after it ended)

#6 Post by Alex »

jeffster wrote: Fri Jun 23, 2023 8:16 pm The purpose of the trick was to return to the original interaction, instead of losing it by standard Ren'Py ways.

It's not about having different threads of dialogue and jumping here and there. (Which is a different idea, though interesting too, and I can imagine games that could use it... Affecting the present with time travel to the past?)...

That's not the problem I was talking about though. The second set of dialog was there just as easy means to demonstrate leaving the previous interaction. (I thought if I used drag-dropping or some other GUI action finalizing the interaction, it wouldn't show such an apparent effect in the demo).
Mmm, if you need to read several dialogs switching between them, then your approach might work, but you'll need to store 'currAddr' for each dialog. As for now, in your sample player will see 'called' label from the very beginning everytime jumping to it.

As for drag'n'drop - try to redesign it to not end an outer interaction (like, just a though, call a screen with d'n'd, so it can return to main game routing).

jeffster
Veteran
Posts: 250
Joined: Wed Feb 03, 2021 9:55 pm
Contact:

Re: Interaction Afterlife (restart interaction after it ended)

#7 Post by jeffster »

Alex wrote: Sat Jun 24, 2023 5:40 am As for drag'n'drop - try to redesign it to not end an outer interaction (like, just a though, call a screen with d'n'd, so it can return to main game routing).
My motivation for this work was the idea to have both dialog (e.g., say and choice screens) and other UI on display, so that players could control both aspects at any time.

Imagine that you can click the dialog area and progress to the next dialog line; or you can drag an ingredient to a sandwich and progress in "The Deli" minigame.

It might be hard to make that additional interface without jumps, calls to outer code and "return not-none"s. That's one of the reasons for the idea to return to "unwillingly finished" interaction.

Another idea is to have something like free-roam controls and at the same time continue the dialog. So you could unlink dialog from visual scenes.

Perhaps we could do it by taking dialog lines into some function and processing them as part of a custom GUI system, but it seems easier to just have the regular "say" plus that little trick of returning to the last finished interaction.

AnthonyOlson
Newbie
Posts: 2
Joined: Mon Jul 03, 2023 6:28 am
Contact:

Re: Interaction Afterlife (restart interaction after it ended)

#8 Post by AnthonyOlson »

Thanks for the advice, I will keep it in my mind.

Post Reply

Who is online

Users browsing this forum: No registered users