HTML Tutorial Getting the most out of Sugarcube

PTSdev

Member
Oct 21, 2019
101
285
Guide version: 1.1

Hi there,

I've been thinking about making this thread for a while now. The goal is simple: I absolutely love HTML/SugarCube games and I want to share some of the things I've learned in the past two years since I started developing my own game. (Release: 2023)

Please note that this guide is aimed at people who are looking for an overview on the most frequently occurring questions / problems. I'll gladly provide help to specific problems if the need arises.

Disclaimer: This guide also contains my thoughts on some game design principles. Thanks to Alcahest for pointing out that they can be applied to non-Twine games as well.

1. THE BASICS
1.1. What is Twine / Sugarcube?
is a software that allows you to create browser-based stories. Sugarcube is a so-called story format. There are other decent formats out there, with Harlowe being the most popular one. But nothing beats Sugarcube when it comes to customization options.

1.2. Where to start?
You can use the desktop app to familiarize yourself with Twine's basic concepts, but if you want to create a large project, you have to use a code editing software and . Personally, I use VSCode, because there's the Twee3 extension for it, which comes with many useful features like code highlighting and macro management. For this guide to make sense, you'll have to download - do NOT use Sugarcube 1.

1.3. What is tweego?
Tweego is a little tool that allows you to compile .twee files into a single HTML file. Make sure to read the . I highly recommend using "watch mode", which allows you to compile projects on the fly.

1.4. What else do I need?
Basic programming skills are helpful, but not necessary. You can get more out of Sugarcube if you're familiar with JavaScript. I'll get back to that later.

2. GETTING STARTED
Before you start developing a Twine game, you have to think about the style you're aiming for. Twine excels at two types of games:
- Choose your own adventure (CYOA) novels
- Free roam sandboxes (if you put in some work)

A Twine story consists of passages. You can create links between them. On the most basic level, you can create a tree structure of passages. Player input decides upon which passage is displayed next. Each additional branch adds a layer of complexity to your story. You can merge branches again at some point.

If you go for a non-linear approach, I recommend using some kind of hub passage, i.e. a passage that allows the player to navigate to other passages. You can use the menu on the sidebar to easily add links to passages containing additional information (character sheets, questlogs, inventory) and so on.

2.1. Setup
Create a folder for your twee files. Think of adding sub-folders if your game is going to be complex. The folder hierarchy should be both logical and easy to use. Then create a new workspace in VSCode and set the workspace folder to your freshly created folder. Tell tweego to watch this folder.

Tweego command line:
tweego.exe -w -o test.html writing

(-w is the watch mode, -o is the output file, "writing" is the name of the watched folder)

For your game to work, you'll need the following special passages:
StoryInit - Here you define the story variables, arrays, maps and objects you're going to use. A story variable is stored in the game's history, while a temporary variable is not. Story variables look like this: $example, temporary ones look like this: _temp. If there are going to be things in your game that won't change during runtime, you can use setup instructions. (Please refer to the SC documentation.)
StoryMenu - the famous menu panel on the left side. We'll talk about customization later.
StoryBanner & StoryTitle - Self-explanatory. These are on the left top of your screen. You can use the StoryBanner passage for tasks like displaying character stats.
StoryData - Here you put the required information on the used format and the ifid. You can auto-generate this by setting up your project in the Twine software before you move to VSC/tweego.
StorySettings - some basic settings for the engine go here. You won't need these when you're just starting out.

Sugarcube follows a distinct process when a new passage is being loaded. You can use this to your advantage. These are the special passages you'll need:
PassageReady - Gets called with each passage transition and executes its contents BEFORE the passage is being rendered. Great for keeping track of variables and applying cyclical tasks.
PassageDone - When rendering is done, this passage gets called. It allows you to manipulate things that are already on the screen. We'll talk about DOM macros and CSS manipulation later.
PassageHeader & PassageFooter - Want to have a top / bottom bar? This is the way to go. You'll have to setup the styling for these parts of the page in your stylesheet.

IMPORTANT: If you want things to happen on the most fundamental level, you'll have to use the JavaScript part of your project. Technically, you can also manipulate displayed passages with the passagerender event, but this is not necessary for beginners.

2.2. The history system
A Twine game is always turn-based. A turn occurs when there's a passage transition. After each turn, the engine adds an entry to the story history. This allows players to roll back for a certain amount of passages. The exact amount can be defined in the JavaScript passage like this:

Config.history.maxStates = 5;

Do NOT set this to 0, because it causes all kinds of trouble. If your story uses a shitload of data, you might have to reduce the number of maxStates. If you set it to 1, the game runs the fastest, but there's no rollback option anymore.

2.2. Passage tags
The most important ones are:
[stylesheet] - A stylesheet passage. I recommend only using one of those. If your CSS is more complex, you can include multiple stylesheet passages.
[widget] - A widget passage. It can contain multiple widgets.
[nobr] - Omits line breaks. Highly recommended for widget passages and most other passages as well. You want your code to look clean and adding lots of \ achieves the opposite.

You can combine tags: [widget nobr]

2.3. Markup & Linking passages
Sugarcube uses its own markup language. You can create links between passages by using the Link markup and image links by using the image markup. It's also possible to define setters if you want variables to be changed with the next transition.

Example:
[[Displayed text|Passage][$variable to 22]]

You can also link passages by using the following macros:
<<link "Text" "passage">>...<</link>> Works similar to the markup above if you add the 2nd argument (passage). If you omit it, a link does not forward to another passage. You can execute scripts and other code snippets in the "..." area. Read the DOM warning below.

<<button>><</button>> Creates a button. Otherwise, it works exactly like <<link>>.

<<choice>> Creates a single use link that forwards to another passage. Can be used for dialogue systems. See below for more information.

Technically, you can also use HTML tags (<a>) to create links. This can be very useful if you want to create image links, because it allows you to add classes and custom styling easily. If you want to change story variables, you've got to use the data-setter argument. Forwarding to a passage can be achieved by adding the data-passage argument.

Every mentioned option has pros and cons. Experiment with them to get a feel for what they can do well.

2.4. There are so many macros... which ones are the most important?
Short answer: Control macros. <<if>>, <<switch>> and <<for>> are absolutely necessary. Here are some general tips:
- Avoid nesting dozens of <<if>> statements. There's always a way to keep things simple. Too much nesting makes your code unreadable.
- Use <<for>> to cycle through arrays and objects to perform certain actions like stat checks, trigger checks and so on. Avoid nesting long loops, as this leads to long loading times. Please use <<break>> and <<continue>> to shorten loop running times.
- <<if>> and <<switch>> excel at different use cases.

Long answer:
- <<silently>> can be neat if you have "invisible" calculations. You still should be using the [nobr] tag as often as possible.
- There are lots of interactive macros, please keep in mind that your game might be played by mobile users as well, so having lots of dropdown menus might be a problem for them.
- You can perform nice little tricks with macros like <<cycle>> or <<append>> and <<prepend>>. I won't go into details here.
- <<run>> and <<script>> are necessary if you want to execute JavaScript code on a passage.
- I'm not a friend of <<goto>>. It can be cool if you're using the NavOverride trick (see below), but otherwise I'd stay away from <<goto>> as it adds an unnecessary layer of complexity.

2.5. DOM warning
DOM refers to "Document Object Model", it's basically a standardized way of creating web interfaces. We don't have to go into details here. But you should be aware of DOM macros and Sugarcube's passage transition mechanics. As I've said, changes are stored in the history when a transition occurs. This means that things you manipulate on screen without a transition are NOT being saved. They'll get saved with the next transition.

This can lead to many problems. Let me quote the DOM warning from the Sugarcube documentation, as it's as precise as it gets:
Warning: All DOM macros require the elements to be manipulated to be on the page. As a consequence, you cannot use them directly within a passage to modify elements within said passage, since the elements they are targeting are still rendering, thus not yet on the page. You must, generally, use them with an interactive macro—e.g., —the , or within the . Elements that are already part of the page, on the other hand, present no issues.
This is VERY important. Do not try to manipulate story variables without using the given options.

2.6. General tips
- Only use story variables when necessary. Temporary variables are always an option. You don't want things like loop counters or single use variables to clog up the story history.
- Use <<capture>> to... capture loop counter states. This can be very useful if you create a list of links by running through a loop.
- Be cautious when it comes to using media passages. They can be nice to reduce load times, but you should not put large images or video files into the HTML file. Instead, you can link to them by using the normal HTML methods. (like <img source="path/image.jpg">)
- Familiarize yourself with functions and array methods. Manipulating arrays / objects is going to be very important if your game is complex.

3. PITFALLS AND HOW TO AVOID THEM
Sugarcube's basic structure can lead to lazy design decisions. Before we talk about specific solutions, it's important to have an idea on what we want to avoid.

3.1. The "Take a shower, get out of room, go to kitchen" loop
You all know what I'm talking about. These loops exist because it's easy to create a "circle" of passages. But they're getting tedious really quickly. Ask yourself: Does my game require such a loop for narrative reasons? If the answer is "yes", something interesting should happen in EVERY iteration of the loop. No empty days, no "skip time to progress" copouts. Each moment in the story should be meaningful.

3.2. The "Passage does not exist" issue
Managing big Sugarcube games with lots of passages can become overwhelming. That's why I insisted on creating a logical folder structure. But you can do more: If you have event types like dialogue scenes, you can use ONE passage that displays all the dialogue and store the different scenes in different .twee files / passages. All you've got to do is to include the dialogue passages into the container passage. This can be automated by using passage tags (for simpler stories) or an event system (for complex stories).

Another nice trick is to manipulate passages while they're being displayed. Remember the info about DOM macros, though.

3.3. The "go to the gym 100 times to progress" issue
As HTML games are text-based, it's hard to create mechanically interesting player actions. You mostly progress by navigating through passages. While progression can be linked to linear incrementation of stats, it should not rely on repetition. Of course, you've got to go to the gym many times in real life to get ripped, but you're actually DOING something there. In a Twine game, you only click on a link. If repeating tasks are a part of your game, think about adding mechanics (choices, skill checks, minigames) to them.


4. USEFUL KNOWLEDGE
4.1. Widgets
Widgets are a way to create macros without having to use JavaScript. You only use HTML and the Sugarcube markup. Generally, you should rely on widgets for repeating tasks. Since a recent update, widgets can be defined as containers. This can be used for something like speech boxes.

Widgets are called like macros, e.g. <<examplewidget>>. You can add arguments to each widget, like this: <<examplewidget "Laura" 2>>

Inside the widget definition, you refer to the arguments by using _args[INDEX], with index being the position of the argument after the widget name. So in our example "Laura" would be _args[0] and 2 would be _args[1]. The _args[x] temporary variables CAN'T be modified inside the widget. Please plan your widgets accordingly.

Some examples for widgets I use in my current project:
- Displaying images and videos
- Repeating calculations
- Changing menu elements depending on the current passage / passage tags
- Managing the day/week time cycle (we'll get to that later)
- Managing on the fly CSS shenanigans

4.2. Custom styling
It's fairly easy to change the look of a Sugarcube game. Technically, you can rebuild the entire stylesheet from scratch, but this isn't really necessary. Here are some quick fire tips:
- #ui-bar and #menu are your new best friends
- If you want to add background pictures for passages, you can use passage tags and link them to your CSS. Example:
Code:
body.beach {
    background-image: url("pics/facility/beach_bg.jpg");
    background-attachment: fixed;
    background-repeat: no-repeat;
    background-size: cover;
}
If you want to manipulate background images during runtime, you can look into the <<addclass>> and <<removeclass>> macros.
- Think about using flex or grid layouts. Personally, I'm using flex for the things that are being displayed in the passage container, because it makes styling so much easier.

5. FAQ
5.1. How do I create a time system?
First of all, you'll have to think about its layering. How many layers (years, months, days, hours...) are there going to be? Then you have to create a system that keeps track of time. The most simple way is to move forward one time step with each passage transition. This can be problematic if some of your passages only contain information and are not moving the story forward.

For cases like these, you'll need some kind of action point system. In my current project, I'm using a simple AP system that divides a week into 21 diferent "slots", three for each day. After certain actions, a point gets deducted and time moves forward. I prefer managing this in my JavaScript section.

5.2. How do I create an open world / free roam system?
The answer to this question depends on your game design. If you want the MC to move through a world (room A -> room B -> outside -> town) "naturally", the most simple way is to link passages to each other. This can become quite tedious for players, as they have to click through the same passages over and over again to reach the desired location. You can add a hub screen or a visual map (use an image map if you want to be fancy), to prevent this.

Locations can be simple passages, but you can also define objects in your StoryInit for each one. This allows you to streamline location management and add properties like "unlocked", "character_slots" and so on.

5.3. How do I create a quest system?
A quest usually is a series of tasks. Each task is completed by doing a certain thing inside the game. Having a quest object with all necessary elements is recommended. Here's an example from my game:

Code:
    {
        id: 0, handle: "Your second client", type: "minor",
        prereq: 1,         /* CHAPTER */
        stattus: 0, stage: 0, complete: 4,
        stages: ["Unlock another apartment", "Choose a girl on kinkedin", "Put some flowers into the room", "Hire a maid"],
        stages_done: [false, false, false, false],
        stages_type: ["rooms_count", "counter_girls", "apartF", "rooms_staff_assigned"],
        stages_val: [[2, 2], 2, 5, [2, 0]],
        desc: ["Your clients need a place to live in. You can add apartments on the ROOMS screen."],
        done: false,
        done_msg: "Nicely done.",
        xp: 10, money: 0, skillpts: 0, perkpts: 0, achpts: 0     /* rewards */
    },
The system uses flags to keep track of the quest progress. There's a routine that runs through all currently active quests and checks whether a quest stage has been completed. In this example, the first objective is to unlock another apartment. The game checks the 2nd position of the rooms object (the apartment complex) and looks if the number of apartments is greater than / equal 2. Once this is the case, stages_done[0] is true. The entire quest is completed when the number of done stages equals the number of total stages.

You notice the "stattus" element. This is a basic counter for the different statuses of a quest. 0 = not active, 1 = pending (can be activated), 2 = active, 3 = ready to be processed by the <<questdone>> widget, 4 = done, 5 = failed). Don't ask me why it's spelled with two Ts. :D

Please note that this is just one way to do it. Generally, you should always think the structure of player tasks / quests, before you start implementing a system.

5.4. How can I create a rewarding progression system?
As I've mentioned in the "pitfalls" section, one of the biggest problems of HTML games is their grindiness. You repeat mundane things (go to gym etc.) over and over again to raise a stat like "fitness". Once your stat reaches a certain value, an event gets unlocked. While this is totally fine on a basic level, it should never be a core mechanic to just repeat stuff. Repetition is boring if there's no clear goal or immediate reward.

So how do we avoid this? Well, it's complicated. First of all, it depends on the structure of your game. Is it a CYOA type game or is it a game with a cycle? How much freedom does the player have? Is the game linear or open? And so on. Unlocks can be more rewarding if they're linked to player choice and activity. Maybe you could write a little side plot which involves getting into a physical altercation. If the player makes the right decisions, the MC gets some fitness points. You can also think about adding RPG elements (levels, skill / perk points, special abilities) to your game, but beware: These are no magical solution to your problems.

Another way to make progress more rewarding is to add achievements and cosmetic rewards like costumes, hairstyles or clothes.

5.5. What about dialogue trees?
I've spent hours upon hours on creating something like an RPG dialogue tree system. There are many different ways to achieve this goal. Generally, you'll need to think about the following things:

- When do player choices occur?
- Do I want choices to lead to the addition of content on the page or does a page transition happen?
- Are stat / skill checks a part of the game?
- How many different types of player choices are there?
- Should stat changes be calculated automatically?

I've created a custom widget to handle my choice system. Here's how it looks in action:
<<dial "a" "nor" "passage123" "I want to pick this option." "happy" 4>>

Let's run through the thing:
- dial is the name of the widget
- "a" is the denominator of the choice. If there are multiple choices present, the next ones are called "b" and "c" and so on.)
- "nor" is the type of choice. As you might have guessed, "nor" refers to a "normal" choice, i.e. a choice without a skill check.
- "passage123" is the name of the passage that gets included into the dialogue passage after the player clicks on the link
- "I want to pick this option." is what is being displayed as label for the choice.
- "happy" is the stat that's going to be manipulated and 4 is the amount of happiness points the character gets when he picks the choice.

Oof. Now let's look at an example for skill checks:
<<dial "a" "sug" 4 "passage234" "This is a skill check.">>

- "sug" stands for suggestion, which is a character attribute of the MC in my game
- Once you click on the link, a check routine is being performed. I'll spare you the details, as it involves lots of moving pieces like the game's skill system.

Here's an excerpt from the "dial" widget:
Code:
<div class="choose chooseStat">
        <<link _text "Talk">>
            <<set $statType to _args[0]>>
            <<if _checkval gte _args[1]>>
            <<set $notistring += "''CHECK PASSED'' " + _checkval + " >= " + _args[1] + "<br>">>
                <<if _args[4]>><<stat _args[4] _args[5]>><</if>>

                    <<if $weekend_token neq 4>>
                        <<switch _args[0]>>
                            <<case "sug">>
                                <<set $girl[$current].sugC += 1>>
                            <<case "aut">>
                                <<set $girl[$current].autC += 1>>
                            <<case "log">>
                                <<set $girl[$current].logC += 1>>
                            <<case "cun">>
                                <<set $girl[$current].cunC += 1>>
                            <<case "emp">>
                                <<set $girl[$current].empC += 1>>
                        <</switch>>
                    <</if>>

            <<else>>
                <<set $statPassed to false>>
                <<set $notistring += "''CHECK FAILED'' " + _checkval + " < " + _args[1] + "<br>">>
            <</if>>         
                <<set $current_talk to _args[2]>>
        <</link>></div>
I won't explain all the different sub-widgets and variables, but feel free to ask me if you want to know more.

5.7. Event management
Creating an event system is recommended if your game is having an "open" structure. It works similar to the quest system I've explained above. Basically, an event is something that happens if all unlock conditions are met. So maybe a dialogue scene becomes available once your MC has reached 25 fitness points.

Here's an example of randomly occurring event in my game:
Code:
    {
        cls: "random", once: true,
        handle: "centerfold", type: "player",
        desc: "You find an old magazine in your office. It is very inspirational.<br>+ 1 ",
        prereq1: ["player_lvl"],
        prereq2: [1],
        hu: true,
        unlock_type: ["player_skillpts"],
        unlock_val: [1],
        firedOn: -1, cooldown: 2, prob: 10, prs: 0,
        armed: true, active: false, done: false, activeUntil: -1
    },
The class is "random". "once" defines if the event can happen one time or multiple times. "type: player" means that the MC is going to be affected by the event. The prereqs are the conditions that need to be met for the event to fire. "hu" means "has unlock", the following two lines define the event's outcome, in this case the MC gets one skill point. "firedOn" saves the turn number when the event "fired". "cooldown" is the amount of turns it takes for the event to be active once it's armed. "prob" is the probabilty for the event to occur. "prs" is a counter that increases with each met requirement. Finally, there are "armed", "active" and "done". These are the different states an event can be in.

This looks fairly complicated on first glance, but actually, it's really simple. There's the <<checkevent>> widget that gets called in the PassageReady special passage. It runs through the event object and updates it. Once an event is "ready", it happens.

Here are the basic steps for a check routine:
1. Cycle through the event loop.
2. Add switches / ifs to differentiate between different event types. (I recommend switches)
3. Check for triggers / flags.
4. If all conditions are met, fire the event, e.g. make a link visible.
(5. Add "post-fire" handling, e.g. a system that deals with completed events.)

Of course, your system doesn't have to be this extensive. In general, having an event system simplifies keeping track of things. The goal is to reduce micromanagement. You do not want to manage variable changes spread over hundreds of passages. Instead, the code should be structured in a way that allows you to change event properties in one go.

5.8. The navOverride trick
Sometimes you might want to force the player to visit a certain passage. This can be achieved by using Config.navigation.override. You have to define a function in your JavaScript. Here's a simplified and shortened version of my navOverride:

Code:
Config.navigation.override = function (dest) {
    var sv = State.variables;

    /* story overrides */
    if (sv.current_talk == "bella_lex") {
        sv.storyoverride = true;
        sv.storyid = 10001}

    else {
        sv.storyoverride = false;
    }

    if (sv.ap == 0) {
        return "NextWeek";
    }

     if (sv.storyoverride == true) {
         return "Talk";
     } else {
         return false;  // Proceed as normal
     }
This leads us to the point where we've got to mention State.variables. Each story variable is stored like that, e.g. State.variables.day. If you're using JS, you've got to refer to story variables in this manner. Temporary variables are stored like this: State.temporary.f95.

5.9. How do I create an inventory system?
Well, if you want something that's already fully developed, you can take a look at HiEv's UInv system. It's great, but also fairly complex, so you might be overwhelmed when you'e a beginner. Designing an inventory system by yourself is also an option. Here are some general tips on how to do it:

- How many different types of itmes (e.g. food, clothes, potions, etc.) are there going to be?
- Who can use items? (MC, other characters)
- How many different ways to get items are there? (e.g. shops, dialogue, events, etc.)
- Do items have an effect? If yes, will there be calculations?
- Where are items stored? Is there ONE inventory or a system with sub-inventories? (e.g. different rooms, bags, inventories for characters, etc.)
- Can items be consumed or given to other characters?

Let's say you want to design a clothing system. The MC can wear clothes on the following slots: upper body, lower body, underwear (upper), underwear (lower), shoes, accessoire. You can add these slots to the MC object in your StoryInit. Next we need an object containing all the information on the items. An item should have a name, a type (= MC slot), an unlock requirement, a price (if there's a shop) and maybe some predefined effects like stat buffs.

Now all there's left to do is to assign the item to a slot. This can be done by creating a grid or a list of all items the player currently possesses. Items can be equipped (MC slot variable gets changed to item id) by clicking on a link. (You can go for drag&drop if you're better at coding.)

This is a very simple example. RPGs need more complexity. As I've said: HiEv's UInv is a great place to learn about the necessary concepts.

5.10. The Settings API
The built-in settings menu comes with a minimal amount of possible options. Here's an example for a simple toggle. It has to be put into your JavaScript section.
Code:
Setting.addHeader("Visuals");
Setting.addToggle("facilityNav", {
    label : "Facility navigation in right sidebar",
    default : true
});
If you're planning to use media (audio / video), you should think about adding settings for that. Especially a volume slider can be helpful.
Code:
Setting.addRange("masterVolume", {
    label    : "Master volume",
    min      : 0,
    max      : 10,
    step     : 1,
    onChange : function () {
        SimpleAudio.volume(settings.masterVolume / 10);
    }
});
6. External resources
and have some fantastic content on their Githubs. They are also always helpful on the Sugarcube subreddit and heroes in general. (The same goes for TheMadExile and greyelf!)

I definitely recommend the following third party addons / macros:
- CSS macro
- Load/Save handler & FileSaver
- ChapelR's Dialog API (adds some functionality to the existing API)
- Keyboard links
- <<message>> and <<mouseover>>
- Fullscreen macro

One last tip: 99% of all problems can be solved by reading the Sugarcube documentation. It's that good.

Thanks for reading this blurb. Feel free to ask questions and have a nice day.
 
Last edited:

Femboy GH

New Member
Dec 12, 2022
3
2
thx for your work, I was looking for this kind of guide to start creating my own game. Also, do you have a discord server or sth similar, would like to have some place to discuss develop game
 

PTSdev

Member
Oct 21, 2019
101
285
There will be a discord server for my game when it releases.
But there's a server for Twine games:
There are lots of helpful people there.
 

SSWorldMaker

Member
Game Developer
Jul 17, 2018
230
409
I just find this tread, thanks for the time you take to explain how you are using twine with sugarcube.

On 2.4 I would advise you to remove all <<silently>> mention, because it was demoted on sugarcube quite some times ago. And the tag nobr can be forget.
Use this on Javascipt in your twine project.
Config.passages.nobr = true;
It's way more simple to remove all automatic <br> to avoid all empty line space for every line of code or hidden condition you have in your passage.

I have not the same approach of you for my game with some part you explain, but it's still interesting.
 

PTSdev

Member
Oct 21, 2019
101
285
Thanks for the reply. This guide is referring to 2.36.1, so <<silently>> is still valid as of now, but it's good to know that it's gonna be deprecated soon.
As for nobr: I know about the config setting, personally, I mostly use the "nobr" passage tag, but that's mostly out of habit.

The guide in general very much reflects my personal approach, it's mostly there to share some ideas.
 

SSWorldMaker

Member
Game Developer
Jul 17, 2018
230
409
Yeah it's interesting to see how other people handle the same things differently in the same engine.

Besides I overuse widget that for sure :p , and I didn't know that we could use the temporary variable on arguments _args in widget, I have try to replace all $args in my game by _args , but there is no perf change at all.
 

PTSdev

Member
Oct 21, 2019
101
285
$args was deprecated in 2.36.0, you should not use it anymore - unless you're on an older version of SC and don't plan to upgrade.
 
  • Thinking Face
Reactions: SSWorldMaker

SSWorldMaker

Member
Game Developer
Jul 17, 2018
230
409
I'm already on Sugarcube 2.36.1. :LOL: for some times. But thanks for telling me, it's hard to stay up to date.
 
Last edited: