[SOLVED] time announcement calendar. working with tuples?

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
User avatar
chapscher
Newbie
Posts: 11
Joined: Sun May 07, 2017 12:05 am
Tumblr: chapscher
Contact:

[SOLVED] time announcement calendar. working with tuples?

#1 Post by chapscher »

I'm new to programming and am having a hard time figuring out how tuples work.

I have my game arranged into a bunch of "time slots" that I'm treating like small chapters. At the end of each small chapter the player gets to make a phone call or work on a skill. But once they finish with whatever they're doing they will return to the time slot label ("s_loc" I call it) and the next time/location is announced by a character who's playing the role of the chyron.

so my game basically is structured like this:

Code: Select all

define loc = Character(what_font="cour.ttf")

label start:
  $ slot = 1
  jump s_loc

label s_loc:
  if slot == 1:
    scene bg lecturehall
    loc "Noon. Monday, November 4.{p}LECTURE HALL"
    "This is where the first scene goes"
    jump phone_m
  if slot == 2:
    scene bg office
    loc "Early Afternoon. Monday, November 4.{p}OFFICE"
    "This is where the second scene goes"
    jump phone_m
  #and so on.

  label phone_m:
    menu:
      "Whom shall I call?"
      "Call Adam":
        "This is where a long conversation with Adam goes."
        $ slot += 1
        jump s_loc
      "Call Beth": #and so on. 
Each $ slot += 1 moves the "hour" section one forward in the following progression:

["Early Morning", "Morning", "Late Morning", "Noon", "Early Afternoon", "Mid-Afternoon", "Late Afternoon", "Early Evening", "Evening", "Night", "Late Night"]

and once it reaches the end of that it starts over but now it's the next day, so the day of the week/month updates. (Well... "updates". Right now I write it all out).

As you can probably guess, writing out loc's thing can get pretty tedious and at times problematic. Especially when there are events in a separate label that could happen during several different master time slots. Then it makes things look like this:

Code: Select all

"I leave the construction site and return to my car, leaving nothing more than faint imprints on gravel as I drive onto the expressway."
$ slot += 1
if slot == 62:
    loc "Late Night. Saturday, November 9.{p}LIVING ROOM"
if slot == 117:
    loc "Late Night. Thursday, November 14.{p}LIVING ROOM"
if slot == 139:
    loc "Late Night. Saturday, November 16.{p}LIVING ROOM"
if slot == 194:
    loc "Late Night. Thursday, November 21.{p}LIVING ROOM"
if slot == 216:
    loc "Late Night. Saturday, November 23.{p}LIVING ROOM"
"I arrive home and brush the dust from the construction site from my hair as I walk around the house to the backyard."
There's just too much room for error. I'm not entirely sure how to have loc simply state the time assigned to a specific slot. Not to mention how/if I can still include the location. I've seen a few cookbooks for clocks and calendar screens, but they don't seem to have what I'm looking for. Could anyone point me in the right direction?
Last edited by chapscher on Tue Jul 18, 2017 12:36 am, edited 1 time in total.

User avatar
trooper6
Lemma-Class Veteran
Posts: 3712
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: time announcement calendar. working with tuples?

#2 Post by trooper6 »

When does the game start and how many months/years will this game last?
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

User avatar
chapscher
Newbie
Posts: 11
Joined: Sun May 07, 2017 12:05 am
Tumblr: chapscher
Contact:

Re: time announcement calendar. working with tuples?

#3 Post by chapscher »

(hi, trooper6!)

Just November and December.

User avatar
Milkymalk
Miko-Class Veteran
Posts: 753
Joined: Wed Nov 23, 2011 5:30 pm
Completed: Don't Look (AGS game)
Projects: KANPEKI! ★Perfect Play★
Organization: Crappy White Wings
Location: Germany
Contact:

Re: time announcement calendar. working with tuples?

#4 Post by Milkymalk »

You already made a list of your "times". As this list never changes, you can make it a tuple by replacing the [ ] with ( ).

Code: Select all

python:
    times = ('early morning", "morning" ...etc. )

label example:
    $ now = 0      # the first element is 0, not 1
    "It is [times[now]]."
I'm not sure if this works. The "say" screen is known to have issues with function calls for variables, maybe it doesn't like fields either. In that case:

Code: Select all

label example:
    $ now = 0      # the first element is 0, not 1
    $ nowname = times[now]
    "It is [nowname]."
To have time advance, a function would be best:

Code: Select all

def pass_time():
    now += 1
    if now == len(times):
        now = 0
        # add more rollover checks here
You call that with:

Code: Select all

$ pass_time()
If you don't understand something, just ask.
Crappy White Wings (currently quite inactive)
Working on: KANPEKI!
(On Hold: New Eden, Imperial Sea, Pure Light)

User avatar
chapscher
Newbie
Posts: 11
Joined: Sun May 07, 2017 12:05 am
Tumblr: chapscher
Contact:

Re: time announcement calendar. working with tuples?

#5 Post by chapscher »

Thanks for your answers. (I knew that starting at 1 instead of 0 was bound to bite me in the ass somewhere along the line. Can't fight it forever, I suppose. lol)

Unfortunately, I'm encountering a bit of a problem

Here's what I have written:

Code: Select all

init python:
    times = ("Early Morning", "Morning", "Late Morning", "Noon", "Early Afternoon", "Mid-Afternoon", "Late Afternoon", "Early Evening", "Evening", "Night", "Late Night")
    def pass_time():
        global now
        now += 1
        if now == len(times):
            now = 0
label start:
    $ now = 0
    $ nowname = times[now]
    "It is [nowname]"
    "Click to progress."
    $ pass_time()
    "It is [nowname]"
(I added the "global now" because if it's not there then I get the "local variable 'now' referenced before assignment" error. I'm not sure if that's the proper way to correct that error but...)
It "works" but the time does not progress. It is perpetually "Early morning". Or "noon" or whatever I set $ now as

Quite probably very related: what are rollover checks and how do they work? I've been digging around on here but I haven't found any direct answer.

User avatar
Milkymalk
Miko-Class Veteran
Posts: 753
Joined: Wed Nov 23, 2011 5:30 pm
Completed: Don't Look (AGS game)
Projects: KANPEKI! ★Perfect Play★
Organization: Crappy White Wings
Location: Germany
Contact:

Re: time announcement calendar. working with tuples?

#6 Post by Milkymalk »

Yes, "global" is what I forgot because I rarely use global variables in functions :) Good job.

You have to reassign nowname after time passes so the displayed string actually changes; it's not a dynamic assignment. I suggest you add it to pass_time().

There are more elegant methods to do this, but for what you want to accomplish, this suffices.

When I said "rollover checks" I meant: Advancing the date and day of the week if the daytime rolls over to 0, which includes checking for the date rolling over from 30 to 1 (end of November) and changing the month when that happens.
Crappy White Wings (currently quite inactive)
Working on: KANPEKI!
(On Hold: New Eden, Imperial Sea, Pure Light)

User avatar
Moonpearl
Newbie
Posts: 15
Joined: Sun Jul 09, 2017 4:32 pm
Skype: moonpearl121
Contact:

Re: time announcement calendar. working with tuples?

#7 Post by Moonpearl »

Personnally, I would go for a class. It's not necessarily relevant if it's just for your periods problem, but it might save you some trouble when you expand it to manage more, like dates and stuff.

Code: Select all

init python:
    class Game_Time:
        PERIODS = ("Early Morning", "Morning", "Late Morning", "Noon", "Early Afternoon", "Mid-Afternoon", "Late Afternoon", "Early Evening", "Evening", "Night", "Late Night")

        def __init__(self):
            self.now = 0

        def advance(self, n = 1):
            self.now += n

        def period(self):
            return Game_Time.PERIODS[self.now % len(Game_Time.PERIODS)]

label start:
    $ time = Game_Time()
    
label loop:    
    $ period = time.period()
    "It is [period]."
    "Click to progress."
    $ time.advance()
    jump loop

User avatar
Milkymalk
Miko-Class Veteran
Posts: 753
Joined: Wed Nov 23, 2011 5:30 pm
Completed: Don't Look (AGS game)
Projects: KANPEKI! ★Perfect Play★
Organization: Crappy White Wings
Location: Germany
Contact:

Re: time announcement calendar. working with tuples?

#8 Post by Milkymalk »

That's what I meant with "more elegant methods" ;)
Crappy White Wings (currently quite inactive)
Working on: KANPEKI!
(On Hold: New Eden, Imperial Sea, Pure Light)

User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: time announcement calendar. working with tuples?

#9 Post by Remix »

If you are not afraid of a bit of code logic I would personally go with a class that handles both the progression of time and time based events.
Basically (in semi English):

Event Class:
Keeps track of lowest time unit (probably hour)
Methods:
Output a string saying the current time and date
Register an Event - including available times
Test an Event - is it accessible at the current hour

With that running in the background, you would then just write each label and have them register themselves to the class.
The class would then know exactly when the label could/should be shown.

... depending on work, I should be able to run up a test script using that concept sometime soon...
Frameworks & Scriptlets:

User avatar
Moonpearl
Newbie
Posts: 15
Joined: Sun Jul 09, 2017 4:32 pm
Skype: moonpearl121
Contact:

Re: time announcement calendar. working with tuples?

#10 Post by Moonpearl »

I've expanded my class a bit. Feel free to use.

Code: Select all

init python:
    class Game_Time:
        PERIODS = ("Early Morning", "Morning", "Late Morning", "Noon", "Early Afternoon", "Mid-Afternoon", "Late Afternoon", "Early Evening", "Evening", "Night", "Late Night")
        MONTHS = ("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December")
        WEEK_DAYS = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday")
        MONTHS_DAYS = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
        
        def __init__(self, now = 0):
            self.period = 0
            self.day = 0
            self.week = 0
            self.week_day = 0
            self.month = 0
            self.month_day = 0
            self.now = now
            self.update()

        def advance(self, n = 1):
            self.now += n
            self.update()
            
        def update(self):
            self.period = self.now % len(Game_Time.PERIODS)
            self.day = self.now / len(Game_Time.PERIODS)
            self.week_day = self.day % 7
            self.week = self.day / 7
            day = self.day
            self.month = 0
            while day >= Game_Time.MONTHS_DAYS[self.month]:
                day -= Game_Time.MONTHS_DAYS[self.month]
                self.month += 1
            self.month_day = day + 1

        def period_name(self):
            return Game_Time.PERIODS[self.period]
            
        def week_day_name(self):
            return Game_Time.WEEK_DAYS[self.week_day]
            
        def month_name(self):
            return Game_Time. MONTHS[self.month]
            
        def date_name(self):
            return self.week_day_name() + ", " + self.month_name() + " " + str(self.month_day)

label time_start:
    $ time = Game_Time()
    
label time_loop:
    $ date = time.date_name()
    $ period = time.period_name()
    "Today is [date]. It is [period]."
    menu:
        "Next period":
            $ time.advance()
        "Next day":
            $ time.advance(len(Game_Time.PERIODS))
        "Next week":
            $ time.advance(len(Game_Time.PERIODS) * 7)
    jump time_loop

User avatar
chapscher
Newbie
Posts: 11
Joined: Sun May 07, 2017 12:05 am
Tumblr: chapscher
Contact:

Re: time announcement calendar. working with tuples?

#11 Post by chapscher »

Oh my god thank you so much! I'm sorry I didn't respond sooner.

Computer Friend and I have been playing around with this for the past few days and we came up with something similar (although yours looks far more elegant).

Code: Select all

init python:
    class Game_Time:
        PERIODS = ("Early Morning", "Morning", "Late Morning", "Noon", "Early Afternoon", "Mid-Afternoon", "Late Afternoon", "Early Evening", "Evening", "Night", "Late Night")
        DAYS = ("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
        NMONTHS = (0, 31, 59, 90, 120, 151, 181, 212, 243, 274, 304, 335, 365)
        SMONTHS = ("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December")
        def __init__(self):
            self.now = 10
            self.day = 0
            self.DOY = 0
            self.hwdm = "Early Morning. Monday, January 1."
        def get_dtp(self):
            self.hwdm = self.period() + ". "
            self.hwdm = self.hwdm + self.dow() + ", "
            self.hwdm = self.hwdm + self.mog + " "
            self.hwdm = self.hwdm +  self.dom + "."
            return self.hwdm
        def advance(self, s = 0, n = 1):
            self.now += n
            if self.now%11 == 0:
                self.DOY += n
            s = n - 1
            while(self.DOY%365 > Game_Time.NMONTHS[s]):
                s = s + n
            if self.DOY < 31:
                self.ndom = self.DOY
                self.mog = Game_Time.SMONTHS[0]
            else:
                self.ndom = self.DOY - Game_Time.NMONTHS[s-1]
                self.mog = Game_Time.SMONTHS[s]
            self.dom = str(self.ndom)
        def sleeps(self, n = 3, i = 0): #sleeping. advancing 3 periods
            while i < n:
                i = i + 1
                self.advance()
        def dow(self): #Day of Week
            return Game_Time.DAYS[self.DOY%7]
        def period(self):
            return Game_Time.PERIODS[self.now % len(Game_Time.PERIODS)]
        def greet(self): #When it is "Late Night"
            if self.now % 11 == 10:
                return True
            else:
                return False

label start:
    $ time = Game_Time()
    $ time.advance()
    jump loop

label loop:
    $ period = time.get_dtp()
    if time.greet():
        "Go to sleep"
    "It is [period]"
    menu:
        "Would you like to go to sleep?"
        "Yes":
            $ time.sleeps()
            "You go to sleep"
            "You will awaken in three time periods."
        "No":
            "You do not sleep"
            "Click to progress."
            $ time.advance()
    jump loop

User avatar
Moonpearl
Newbie
Posts: 15
Joined: Sun Jul 09, 2017 4:32 pm
Skype: moonpearl121
Contact:

Re: time announcement calendar. working with tuples?

#12 Post by Moonpearl »

You're welcome. ;) I come from Ruby, I still need to hone my Python skills, even though the two languages are very similar. So it was a nice exercise for me. :)

User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: time announcement calendar. working with tuples?

#13 Post by Remix »

... maybe a bit late, the following code allows you to write a label and register it to a handler.

The handler tracks time (using the store to allow save, rollback, roll forward and load to work properly)
It holds the events, which can be registered anywhere in the script (so, next to each label makes sense)
It tests events against time
It outputs all events for any hour
It calculates how long the wait is until the next available event
It has utility functions to output text data for time or event

The menu screen integrates with the handler and automatically creates buttons for available events.
Just "show screen event_choice" is all that is needed

The script is all in one file (you can move parts to other files like screens.rpy if it suits your needs)
It has a few label events to run a game about a thirsty person so you can test (maybe create new project and just copy it into script.rpy)
Inline comments and code layout *should* make most of it self-explanatory

Anyway...

Note: has a reference to Champagne, so might not be pegi-{low number}

Code: Select all

          ######################################
          #    The Python Class & variables    #
          ######################################
#
# This python stuff could go in a seperate .rpy if you want
#

#
# Initialize this python block in a -1 offset so the 
# event_handler object reference is available to inline 
# 0 offset python blocks that register labels as events
#
init -1 python:
    #
    # Import the store to hold the hour variable, using namespace 
    # to avoid error during instantiation within this -1 block
    import renpy.store as ren_store

    # default duration for events that do not specify their own
    default_event_duration = 1

    # the hour the game starts at... 
    default_start_hour = 0

    # The script will actually output the name relevant to
    # the number equal or nearest and lower to hour,
    # You could name all 24 hours if wanted
    # Range would be 0 to 23 (not 1 to 24)
    hour_names = ( (0, _("Night Time")),
                   (8, _("Early Morning")),
                   (12, _("Noon")),
                   (18, _("Late Afternoon")),
                   (22, _("Late Evening"))
                 )
    # Note: Amend the EventHandler.get_hour_of_day() output to alter 
    # the display of time/date info within the choice menu

    # Re-order if you want to start on a different day
    weekday_names = ( _("Monday"),
                      _("Tuesday"),
                      _("Wednesday"),
                      _("Thursday"),
                      _("Friday"),
                      _("Saturday"),
                      _("Sunday")
                    )

    # Pretty basic and self explanatory
    month_names = ( ( _("November"), range(1,31)), # start day, month days+1
                    ( _("December"), range(1,32))
                  )


    class EventHandler(object):
        """ Handle keeping track of time and scheduled events """

        def __init__(self):
            #
            # hour is handled by renpy.store
            ren_store.event_handler_hour = default_start_hour
            #
            # Empty events list to start
            self.events = []

        def get_str_for_hour(self, hour=None):
            """ Ouput a string to represent the hour """
            hour = self.get_hour(hour) 
            ret = "{0} on {1} {2} {3}".format(self.get_hour_name(hour), 
                                              self.get_weekday_name(hour), 
                                              self.get_month_name(hour),
                                              self.get_day_of_month(hour))

            # Comment out this next line to drop showing the hour x:00 part
            ret = "{0}:00 - {1}".format(self.get_hour_of_day(), ret)
            
            # Comment out this next line to drop showing the stored hour part
            # Only really useful for debugging rollback etc
            #
            # un-comment it to view total hour count in menu screen
            # ret = "({0}) {1}".format(self.get_hour(), ret)

            return ret

        #
        # Setters and Getters to play nicer with rollback
        #
        def __getattr__(self, name):
            if name == 'hour':
                return ren_store.event_handler_hour or 0
            try:
                return self.__dict__[name]
            except KeyError:
                return type(self).__getattr__(self, name)

        def __setattr__(self, name, value):
            if name == 'hour':
                ren_store.event_handler_hour = value
            else:
                # We only use this to create the empty events list
                self.__dict__[name] = value

        def get_hour(self, hour=None):
            return hour if hour is not None else ren_store.event_handler_hour

        #
        # You could theoretically pass a negative to travel back in time ;)
        def advance_time(self, hours=1):
            # Advance the time by x hours
            ren_store.event_handler_hour += hours

        #
        # Utility functions for working with days, weekdays, day of month
        # and months when represented by just an hour value
        #

        def get_hour_of_day(self, hour=None):
            hour = self.get_hour(hour) 
            return hour % 24

        def get_hour_name(self, hour=None):
            hour = self.get_hour_of_day(hour)
            ret = hour_names[0][1]
            for hour_name in hour_names:
                if hour < hour_name[0]:
                    break
                ret = hour_name[1]
            return ret

        def get_day_number(self, hour=None):
            hour = self.get_hour(hour) 
            # day number starting with zero as first day
            return divmod(hour, 24)[0]

        def get_weekday_name(self, hour=None):
            hour = self.get_hour(hour) 
            return weekday_names[ self.get_weekday_number(hour) ]

        def get_weekday_number(self, hour=None):
            hour = self.get_hour(hour) 
            return self.get_day_number(hour) % 7

        def get_day_of_month(self, hour=None):
            hour = self.get_hour(hour) 
            day = self.get_day_number(hour) + 1
            for month in month_names:
                if day <= len(month[1]):
                    break
                day -= len(month[1])
            return day

        def get_month_name(self, hour=None):
            hour = self.get_hour(hour) 
            return month_names[ self.get_month_number(hour) ][0]

        def get_month_number(self, hour=None):
            hour = self.get_hour(hour) 
            day = self.get_day_number(hour)
            # remember days start 
            month_number = 0
            for month in month_names:
                if day < len(month[1]):
                    break
                month_number += 1
                day -= len(month[1])
            return month_number

        def __str__(self):
            return self.get_str_for_hour(self.get_hour())

        def add_event(self, label_name=None, **kwargs):
            if not isinstance(label_name, basestring) or len(label_name) < 1:
                raise KeyError # Must have label name
            event_data = {'name' : label_name,
                          'hour' : range(0, 24), # 0 to 23
                          'day' : range(1, 32), # 1 to 31
                          'weekday' : range(0, 7),
                          'month' : range(0, len(month_names)),
                          'function' : None,
                          'data' : {}
                          }
            self.events.append(event_data)
            self.update_event(label_name, **kwargs)

        def update_event(self, label_name, **kwargs):
            event = None
            for k in self.events:
                if k['name'] == label_name:
                    event = k
                    break
            if not event:
                raise KeyError # Not found
            for k in kwargs:
                if k == 'name': continue # cannot update label name
                elif k in ['hour', 'day', 'weekday', 'month']:
                    event[k] = self.get_number_range_for(k, kwargs[k])
                elif k == 'function':
                    if globals(kwargs[k]):
                        event[k] = kwargs[k]
                else:
                    # Unknown keyword, store in data
                    event['data'][k] = kwargs[k]

        def get_number_range_for(self, type, data):
            number_range = []
            if not isinstance(data, (list, tuple)):
                data = [data]
            for data_part in data:
                if isinstance(data_part, int):
                    number_range.append(data_part)
                elif isinstance(data_part, basestring):
                    # A string... let's play
                    type_names = self.get_list_of_names_for(type)
                    # Try entire string
                    index = self.get_index_for_name(type_names, data_part)
                    if index > -1:
                        number_range.append(index)
                    elif " to " in data_part:
                        start, end = data_part.split(" to ")
                        start_index = self.get_index_for_name(type_names, 
                                                              start)
                        end_index = self.get_index_for_name(type_names, 
                                                            end)
                        if start_index == -1 or end_index == -1:
                            raise KeyError
                        while start_index <= end_index:
                            number_range.append(start_index)
                            start_index += 1
                            if start_index == len(type_names):
                                start_index = 0
                elif isinstance(data_part, (list) ):
                    # python 2.7 recognizes range as list
                    for k in data_part:
                        number_range.append(k)
            return number_range

        def get_list_of_names_for(self, type='hour'):
            if type == 'hour':
                ret = [k for k in range(0, 24)]
                for hour_name in hour_names:
                    ret[hour_name[0]] = hour_name[1]
                return ret
            if type == 'weekday':
                return [k for k in weekday_names]
            if type == 'month':
                return [k[0] for k in month_names]
            if type == 'day':
                return range(1, 32)
            else:
                raise KeyError

        def get_index_for_name(self, name_list, name):
            try:
                return int(name)
            except:
                pass # Silently pass
            if name in name_list:
                return name_list.index(name)
            elif _(name) in name_list:
                return name_list.index( _(name) )
            return -1

        def test_event(self, event, hour=None):
            hour = self.get_hour(hour) 
            # event is a dictionary
            if not hour % 24 in event['hour']:
                return False
            if not self.get_weekday_number(hour) in event['weekday']:
                return False
            if not self.get_day_of_month(hour) in event['day']:
                return False
            if not self.get_month_number(hour) in event['month']:
                return False
            if event['function']:
                return globals(event['function'])()
            return True

        def get_event_data(self, label_name):
            for k in self.events:
                if k['name'] == label_name:
                    return k
            return False

        def get_duration_for_event(self, label_name):
            event = self.get_event_data(label_name)
            if 'duration' in event['data']:
                return event['data']['duration']
            return default_event_duration

        #
        # Utility function to return a ren'py say-able string showing
        # the availability and data held against a named label event
        #
        def get_event_data_str(self, label_name):
            ret = "Data for label '{0}': ".format(label_name)
            event = self.get_event_data(label_name)
            if event:
                ret += "Availability: "
                for k in ['hour', 'day', 'weekday', 'month']:
                    ret += "{0} = ".format(k)
                    if not len(event[k]):
                        ret += "No data ... "
                    else:
                        names = self.get_list_of_names_for(k)
                        for v in event[k]:
                            if k != 'day' and names[v]:
                                v = names[v]
                            ret += "{0}, ".format(v)
                        ret = ret[:-2] + " ... "
                if ret[-2:] == ". ":
                    ret = ret[:-5]
                else:
                    ret += "No data"
                ret += " --- Function: {0}".format(event['function'])
                ret += " --- Data: "
                for k in event['data']:
                    ret += "{0} = {1}, ".format(k, event['data'][k])
                if ret[-2:] == ", ":
                    ret = ret[:-2]
                else:
                    ret += "No data"
            else:
                ret += "No data found"
            return ret

        # Find and return the next hour (after passed hour value) 
        # upon which an event occurs, else -1
        def get_next_event_hour(self, hour=None):
            hour = self.get_hour(hour)
            max_hours = sum(len(k[1]) for k in month_names) * 24
            while hour <= max_hours:
                hour += 1
                for event in self.events:
                    if self.test_event(event, hour):
                        return hour
            return -1

        # How many hours between passed hour value and the next event(s)
        def get_hours_until_next_event(self, hour=None):
            hour = self.get_hour(hour)
            return self.get_next_event_hour(hour) - hour

        # Get a list of events available for passed event hour
        def get_events_for_hour(self, hour=None):
            hour = self.get_hour(hour)
            events = []
            for event in self.events:
                if self.test_event(event, hour):
                    events.append(event)
            return events

        # Choice menu actions should call this before any event jump
        # to automatically add the duration to the stored hour
        def handle_choice_menu_action(self, *args, **kwargs):
            duration = 1
            if 'data' in kwargs:
                if 'duration' in kwargs['data']:
                    duration = int(kwargs['data']['duration'])
            self.advance_time(duration)
            renpy.checkpoint()
            return None

    #
    # Instantiate the class
    #
    event_handler = EventHandler()

    #
    # End of the Python stuff
    #


          ######################################
          #       Automated Event Menu         #
          ######################################

#
# Dunno if these styles actually do much
#
# Put these  in gui.rpy if you want
#

define gui.event_choice_button_width = gui.choice_button_width
define gui.event_choice_button_height = gui.choice_button_height
define gui.event_choice_button_tile = gui.choice_button_tile
define gui.event_choice_button_borders = gui.choice_button_borders
define gui.event_choice_button_text_font = gui.text_font
define gui.event_choice_button_text_size = gui.text_size
define gui.event_choice_button_text_xalign = 0.5
define gui.event_choice_button_text_idle_color = "#cccccc"
define gui.event_choice_button_text_hover_color = "#ffffff"

define gui.event_choice_text_font = gui.text_font
define gui.event_choice_text_size = gui.text_size
define gui.event_choice_text_xalign = 0.5

#
# Amend and tweak as desired
#
# Put in screens.rpy if you want
#

screen event_choice():
    $ events = event_handler.get_events_for_hour()
    modal True
    style_prefix "event_choice"
    vbox:
        # 
        # A String showing the current time/date
        #
        # Comment it out if desired
        $ t = "{0}".format(str(event_handler))
        text "[t]"
        for event in events:
            python:
                #
                # Build the TextButton text string
                #
                caption = ""
                #
                # Check for inline image on left
                if 'image_left' in event['data']:
                    caption = "\{image={0}\} ".format(
                                                event['data']['image_left'])
                if 'caption' in event['data']:
                    caption = "{0}{1}".format(caption,
                                              event['data']['caption'])
                else:
                    # label name with spaces and capitals
                    name_parts = event['name'].split('_')
                    for name_part in name_parts:
                        caption = "{0}{1}{2}".format(
                                    caption, 
                                    "" if name_part == name_parts[0] else " ",
                                    name_part.capitalize())
                duration = default_event_duration
                if 'duration' in event['data']:
                    duration = int(event['data']['duration'])
                #
                # We could easily add extra info here saying how long the
                # event is going to take
                #
                # Comment it out if desired
                caption = "{0} ({1} hour{2})".format(caption,
                                                     duration,
                                                     "" if duration == 1 \
                                                        else "s")
                #
                # Finally check for inline image on right
                if 'image_right' in event['data']:
                    caption = "{0} \{image={1}\} ".format(
                                                caption,
                                                event['data']['image_right'])
                #
                # End Build TextButton text string
            textbutton "{0}".format(caption):
                action [ Function(event_handler.handle_choice_menu_action, \
                                  data = {'duration': duration}),
                         Hide("event_choice"),
                         Jump(event['name'])
                       ]
        # Finally a button for passing time
        $ next_event_offset = event_handler.get_hours_until_next_event()
        if next_event_offset > -1:
            textbutton "Wait Until Next Choices in {0} hour{1}".format(
                                    next_event_offset,
                                    "" if next_event_offset == 1 else "s"):
                action [ Function(event_handler.handle_choice_menu_action, \
                                  data = {'duration': next_event_offset}),
                         Hide("event_choice"), #_menu_action, **event),
                         Jump("just_pass_time")
                       ]
        elif not len(events):
            # 
            #
            # You might want to change this a bit
            #
            # Game end button 
            #
            textbutton "Nothing more to do... pass out drunk":
                action [ Hide("event_choice"), #_menu_action, **event),
                         Jump("end_of_game")
                       ]

#
# End of choice menu screen code
#


          ######################################
          #       Basic Non Event Labels       #
          ######################################

label start:
    "You are horribly thirsty... \
    \n... and it is too late to hit a pub."
    show screen event_choice
    "So, what would you like to do?"
    return

label just_pass_time:
    show screen event_choice
    "Time Passed. What to do now?"

label end_of_game:
    $ hours_until_next_event = event_handler.get_hours_until_next_event()
    if hours_until_next_event > -1:
        show screen event_choice
        "Duped by a dodgy rollback... This text should not appear"
    "That's all folks!"
    return

          ######################################
          #            Event Labels            #
          ######################################

#
# Kings Head
#
init python:
    event_handler.add_event("drink_at_kings_head",
                            hour = [20,21],
                            weekday = "Monday to Wednesday",
                            duration = 5,
                            day = range(1, 6),
                            caption = "Drink at The King's Head",
                           )
label drink_at_kings_head:
    # This would show the event data for named label
    $ d = event_handler.get_event_data_str('drink_at_kings_head')
    "You drink at the King's Head while reading the debug output... \
    \n{size=-7}\n[d]{/size}"
    $ duration = event_handler.get_duration_for_event("drink_at_kings_head")
    "Sophie serves the drinks. She's cute. [duration] hours pass in a blink"
    #
    # Inline hour advance (do NOT use in start label though)
    $ event_handler.advance_time(1)
    "She used her charm to persuade you to stay another hour."
    #
    show screen event_choice
    "Sophie calls last orders. \nWhat to do kangaroo?"

#
# Wier
#
init python:
    event_handler.add_event("drink_at_wier",
                            hour = "20 to 22",
                            weekday = ["Tuesday", "Thursday"],
                            day = [1,2, "22 to 26"],
                            duration = 4,
                            caption = "Drink at The Wier"
                           )
label drink_at_wier:
    "You drink at The Wier"
    $ duration = event_handler.get_duration_for_event("drink_at_wier")
    "Kirsty serves the drinks. [duration] hours have passed"
    show screen event_choice
    "Kirsty calls last orders. \nWhat's the plan pelican?"

#
# Home
#
init python:
    event_handler.add_event("drink_at_home",
                            hour = [19],
                            weekday = ["Tuesday to Thursday", "Saturday"],
                            day = range(4,14),
                            duration = 3,
                           )
label drink_at_home:
    "You drink at home... alone... while playing Ren'py games, yay."
    show screen event_choice
    "Waiting for a download to finish, you find your glass empty. \
     \nWhat now brown cow?"

#
# Midnight Whisky
#
init python:
    event_handler.add_event("drink_lemonade",
                            hour = 0,
                            weekday = "Monday",
                            day = range(1,8), # first monday midnight
                            duration = 1,
                           )
label drink_lemonade:
    "You have a sneaky midnight soda, a nice Lemonade"
    show screen event_choice
    "That hit the spot. \nTime to sleep and count lil sheep?"

#
# Champagne Xmas
#
init python:
    event_handler.add_event("drink_champagne",
                            hour = range(8, 24),
                            day = 25,
                            month = "December",
                            duration = 3,
                           )
label drink_champagne:
    "You dive into the wine cellar and sit with the Champagne.\
    \nSoon you are sipping a glass of bubbly."
    show screen event_choice
    "Still no sign of Santa. \nWhat's the choice tortoise?"
With a few more tweaks I might add it to the cookbook too.
Frameworks & Scriptlets:

User avatar
chapscher
Newbie
Posts: 11
Joined: Sun May 07, 2017 12:05 am
Tumblr: chapscher
Contact:

Re: [SOLVED] time announcement calendar. working with tuples

#14 Post by chapscher »

OH MY GOD.

Thank you so much for your reply, I can't believe I didn't see it until right now. I'm sorry for the delay in my response. It's kinda late but I'm going to look into this right away.

xplosion
Newbie
Posts: 10
Joined: Sat Jul 21, 2018 3:49 pm
Contact:

Re: [SOLVED] time announcement calendar. working with tuples?

#15 Post by xplosion »

Thanks for this guys

Post Reply

Who is online

Users browsing this forum: Google [Bot]