Ren'Py - Time Advance Issue

Xavster

Well-Known Member
Game Developer
Mar 27, 2018
1,243
7,550
I have been hitting my head against a wall on a glitch I have with forwarding the game time within my VN. The following code does fine in terms of advancing the time, however when called from a different label, I am unable to get it to go back to the original label.
Code:
screen advance_time:
    zorder 200
    vbox xalign 0.9 yalign 0.05:
        imagebutton idle "advtime.png" action Call("advance_time")

label advance_time:
    if dtime == 4:
       $ dtime = 0
       $ day += 1
    else:
       $ dtime += 1
The top section is a screen overlay button to activate the advance_time label. I will also need to call the advance_time label within the coding itself to forward time after an event. What I am seeking the code to do, is to simply run the math and not change the position in the code.

Note: I tried several of the suggestions in https://f95zone.to/threads/renpy-day-time.18367/ but alas was not able to resolve.


Edit: I have done a little more testing and the advance_time label works fine when used as a call after an event. However during the game navigation screens, where I am using an imagemap, if I press the forward time button it goes to the next line within the active label. Thinking of games I have played, I'm not sure whether this is fixable. :confused:
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,110
14,782
Code:
screen advance_time:
    zorder 200
    vbox xalign 0.9 yalign 0.05:
        imagebutton idle "advtime.png" action Call("advance_time")

label advance_time:
    if dtime == 4:
       $ dtime = 0
       $ day += 1
    else:
       $ dtime += 1
Firstly :
There's no return at the end of "advance_time", have you forgot it in your example, or is it also missing in your game ?
When you call a label, you must also return from it, it's mandatory. Else Ren'py will naturally continue the flow of the code by processing what come next in the rpy file.

Secondly:
Like there's just math done here, you can do it directly from the screen. There's way more
 
  • Like
Reactions: Xavster

the66

beware, the germans are cumming
Modder
Respected User
Donor
Jan 27, 2017
7,593
23,528
another option, create your own screen action.

Python:
init python:
    class AdvanceTime(Action):
        def __call__(self):
            if renpy.store.dtime == 4:
                renpy.store.dtime = 0
                renpy.store.day += 1
            else:
                renpy.store.dtime += 1

            renpy.restart_interaction()

screen advance_time():
    zorder 200
    vbox xalign 0.9 yalign 0.05:
        imagebutton idle "advtime.png" action AdvanceTime()
 

Xavster

Well-Known Member
Game Developer
Mar 27, 2018
1,243
7,550
Firstly :
There's no return at the end of "advance_time", have you forgot it in your example, or is it also missing in your game ?
When you call a label, you must also return from it, it's mandatory. Else Ren'py will naturally continue the flow of the code by processing what come next in the rpy file.

Secondly:
Like there's just math done here, you can do it directly from the screen. There's way more
I tried with and without the return on the end of the label and from what I could see it didn't make any difference. With the functionality I require I will likely have to allow for a conditional jump, hence the set variable option may not be flexible enough. Thanks for the response though.

another option, create your own screen action.

Python:
init python:
    class AdvanceTime(Action):
        def __call__(self):
            if renpy.store.dtime == 4:
                renpy.store.dtime = 0
                renpy.store.day += 1
            else:
                renpy.store.dtime += 1

            renpy.restart_interaction()

screen advance_time():
    zorder 200
    vbox xalign 0.9 yalign 0.05:
        imagebutton idle "advtime.png" action AdvanceTime()
Tried the code and it worked immediately. As per my notes above, I also need to integrate an update of a number of other variables with each day advance (revised commodities prices), which may mean that I settle for the limitations of my current 'call' coding. What you have posted though gives me the framework for doing other actions within the game. (y)

PS: If you haven't already seen, I have posted the 0.1 of my VN, which is a very simple kinetic novel (see sig link). The step that I am currently undertaking is to convert it to a real game for the next batch of content.
 

the66

beware, the germans are cumming
Modder
Respected User
Donor
Jan 27, 2017
7,593
23,528
just read, you also want to call this from within the script.
you might use this code instead.
Python:
init python:
    class AdvanceTime(Action):
        def __call__(self):
            advanceTime()
            renpy.restart_interaction()

    def advanceTime():
        if renpy.store.dtime == 4:
            renpy.store.dtime = 0
            renpy.store.day += 1
        else:
            renpy.store.dtime += 1

screen advance_time():
    zorder 200
    vbox xalign 0.9 yalign 0.05:
        imagebutton idle "advtime.png" action AdvanceTime()
now you have the screen action and a function to call.
 

Xavster

Well-Known Member
Game Developer
Mar 27, 2018
1,243
7,550
just read, you also want to call this from within the script.
you might use this code instead.
Python:
init python:
    class AdvanceTime(Action):
        def __call__(self):
            advanceTime()
            renpy.restart_interaction()

    def advanceTime():
        if renpy.store.dtime == 4:
            renpy.store.dtime = 0
            renpy.store.day += 1
        else:
            renpy.store.dtime += 1

screen advance_time():
    zorder 200
    vbox xalign 0.9 yalign 0.05:
        imagebutton idle "advtime.png" action AdvanceTime()
now you have the screen action and a function to call.
Thanks, I'll do some experimenting. Been a long long time since I have done any real coding (hint - turbo C), however not bad at figuring things out. I may potentially take a simpler approach for the 0.2 edition, however if someone wants to assist in optimising the code, I'm all ears. I will however stay disciplined in the code layout (different files for different locations) and also enforce my current image coding system, which should make debugging easier.

You don't have permission to view the spoiler content. Log in or register now.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,110
14,782
I tried with and without the return on the end of the label and from what I could see it didn't make any difference.
Then there's an error elsewhere in your code. Even when the screen is shown, the Call screen action return to the right place :
Code:
screen myScreen():
    textbutton "click me":
        action Call( "whatever" )

label start:

    show screen myScreen

    "pass me please."
    "Click on the button please."
    "And you're back on the start label, in the right place."

    "END"
    return

label whatever:
    "You're in a called label."
    return
 

RVNSN

Drunken Pirate Skirtchaser
Game Developer
Jan 17, 2019
738
436
How did the experiment go? I'm trying to work out something that's probably fairly simple: presently using a time system with 4 times of day, an image for display for each one - on the image is written (from script) the day number, day of the week, and time of day (which corresponds to which image is presently being shown). I want to use this image to advance time (or part of it is even better, I put arrows on it to indicate forwarding time, and a hover version to light up the arrows with a mouseover - mouseover not in use yet).

Anyway, I am now at the point where I'm ready to include the option to skip the time of day forward, and I'm thinking I want to change the way time moves forward. So far, as everything has been following a story path without an open world exploration, I have been advancing manually by hiding the one image and showing the next (which I took from the code of another game). However, I'm thinking it would be much more useful to have time advance by adding numbers and having renpy automatically switch the time of day and image display to match.
 

Xavster

Well-Known Member
Game Developer
Mar 27, 2018
1,243
7,550
How did the experiment go? I'm trying to work out something that's probably fairly simple: presently using a time system with 4 times of day, an image for display for each one - on the image is written (from script) the day number, day of the week, and time of day (which corresponds to which image is presently being shown). I want to use this image to advance time (or part of it is even better, I put arrows on it to indicate forwarding time, and a hover version to light up the arrows with a mouseover - mouseover not in use yet).

Anyway, I am now at the point where I'm ready to include the option to skip the time of day forward, and I'm thinking I want to change the way time moves forward. So far, as everything has been following a story path without an open world exploration, I have been advancing manually by hiding the one image and showing the next (which I took from the code of another game). However, I'm thinking it would be much more useful to have time advance by adding numbers and having renpy automatically switch the time of day and image display to match.
I'm still no expert, but I'll try to provide some guidance.

To get the correct image and also activate the advance time function I use similar to the code below. This line of code provides an imagebutton that is adjusted according to the time of day and runs the advance_time label.
Python:
        imagebutton auto ("time_{}_%s.webp".format(dtime)) action Function(renpy.call, label="advance_time")
In the script above you would need to label your images similar to "time_1_hover.webp" where 1 corresponds to the time of day via the dtime variable.

I ended up doing the advance_time action within a label as it gives me opportunity to do other checks and adjustments. Below is a simplification of the label I actually use.
Python:
label advance_time:
    if dtime == 3:
        $ dtime = 0
        $ day += 1
        jump room_cap
    else:
        $ dtime += 1
    jump expression loc
    return()
The "jump expression loc" line in the code is important as it reloads the current location label (loc is the variable for the current location). From here dependent upon day / time I call different screens from within the location label. If you don't reload the current location screen your location will not update. If you take a game like Milfy City, they don't do this, which is why they only allow time advance from the Map screen (as it never changes).
 

the66

beware, the germans are cumming
Modder
Respected User
Donor
Jan 27, 2017
7,593
23,528
but keep in mind, when calling a label you have to return at some point or you fill nicely your return stack (you increase the nesting level with every new call w/o return).
the return in your example is never reached.
 
  • Like
Reactions: Xavster

Xavster

Well-Known Member
Game Developer
Mar 27, 2018
1,243
7,550
but keep in mind, when calling a label you have to return at some point or you fill nicely your return stack (you increase the nesting level with every new call w/o return).
the return in your example is never reached.
I can sort of see the problem that I am creating in my current code, however require some additional clarification. What I am doing is firstly running a label to determine which screens are going to be displayed.
2019-11-27_171327.jpg
In the case as seen above I am running a label kitchen, which in this case calls a screen as below:
Python:
            call screen kitchen("pckfjk1")
This kitchen screen code is as below.
Python:
screen kitchen(base):
    imagemap:
        ground ("{}_{}_{}".format(base,comm_view,sect))
        auto ("{}_{}_{}_%s.webp".format(base,comm_view,sect))

        if comm_view == "b":
            hotspot (0,0,195,1080) clicked Jump("common") tooltip "common"
            if base != "pck0":
                hotspot (220,280,1500,800) clicked Jump("{}".format(base))
        else:
            hotspot (1725,0,195,1080) clicked Jump("common") tooltip "common"
            if base != "pck0":
                hotspot (0,280,1700,800) clicked Jump("{}".format(base))

    use info_display
The info_display screen contains the nameplate at the top and also the advance_time button.

When the advance_time button is pressed, I need to run a label that increments the time, also does some checks / adjustments and then either reruns the current kitchen label or jumps to another label (location / event). I have adjusted the imagebutton to use action Jump("advance_time") instead. Is this a good idea or should I be doing something else?
 

recreation

pure evil!
Respected User
Game Developer
Jun 10, 2018
6,253
22,172
I can sort of see the problem that I am creating in my current code, however require some additional clarification. What I am doing is firstly running a label to determine which screens are going to be displayed.
View attachment 471554
In the case as seen above I am running a label kitchen, which in this case calls a screen as below:
Python:
            call screen kitchen("pckfjk1")
This kitchen screen code is as below.
Python:
screen kitchen(base):
    imagemap:
        ground ("{}_{}_{}".format(base,comm_view,sect))
        auto ("{}_{}_{}_%s.webp".format(base,comm_view,sect))

        if comm_view == "b":
            hotspot (0,0,195,1080) clicked Jump("common") tooltip "common"
            if base != "pck0":
                hotspot (220,280,1500,800) clicked Jump("{}".format(base))
        else:
            hotspot (1725,0,195,1080) clicked Jump("common") tooltip "common"
            if base != "pck0":
                hotspot (0,280,1700,800) clicked Jump("{}".format(base))

    use info_display
The info_display screen contains the nameplate at the top and also the advance_time button.

When the advance_time button is pressed, I need to run a label that increments the time, also does some checks / adjustments and then either reruns the current kitchen label or jumps to another label (location / event). I have adjusted the imagebutton to use action Jump("advance_time") instead. Is this a good idea or should I be doing something else?
The variables/functions inside the label don't care about how the label is ...erm, "called", so yeah, action Jump is fine.
 
  • Like
Reactions: Xavster

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,110
14,782
I can sort of see the problem that I am creating in my current code, however require some additional clarification.
Have I forgot to tell you about this in my PM ?
I clearly remember having the same thought that the66 when seeing the code. But like I had the full code, as far as I remember (I'm at works right now), in fact you never call the "advance_time" label, only jump to it. Therefore, it wasn't an effective issue, since in fact the return is totally useless here.
I saw it as a residue of the code you used as base for yours (one gave few times ago on the forum), and if I forgot to talk about this (sorry if it's the case), it's probably for this reason.


Is this a good idea or should I be doing something else?
What I can say is that :
  • It works ;
  • The code is correct ;
  • It never triggered an error during my tests ;
  • As far as I remember, the return stack stay constant (so the issue pointed by the66 never happen).

But, is it a good idea or not, only you can answer this question. There's no universal "good idea", just ideas that works for one kind of code and that is correctly understood by the coder.
 
  • Like
Reactions: Xavster

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,557
2,170
To reinforce what has been said before... but if you use call, there must be a corresponding return

jump is "Go THERE".
call is "Go THERE and then come back here".

... without the return the code has no clue about the "then come back here" part... which is the whole point of using call.

But to address your "advance time" code... I tend to focus on linear style games. So your open world approach (which I'm sure is fine) is a little alien to my way of thinking.

However, I wrote up this test script. The code works and I've tested it.
I don't know if it exactly fits what you're trying to do... but I've tried to do the whole generic "morning -> afternoon -> evening -> night" thing in a closed loop.

Maybe there's something here that can help you solve your own problem...

You don't have permission to view the spoiler content. Log in or register now.

The image I used is also attached... since it is the only thing stopping you cut and pasting this code into a temporary RenPy project on your own computer.

Edit: fixed the advance time button not being reshown when skipping forward to the middle of next day. It actually worked originally, but then I changed something else that broke it.
 
Last edited:

the66

beware, the germans are cumming
Modder
Respected User
Donor
Jan 27, 2017
7,593
23,528
ofc is the code working.
but action Function(renpy.call, label="advance_time") is effectively calling the label and so creating everytime a new entry in the return stack.
one of my saves from creating the android port has 17 entries and another one already 39.
just do a simple action Jump("advance_time") and the problem is solved.
 
  • Like
Reactions: Xavster

Xavster

Well-Known Member
Game Developer
Mar 27, 2018
1,243
7,550
Thanks everyone. Still 'new' to coding and trying to figure out what exactly what is happening in Ren'Py / python. I say 'new' to coding, as last time I did it seriously it was in Pascal and Turbo C. :p

PS: AON - thanks for all your assistance, I'll get to your beta comments next week. (y)

PPS: As a little query, when you do a return, I assume it goes back to the next line of code in the label from which you made the call?
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,557
2,170
PPS: As a little query, when you do a return, I assume it goes back to the next line of code in the label from which you made the call?
Yes.
At least within RenPy's usual flow as controlled by the structure of indented code.

Which is to say, it works how you'd expect it to - but that doesn't always mean it's the very next line of code below the call. I'm thinking of stuff like if {condition} == True: or menu: blocks.
 

the66

beware, the germans are cumming
Modder
Respected User
Donor
Jan 27, 2017
7,593
23,528
PPS: As a little query, when you do a return, I assume it goes back to the next line of code in the label from which you made the call?
a return from the renpy call statement? yes, always.
a return from the renpy.call() function? yes, unless you've used from_current=True as kwarg. then you would return to the call itself. :eek:
 
  • Like
Reactions: 79flavors

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,557
2,170
a return from the renpy.call() function? yes, unless you've used from_current=True as kwarg. then you would return to the call itself. :eek:
Okay... I'm officially terrified.
No... No... I'm not going to think about it. Down that road lies madness.
 

the66

beware, the germans are cumming
Modder
Respected User
Donor
Jan 27, 2017
7,593
23,528
a funny way to create a for loop
Python:
label start:

    $ i = 0
    $ renpy.call("call_test", from_current=(True if i < 5 else False))
    
    return
    
label call_test():
    
    "[i]"
    $ i += 1
    
    return
 
  • Like
Reactions: recreation