Do you want to build a sleep event?
anjuna edited this page 4 months ago

How to build Sleep Events

Anjuna
Grand Duke of Telecommunications
December 9, 2023

1 Introduction

Welcome to the tutorial on the sleep cycle, and how you can interact with it. I am very much aware of how large this document is, how bad I am in writing it, and how daunting working with this can be. What I hope you’ll quickly realise is that a lot of this code is there to ensure that you do not have to think about how this all works. There are specific places where you can add your code to it (either directly, or through mods) and you can ignore everything else. I hope this helps you.

  • Do you want to understand which locations does what? Section 2 has a general overview and section 3 goes into further depth.
  • Have an event ready, and want to add it to the sleep cycle? Section 4 and section 4.3 in particular will help you out.
  • Do you want examples on how to build events for the sleep cycle? Section 4.3.2 has you covered.
  • Do you have a mod and want to know how to interact with the sleep cycle? Section 5 explains it all.

If you have any other questions, you can always ask for help at the Discord.

I wish you a happy coding experience.

Your truly,

Anjuna

2 General Overview of the Sleep Cycle

Let us start by understanding the general flow of the Sleep Cycle which is captured in Figure 1 for a visual shorthand.

[figure here]

Figure 1: General Overview of the Sleep Cycle

The entire sleep package contains 12 different locations:

  1. bed
  2. bed_events
  3. bed2
  4. bed_get_out
  5. bed_get_out events
  6. pre_sleep
  7. pre_sleep_events
  8. sleep
  9. dream_events
  10. sleep_events
  11. wakeup
  12. wakeup_events

2.1 bed

When Sveta starts to lie in bed, she moves to the bed location. Code which must fire before lying in bed events and the lying in bed hub (bed2) goes here. After this, she moves to the bed_events location.

2.2 bed_events

We check for any events that happen as Sveta wants to lie in her bed. Afterwards we move to bed2, which is the main lying in bed hub.

2.3 bed2

The main hub when Sveta lies in bed. From bed2 she can read a book, access her alarmclock, and more. Of importance to us, Sveta can either go to sleep (which moves her to the pre_sleep location) or get out of her bed (which moves her to the bed_get_out location).

2.4 bed_get_out

After deciding to leave her bed, Sveta moves to the bed get out location, from here any code is evaluated which trigger on Sveta leaving her bed, after which we move to the bed_get_out_events location. After returning from there we finally move back to the bedroom.

2.5 bed_get_out_events

Here we check for any events related to getting out of bed. Most of these will probably remove Sveta from the sleep cycle, if not (either because no event is chosen, or it doesn’t remove us from the sleep cycle) we go back to the bed get out location.

2.6 pre_sleep

When Sveta decides to go to sleep, we move to the pre_sleep location. We start be evaluating all code which must trigger before any events, after this we move to the pre_sleep_events location, and then return here. After returning from the pre_sleep_events location, all of the code that should happen after the events but before any sleep or dreams triggers. This includes undressing, plugs, and makeup. After this Sveta moves to the sleep location

2.7 pre_sleep_events

After the initial setup in pre_sleep we check whether there are any events which should trigger before Sveta actually goes to sleep, and if so pick one at random (there is a priority queue for events linked to quests). If an event is chosen it can either have Sveta exit the sleep cycle (for example Sveta is kidnapped and ends up in an abandoned warehouse or something), or continue the sleep cycle afterwards. If the sleep cycle is continued (either because no event is chosen, or the event ends in the continuation of the sleep cycle), Sveta continues in the pre_sleep location.

2.8 sleep

After the preparations done in pre_sleep, Sveta can now actually start sleeping, well almost. First Sveta moves to the dream events location where a dream is chosen. Afterwards Sveta moves to actual sleep loop. Here time advances and we move back and forth to sleep events. Finally after finishing the sleep loop, Sveta moves to the wakeup location.

2.9 dream_events

We move to dream_events at the start of the sleep location. Here we choose a dream which will be shown while time advances during the sleep loop. These dreams will happen before any time advances. Afterwards Sveta returns to sleep.

2.10 sleep_events

During the sleep loop in sleep we move here to check whether any events trigger. If no events trigger, or the event ends with Sveta asleep (again), we return back to sleep.

2.11 wakeup

After the sleep loop has concluded, we move to wakeup to run any code that must happen after finishing sleep, but before any events trigger. Then we move to wakeup events, after which we move back. Finally, Sveta is moved to bed get out to get out of her bed.

2.12 wakeup_events

Here we check for any events which trigger on waking up. If no events trigger, or the event concludes with Sveta still waking up (in her bed), we return back to wakeup

3 The Sleep Cycle in depth

3.1 bed

bed has a fairly simple structure, consisting of only 2 locations: start and mod sleeptriggers. bed is entered as gt ‘bed’, ‘start’ or gt ‘bed’.

[figure here]

Figure 2: The bed location

3.1.1 start

This sublocation is used for triggers which happen before any events that trigger on going to lie in bed. Currently there are none. Sveta is automatically moved to bed, mod sleeptriggers.

3.1.2 mod_sleeptriggers

This sublocation is used so mods have a moment to run relevant code. See section 5 on how this works. Sveta is automatically moved to bed events.

3.2 bed_events

bed events has a relatively complicated structure that we will discuss fully in chapter 4. It is entered as gt ‘bed_events’, ‘start’ Afterwards Sveta is automatically moved to bed2

3.3 bed2

bed2 is the main hub where Sveta lies in bed. It consists of 3 main locations (start, mod_sleeptriggers, and main) and multiple actions that can be taken (reading, masturbating, accessing the alarmclock, going to sleep, and more). It is usually entered as gt ‘bed2’, ‘start’.

[figure here]

Figure 3: The bed2 location

3.3.1 start

This sublocation handles any triggers that need to be set after any potential lying down event has resolved. Sveta is automatically moved to bed2, mod sleeptriggers

3.3.2 mod_sleeptriggers

This sublocation is used so mods have a moment to run relevant code. See section 5 on how this works. Sveta is automatically moved to bed2, main.

3.3.3 main

The main hub where Sveta is lying awake in bed. From here Sveta can access a variety of actions, including (but not limited to): setting her alarm; deciding to wear her underwear, buttplug, or vibe while sleeping; reading a book; masturbating; going to sleep; and getting out of bed. In particular, if Sveta gets out of bed she moves to bed get out. If she decides to go to sleep, she’ll move to pre sleep.

3.4 bed_get_out

bed get out is responsible for resolving any code related to getting out of bed. It consists of 3 sublocations: start, mod_sleeptriggers, end. The location is entered as xgt ‘bed_get_out’, ‘start’.

[figure here]

Figure 4: The bed_get_out location

3.4.1 start

Here all code is run that has to happen before events which happen on Sveta getting out of bed. Sveta is automatically moved to bed get out, mod_sleeptriggers

3.4.2 mod_sleeptriggers

This sublocation is used so mods have a moment to run relevant code. See section 5 on how this works. Sveta is automatically moved to bed get out events.

3.4.3 end

This sublocation sends Sveta to the correct bedroom. It is called by bed get out events.

3.5 bed_get_out_events

bed get out events has a relatively complicated structure that we will discuss fully in chapter 4. It is entered as xgt ‘bed_get_out_events’, ‘start’ Afterwards Sveta is automatically moved to bed_get_out, end.

3.6 pre sleep

pre sleep runs all of the code in preparation of for the sleep cycle, in particular it runs code related to undressing, routines, etc. It contains 5 sublocations: start, pre_sleep2, prepare_sleep, mod_sleeptriggers, and end. It is entered as gt ‘pre_sleep’, ‘start’

[figure here]

Figure 5: The pre_sleep location

3.6.1 start

This location runs any code that has to happen before events. Currently there are none. Sveta is automatically moved to pre sleep events

3.6.2 pre_sleep2

Called by pre sleep events, and it deals with undressing Sveta. Sveta is automatically moved to pre sleep, prepare sleep

3.6.3 prepare_sleep

Here messages are displayed about Sveta’s nightly routine, including removing plugs/vibes, wearing/removing underwear, wearing makeup. It also runs any code that happens after any events. Sveta is is automatically moved to pre_sleep, mod_sleeptriggers.

3.6.4 mod_sleeptriggers

This sublocation is used so mods have a moment to run relevant code. See section 5 on how this works. Sveta is automatically moved to pre_sleep, end.

3.6.5 end

pre_sleep, end exists to raise set an act which takes Sveta to sleep.

3.7 pre_sleep_events

pre sleep events has a relatively complicated structure that we will discuss fully in chapter 4. It is entered as gt ‘pre sleep events’, ‘start’ Afterwards Sveta is automatically moved to pre_sleep, pre_sleep2.

3.8 sleep

sleep is the main location where time advances and contains 6 sublocations (start, post_dream, sleep_handler, sleep_loop, mod_sleeptriggers, and post_sleep) and 2 function (calc_minutes_to_wakeup, is_tomorrow_school_vacation). It is usually called as gt ‘sleep’, ‘start’.

[figure here]

Figure 6: The sleep location. The dashed lines indicate that sleep loop calls mod sleeptriggers and sleep events, start using gosub and the dotted line indicates that if no event is chosen sleep loop continues on.

3.8.1 start

This location runs any code that has to happen before a dream is set. Currently there are none. Afterwards Sveta is automatically moved to dream events.

3.8.2 post_dream

After a dream is chosen, post dream calculates to minutes needed to get a full nights rest: (100 − pcs sleep) ∗ 6 + 150 + rand(0, 60). Afterwards Sveta is automatically moved to sleep, sleep handler

3.8.3 sleep_handler

sleep handler first calculates how many minutes are needed before Sveta wakes up, this is done using the calc_minutes_to_wakeup (see below). If Sveta still has time left to sleep, she moves to sleep, sleep_loop; otherwise she moves to sleep, post_sleep.

3.8.4 sleep_loop

Here time is actually advanced. Code is run each minute and sleep, mod_sleeptriggers and sleep_events are called continuously. NOTE: sleep_events is only called once every 5 minutes. When the loop completes, Sveta is automatically moved to sleep, post_sleep

3.8.5 mod_sleeptriggers

This sublocation is used so mods have a moment to run relevant code. See section 5 on how this works. This sublocation is called with as gs ‘sleep’, ‘mod_sleeptriggers’ and is a dead end. The sleep_loop continues on afterwards.

3.8.6 post_sleep

Here any code is run on the completion of the sleep loop, including penalties for having too little sleep. Afterwards Sveta is automatically moved to wakeup

3.8.7 calc_minutes_to_wakeup

This function is used to calculate the number of minutes until Sveta wakes up. It takes the time needed until a full rest (calculated in sleep, post_dream and compares this to her alarm. During the checks for holiday alarm times is_tomorrow_school_vacation is called. As a function this sublocation is a dead end (and called with a gs).

3.8.8 is_tomorrow_school_vaction

This function is used to find out whether tomorrow is a school vacation. It is used in the check for the holiday alarm. As a function this sublocation is a dead end (and called with a gs).

3.9 dream_events

dream events has a relatively complicated structure that we will discuss fully in chapter 4. It is entered as gs ‘dream_events’, ‘start’ Afterwards Sveta is automatically moved to sleep, post dream.

3.10 sleep_events

sleep events has a relatively complicated structure that we will discuss fully in chapter 4. It is entered as gs ‘sleep_events’, ‘start’ Afterwards one of multiple things can happen:

  1. If no events trigger, the location is a dead end and the sleep_loop can continue.
  2. If an event has happened, and Sveta resumes sleeping, and a new dream is needed; Sveta is moved to sleep, start
  3. If an event has happened, and sveta resumes sleeping, but no dream is needed; Sveta is moved to sleep, sleep_handler
  4. If an event has happened, and Sveta stops sleeping, the event moves her to the correct location.

3.11 wakeup

wakeup handles all the code related to waking up (but not getting out of bed). It consists of 3 sublocations (start, mod_sleeptriggers, and get_out) and 1 function snooze_alarm. It is usually called as xgt ‘wakeup’, ‘start’.

[figure here]

Figure 7: The wakeup location. The dashed line indicated that get out calls snooze alarm with a gosub.

3.11.1 start

Start handles any code before events related to waking up. Afterwards Sveta is automatically moved to mod sleeptriggers.

3.11.2 mod_sleeptriggers

This sublocation is used so mods have a moment to run relevant code. See section 5 on how this works. Sveta is automatically moved to wakeup_events.

3.11.3 get_out

get out sets the relevant actions related to getting out of bed, mostly related to routines. These actions lead to bed_get_out.

3.11.4 snooze_alarm

This function sets an act to snooze a few minutes more and sleep in. As a function this sublocation is a dead end (and called with a gs).

3.12 wakeup_events

wakeup events has a relatively complicated structure that we will discuss fully in chapter 4. It is entered as xgt ‘wakeup_events’, ‘start’ Afterwards Sveta is automatically moved to wakeup, get_out.

4 Events in depth

Each event location follows the same, general, structure to make coding for them easier. This structure is captured in Figure 8 for a visual shorthand. The event locations are always initially entered through ‘....’, ‘start’.

[figure here]

Figure 8: General Overview of the Event locations. Dashed lines indicate that the (external) event is called and calls other locations using gosub.

4.1 Sublocations

4.1.1 start

Here we check, for each event, whether it should trigger. If it does we add it to the queues (for more info see section 4.3). We automatically move to mod_sleepevents.

4.1.2 mod_sleepevents

This sublocation is used so mods have a moment to add events to the queues (again, see section 4.3). See section 5 on how this works. We automatically move to event_handler.

4.1.3 event_handler

Here we check whether there are any events in the queues (section 4.3), if not (or we’ve already had enough events happen) we move to continue. If there are events in the queues (and we can still show more), the following happens:

  1. If there are events in the priority queue, move to event_handler2, priority
  2. Otherwise, if there are events in the normal queue, move to event_hander2 Most of the time, only a single event is allowed to happen, afterwards we are moved to continue

4.1.4 event_handler2

Here we pick a random event from the appropriate queue (section 4.3) and execute it. The event must either call event_end (if the event does not leave the sleep cycle) or exit (if it does).

4.1.5 event_end

When the event ends it calls gs ‘...’, ‘event_end’. If there are still events left in the priority queue (section 4.3) there is the option of moving to event handler2, priority (at the time of writing, this option is disabled). We then move to event handler. Notice that an event has now happened, which means that eventually event handler will direct us to continue.

4.1.6 exit

When the event leaves the sleep cycle it needs to call gs ‘...’, ‘exit’ to clean up any remaining variables.

4.1.7 continue

Here any variables related to the event location are cleaned up, and we are moved along to the next location in the sleep cycle.

4.2 sleep_events and event_end

At the end of an event during the sleep cycle (and at the time of writing, only in sleep_events) there are actually three options:

  1. Continue on with the sleep loop: gs ‘sleep_events’, ‘event end’, ‘sleep’ or gs ‘sleep_events’, ‘event_end’. This is best chosen when Sveta didn’t “wake up” during the event, and the final screen can be kept for the rest of the sleep.
  2. Choose a new dream: gs ‘sleep_events’, ‘event_end’, ‘dream’. This is best chosen when Sveta “wakes up” during the event and then chooses to go back to sleep. This also recalculates the time that Sveta needs to sleep and can cause her to sleep for longer.
  3. Wake up: gs ‘sleep_events’, ‘event_end’, ‘wake’. This is chosen when Sveta “wakes up” during the event and decides to get out of bed. It is equivalent to gs ‘sleep_events’, ‘exit’ & gs ‘wakeup’, ‘start’.

4.3 Queues and how to stage events

The event locations use two different queues where events can be staged:

  1. $sleep_events_priority
  2. $sleep_events These names are reused in every location (so queues in bed events are named $sleep_events), this should make working with this system slightly easier.

4.3.1 How do I stage an event?

Let us suppose that you have written an event, located at ‘your_event_loc’, ‘your_event_arg’, how do you add this to the system?

  1. Create a dummy sublocation in the event location which looks as follow:

    if $ARGS[0] = ‘your_event_name’:
    gt ‘your_event_loc’, ‘your_event_arg’
    end
    
  2. Add an if statement to the event location in start with you conditions as follows (‘‘event location’’ is the current location, for example bed events, or wakeup events):

    if [insert your conditions here]:
    $sleep_events[] = ‘gs ‘‘event_location’’, ‘‘your_event_name’’ ’
    end
    
  3. If your event must fire as soon as possible, use $sleep_events_priority[] instead.

  4. At the end of your event, if it returns to the sleep cycle, you use:

    gs ‘event_location’, ‘event_end’
    
  5. At the end of your event, if it does not returns to the sleep cycle, you use:

    gs ‘event_location’, ‘exit’
    gt ‘location_of_your_choosing’, ‘arg_of_your_choosing’
    

4.3.2 Examples

Example 1: We have written an event where Kolka assaults Sveta when she goes to sleep while horny, between 21:00 and 00:00, Anya isn’t there, and Sveta and Kolka have had sex before. Afterwards Sveta goes back to sleep. First of all, this event should trigger in pre sleep events due to the fact that it triggers when you go to sleep. So we add:

if $ARGS[0] = ‘brother_assault’:
    gt ‘pre_sleep_events’, ‘brother_assault2’
end
if $ARGS[0] = ‘brother_assault2’:
    ‘You’’re lying in bed, the room quiet, tingles in your nether region, as you hear the door to ...
    ...
    ...
    act ‘Go to sleep’:
        gs ‘pre_sleep_events’, ‘event_end’
    end
end

At the end of pre_sleep_events.

Under pre_sleep_events, start we add:

if hour >= 21 and (locat[’Anya_inroom’] = 0 or locat[’Anya’] = 1 or locat[’Anya’] = 26)
            and pcs_horny >= 75 and brotherSex > 0:
    $sleep_events[] = ‘gs ‘‘pre_sleep_events’’, ‘‘brother_assault’’ ’
end

The start of start now looks like:

if $ARGS[0] = ’start’ or $ARGS[0] = ’’:
    menu_off = 1
    killvar ’$sleep_events’
    killvar ’$sleep_events_priority’
    if sleepVars[’events_active’] = 1:
        sleepVars[’events_done’] = 0
        if hour >= 21 and (locat[’Anya_inroom’] = 0 or locat[’Anya’] = 1 or
                    locat[’Anya’] = 26) and pcs_horny >= 75 and brotherSex > 0:
            $sleep_events[] = ‘gs ‘‘pre_sleep_events’’, ‘‘brother_assault’’’
        end
        if succubusQW = 2:
            $sleep_events_priority[] = ’gs ’’pre_sleep_events’’, ’’suc_event’’ ’
        end
        ...

Example 2: We have written a collection of sexy dreams that Sveta can get when she is under the influence of an aphrodisiac. These are just an image and some text. This should trigger in dream events. Since we don’t need to goto anywhere, we can add the following to the end of dream_events:

if $ARGS[0] = ‘aphro_dreams’:
    dream_rand = rand(0, 9):
    if dream_rand = 0:
        ‘You dream that you’’re in the middle of a endless orgy, the pleasure blindingly pink as
    elseif dream_rand = 1:
        ...
    end
    gs ‘dream_events’, ‘event_end’
end

And we add the following to dream events, start:

if aphrodisiac_timer > 0:
    $sleep_events[] = ‘gs ‘‘dream_events’’, ‘‘aphro_dreams’’ ’
end

Example 3: We have written a chain of quests where Sveta investigates Vadim Bely, and as part of this quest (say when BelyQW[‘investigation’] = 5) Sveta gets kidnapped while sleeping. The event itself is located in ‘Beli invest’, ‘sleep kidnap’. This should probably trigger in pre_sleep_events since it’s a singular event (since sleep_events are checked many, many times during the sleep_loop), and as such we add:

if $ARGS[0] = ‘bely_kidnap’:
    gt ‘Beli_invest’, ‘sleep_kidnap’
end

at the end of pre_sleep_events. Because this event is related to a quest line, and only triggers once anyway, we really want it to trigger as reliably as possible (though maybe still with some randomness). As such this is a priority event and thus we add the following to start

if BelyQW[‘investigation’] = 5 and rand(0, 5) = 0:
    $sleep_events_priority[] = ‘gs ‘‘pre_sleep_events’’, ‘‘bely_kidnap’’ ’
end

Furthermore, since Sveta is kidnapped, she won’t return to the sleep cycle. So at some point the event must call gs ‘pre_sleep_events’, ‘exit’.

4.3.3 Why use gosub and dummy locations?

Some locations really benefit from a gosub setup (notably dream events and possibly sleep events) as such we have implemented this everywhere to reduce the difficulty of working with this system. You always use gs to enter and exit the events, in ever single one of these event locations. This is significantly simpler than having to switch between gt, gs, and xgt depending on what you’re coding for. Furthermore the $sleep events strings are evaluated using dynamic (which can be tricky to work with), but we also build in some saveguards. As such most of the time this allows us to either escape dead ends, or get stuck in a known location which makes it easier to debug.

5 Mods

So you are building a mod, and you want to run some code during the sleep cycle and add some events. Be sure you understand where you want to inject this code (see the previous sections for more information).

5.1 Running code

If you want to run code during specific part of the sleep cycle, it can be done relatively easily:

  1. Choose the relevant location from:
    • bed
    • bed2
    • pre_sleep
    • sleep
    • wakeup
    • bed get out
  2. Add an if-block to the main location of your game with:

    if $ARGS[0] = [insert location here] and $ARGS[1] = ‘mod_sleeptriggers’:
        [insert code here]
    end
    
  3. There should not be any gt or xgt out of this location.

5.1.1 Examples

Example 1 We have created a drug which slowly alters the body during sleep. Every 10 minutes of sleep Sveta gains some experience for a random stat. This code should execute during sleep. As such we add the following to the main location of our mod:

if $ARGS[0] = ‘sleep’ and $ARGS[1] = ‘mod_sleeptriggers’ and (sleepVars[‘stime’] mod 10 = 0):
    temp_rand = rand(0, 9):
    if temp_rand = 0:
        pcs_stren_exp += rand(5, 10)
    elseif temp_rand = 1:
        pcs_vital_exp += rand(5, 10)
    ...
end

5.2 Adding an event

The setup of your events is essentially the same as we discussed before:

  1. Choose the relevant location from:

    • bed_events
    • pre_sleep_events
    • dream_events
    • sleep_events
    • wakeup_events
    • bed_get_out_events
  2. Add an if-block to the main location of your game with:

    if $ARGS[0] = [insert location here] and $ARGS[1] = ‘mod_sleepevents’:
        if [insert conditions here]:
            $sleep_events[] = ‘gs ‘‘mod_eventloc’’, ‘‘event_arg’’ ’
        end
    end
    

5.2.1 Examples

Example 1: We have a mod (called shocker) which adds a shock clit piercing, which can randomly shock Sveta if she doesn’t conform to specific rules. During sleep there is a 0.1% chance each minute that Sveta will get shocked awake. This is an event which should trigger in sleep_events. Furthermore since sleep_events is called only once every 5 minutes, that means there is a 0.5% chance that the shock should trigger when we check for the event. We’re also okay with the fact that it might get overwritten by another event, since this is a repeatable (so we don’t use $sleep_events_priority). As such we add the following to the main location of our mod:

if $ARGS[0] = ‘sleep_events’ and $ARGS[1] = ‘mod_sleepevents’ and [does not conform to rules] and 
    $sleep_events[] = ‘gs ‘‘mod_shocker_sleep_event’’, ‘‘sleep_shocked’’ ’
end

In the mod_shocker_sleep_event location we have the main body of the code. We also have an option to go back to sleep (with an event end call) and to get out of bed (with an exit call):

if $ARGS[0] = ‘sleep_shocked’:
    xgt ‘mod_shocker_sleep_event’, ‘start’
end
if $ARGS[0] = ‘start’:
    ‘Suddenly pain flares through your clit.’
    act ‘wakeup’:
        gt ‘mod_shocker_sleep_event’, ‘ev1’
    end
end
if $ARGS[0] = ‘ev1’:
    ...
    ...
    act ‘Go back to sleep’:
        gs ‘sleep_events’, ‘event_end’
    end
    act ‘Get out of bed’:
        gs ‘sleep_events’, ‘exit’
        gt ‘bed_get_out’, ‘start’
    end
end