A while back, I somehow managed to copy the contents of one file and overwrite a different file, meaning the entire section of the map was lost for good. I had to reconstruct it from snippets of prose written in separate documents. It sucked. And that motivated me to try something that would stop that problem from ever happening- hosting my project on GitHub!
Git sounds really fancy and hard to understand, but it's really not! So I'm going to walk you through how to use it to back up your files and do much, much more.
This tutorial expects you to have an already set up Tweego folder and VSCode. If you don't know how to get that started, @manonamora-if has an excellent ready-to-use folder with an explanation of how to use it.
What is Git?
In short, git is a kind of version control. Say you're working on a coding project with somebody else, and you need to work on the same file they were working on. But how do you know you're working on the right version of that file? Maybe they forgot to send you the newest version. Or maybe you both have to make changes at the same time. It would take a lot of effort to manually splice together everybody's changes, let alone identify what each of you had changed. That's what git's job is. Git identifies what has changed about a file, notes those changes, and updates the "main" files to match. That way, everything stays consistent, and big files can be updated easily.
Okay, but what benefit does git provide to you, somebody who's just working on a solo project with very little code? Well for one, it would have completely fixed my problem. Instead of overwriting all of my work, git would have shown me that the file had been changed. Then, I could simply click a button to revert the change. Neat! It also means you can keep working on the same project from multiple locations without losing progress. Say you're working on your game on your home computer, but then you want to keep working on your school laptop. All you'd have to do is "push" your changes to save them to your master file, and then "pull" the changes when you get to school. Neat
The Basics of Git
Okay, but what does "push" and "pull" mean? Git's confusing, but the basic terms you'll be encountering don't have to be! Here's some terminology:
Git - This is the program that goes on your computer to manage your files. It does all of the version control.
GitHub/GitLab/BitBucket - These provide servers you can host your git repositories on.
Repositories - This is a fancy word for a folder that's being maintained by git. Every file in a repository is getting analyzed by git for changes.
Local vs Remote - Your local repository is the one hosted on your computer, and it's the one you're editing. The remote one is the one hosted on a site like GitHub.
Stage - When you stage a file, you're getting it ready to commit it.
Commit - A commit is like saving your progress as a new update. You can go back to a commit later if you messed something up.
Push - When you "push" your commits, git will look at your changes, go into the remote repository, and individually change all of those things in the "main" branch.
Pull - Just like pushing, when you pull, you're taking changes from the remote repository and updating your local one to match it.
Under the cut, I'll show you full step-by-step (with photos!) of how to set up your game with GitHub using VSCode!
Setting Up Git With VSCode
Lucky for you, VSCode has built in integration with GitHub, which means you don't have to download any new programs other than git itself. You'll just have to set it up. A note- I'm not sure at what point exactly in this process VSCode prompts you to install git, because I'm not going to install it on another computer just for this tutorial haha. VSCode will provide the installation, just go along with the default settings and you'll be fine.
So first, make a Github account. It's free!
Now, open VSCode. Here's our project! You're going to want to click on that third button down in the side menu, the Source Control tab.
Under source control, you'll see this option. Click it.
Aaaaand it's done! That was easy, right? Now your folder is a git repository. Crazy!
Before you can put all of this up in GitHub, you'll need to push all of your files. Type a brief message (try "Initializing" to feel like a real cool coder), press commit, and VSCode will ask if you want to skip staging and just commit everything. Yes! Yes you do!
Now that all of your "changes" have been committed, let's publish your new repository to GitHub. Click on the new button that says "publish branch." When the popup appears, click "Allow" to give VSCode access to your GitHub account and sign in. Back in VSCode, you'll see this:
You're probably going to want it to be private, otherwise anyone on the internet could see all of your writing! Which is cool if it's a public coding project that people might want to download and use for their own projects, but if you're not a fan of code diving, leave it private.
Using Git To Help You Write
Now that you've got your folder set up as a git repository, it'll change the way VSCode looks. VSCode is using git's info to know where you've made changes, and it'll represent those changes in the UI. Here's what those look like:
If you click on those lines, you'll get to see this fancy new panel that highlights all of your changes:
So let's say we have a scene, and we aren't happy with how it's looking, but we aren't sure if we want to make one change or a different change. Instead of backing up all of your stuff or copy and pasting it to test it, you can just make whatever change you want and click that backwards facing arrow to revert it back if you aren't happy with it. You can do the same for things like CSS- when you've made some good progress and want to save your changes, commit them. Then any more changes you make will be easy to revert back if they don't look right. Groovy!
Now that everything's set up, it's as easy as committing your changes when you're satisfied with them and pushing those commits to back up your work.
Pat yourself on the back! You just learned (the very basics of) how to use git! You absolute genius!
If you have any questions while following this tutorial, feel free to ask! My askbox is always open!
As I spent an unspecified time trying to figure it out, maybe it will spare someone the trouble or build towards intuition for how stats work. Or maybe this is bait to see if anyone knows a better solution 😏
First of all, flat stats vs fairmath stats. Fairmath stat accumulation is designed to represent stat gain as inversely relative: the higher your stat value, the smaller your absolute gain would be expressed by the same relative number. E.g. 10% gain at 90 is different from 10% at 15. A bonus (and very important) effect of this is that the stat value increased or decreased via fairmath will never fall below 0 or rise above 100, doing all the stat clamping for you.
Fairmath is easy to test and observe in ChoiceScript, where you can run thousands of tests automatically. You cannot do that in Twine. This is my primary motivation for going with flatmath for my SugarCube project. Which means that someone has to handle clamping, as a gain of 10 at stat value 95 will set the value above 100.
The frequent code for handling that is during change:
<<set $stat to Math.clamp($stat + 5, 0, 100)>>
which, in this example, increases variable $stat by 5 and makes sure the result is not smaller than 0 and not greater than 100: clamping.
My problem with it is how much code repetition is there and how incredibly copy paste error prone this is. You will no doubt be copy pasting this code all over your game files and will need to make sure you are replacing the variable name twice each time, lest one variable will end up with the value of another in an oversight that is way too easy to miss. Ideally we want to specify not only the name of the variable, but also our bounds (0 and 100 respectively) only once.
There are two answers to this problem: widgets and JavaScript. A widget for this is one and done, but it is more fuss to integrate it into code, I found. In the JS solution you would need to figure out a function that works for your variable storage schema.
Not only will the above check that each resulting value is within the [0; 100] range, it accepts the variable name as a parameter, meaning it will work for any stat (though you would need to pass the variable name as a String) and for subtraction too:
<<modify "$stat" -18>>
Now to problems. For my links between passages in the format for Twine I use, SugarCube, I strongly prefer the structure of setters:
[[Link text|NextPassageName][stat modifications]]
Calling a widget is not possible inside a setter link though. You would either need to do that in the next passage, which is inconvenient if you do not need that passage for anything else, or to marry two syntaxes in this unholy matrimony:
Now, for the price of extra JS code you can avoid all this. Depending on how you store your game variables, flat or in objects, you can employ tricks to save you time and code lines.
[[Link text|NextPassageName][modifyStat("StatA", -18), $otherstat to "wowza"]]
As you can see, this is suitable for flat stat storage (which I personally do not do). I suppose for the nested stats you could specify the object names as inputs in their order of hierarchy and access them so for a generic function, but I am not sure yet how to do that for a variable number of levels, e.g. Parent.StatGroup.statA vs Parent.statB
I believe this is geared to the very specific way I personally structure my passages and links, so I am ready to be proven wrong 😅
Heyyy! I have a twine sugarcube coding question and I have no eloquent way of asking it so here it is: I want the user to be able to click on a word and a description pops out from underneath and then I want them to be able to re-click that same word and the description is hidden again. sos pls do you know how :) is what im asking even a thing
Hey Veirse!
That's totes possible. And there different ways of going at it (depending on what you want to do with your page, and how far you want the description to appear).
As always, the code below can be found on my PasteBin account.
How To Toggle a Description!
Chapel's Message Macro
The MVP of SugarCube custom macros has something to help: the << message >> macro. It allows you to toggle a part of text by clicking on a link. Click once, it appears. Another time and it disappear. It's pretty much the << linkappend >> macro, but you can hide the text again.
You just need to add the Macro code to the JavaScript, and use the macro as such:
<<message "Clickable Text">>
Description Text/Message to appear
<</message>>
Note: by adding btn after the "Clickable Text", the links become a button instead.
This method is nice if you want the text to appear just below the link. If you want a working example, check the Drawers section in Scene 1 of CRWL.
CyCy's Liveupdate Fix
Technically, not specific to your case, but still works. I've used it for the toggable menu of Exquisite Cadaver (which uses the Simple Book Template). This method is similar to Chapel's macro, but the toggled text doesn't have to be just below the link.
You can find CyCy's Liveupdate Custom Macro here, just need to add that to your JavaScript. Then it is just a matter of creating a link and some conditions:
<<link "Clickable Text">>
<<if not $trigger>>
<<set $trigger to true>>
<<else>>
<<set $trigger to false>>
<</if>>
<<update>>
<</link>>
<<liveblock>>
<<if $trigger>>Description Text/Hidden Message<</if>>
<</liveblock>>
Note: if you have multiple << liveblock >> on the page, the << update >> macro will trigger them all.
Maliface's On/Trigger Macro
Works like Cycy's but you can target one block rather than all of them. You can find the JavaScript code here, and the manual there. And it goes something like this:
<<link "Clickable Text">>
<<if not $trigger>>
<<set $trigger to true>>
<<else>>
<<set $trigger to false>>
<</if>>
<<trigger 'blockname'>>
<</link>>
<<on 'blockname'>>
<<if $trigger>> Description Text/Hidden Message<</if>>
<</on>>
Note: Chapel's Event Macro uses the same macro name. These two macros cannot be used together, unless the name of one of them is modified in the JavaScritpt (Macroadd line)
Span, Link and Replace
And finally, if you want to go OG Sugarcube Code, here's the thing: using the << replace >> macro. It's essentially Maliface's On/Trigger Macro, but with the Base SugarCube Macros.
I have used this option in TTATEH (asking questions) and La Petite Mort (doing actions).
You will need: a span (div works too) with a defined ID/Class, a link, a conditional statement and the replace macro.
<<link "Clickable Text">>
<<if not $trigger>>
<<set $trigger to true>>
<<replace "#target" t8n>>Description Text/Hidden Message<</replace>>
<<else>>
<<set $trigger to false>>
<<replace "#target" t8n>><</replace>>
<</if>>
<</link>>
<span id="target"></span>
Notes: the t8n adds a transition effect to make the new block appear. If you want to target a class instead of an idea, change the # into a . and the id into class.
Overall Notes: for all options, aside from Chapel's, you can use a temporary variable (_var) instead of a permanent one ($var).
Creating a system to manage character relationships is one of the most popular game mechanics in interactive fiction games. While not every game needs a relationship system, it may be a good idea to implement one if the player character’s relationships with others are an important dynamic in your game.
This is an informal tutorial written for Twine and SugarCube. While the coding aspects will only work in SugarCube, the principles should be applicable to other story formats or IF engines. Even if you don’t work in Twine/SugarCube, this may still be helpful if you’re struggling with relationship stats!
This tutorial assumes you already have an understanding of setting stats in SugarCube (see here for a quick overview) and also the TwineScript and JavaScript conditional operators (see here in the documentation). TwineScript and JS conditional operators achieve the exact same thing, so I tend to use them interchangeably depending on what is faster/more comfortable for me.
What Is An Approval System?
An approval system is the mechanic that tracks how one character feels about another. This is typically the player character (PC) and the main NPCs. Most of the time these NPCs are romance options (ROs), but they could also be friends or party members. The higher the approval, the closer the PC and NPC become.
Choosing which characters will have an approval system and which ones do not is important. Unless you’re making a very small game (i.e. six or seven characters max, with no other characters involved in the story), not every character needs to have their approval tracked. These should be the characters whose relationship to the PC directly impacts the narrative and opens up different paths, routes, and outcomes.
How you build your approval system will depend on the scope and style of your game. A romance game where the PC follows the story route of their desired love interest will have different needs than an action/adventure game where the PC’s best friends can turn on them.
Before you design your approval system, there’s a few things you’ll want to think about:
Which characters will be affected by the approval system? How many? Keep in mind that every character who has a relationship/approval stat will need their own relationship/approval variable.
Do you want the approval system be linear? The approval system only ever moves forwards, with the player taking certain actions/dialogue options to gain approval points with an NPC, and they can never lose that progress.
Do you want the approval system to be bi-directional? The approval system can progress and regress. The player can take certain actions/dialogue to gain approval points with an NPC, but they can also take other actions/dialogue to lose points.
What is the impact your approval system will have on the game’s narrative? What types of things do you want it to lock or unlock? How will it shape the player’s experience?
What does your approval system measure? Friendship? Romance and friendship? Friendship and rivalry? Depending on your game’s needs, you may want to have more than one approval system to track different relationship names (for example, a separate system for friendship and one for romance, one for friendship and one for rivalry). You’ll want to think very carefully about using multiple relationship systems. If all of your desired outcomes can be controlled through one approval bar, then you probably don’t need more than one. However, if you want to do something like having a romance between a PC and an NPC who hate each other, you may want to split romance and friendship into two separate functions.
Linear Approval Systems
Linear approval systems measure the PC/NPC relationship in sequential order. The player can only ever gain approval points with an NPC. One gained, points cannot be lost. Usually with linear systems, the player needs to select the right dialogue and action options in order to progress the relationship, but they are not punished for selecting the wrong ones. Once the player achieves the right amount of points with the desired NPC, a special romance or friendship scene will unlock or they will attain some kind of additional content or flavour text.
When creating a linear system, you will want to decide how numerical values (the approval points) define the PC/NPC relationship. Here’s an example of a combined friendship/romance system, using units of 10:
0 – 9 – the characters have just met each other. They’re getting to know each other, but they’re not friends yet.
10 – 19 – The characters are warming up to each other. They are more friends than acquaintances and they are starting to flirt with each other.
20 – 29 – The characters know each other quite well. They are openly flirtatious; maybe they have started dating.
30 – 39 – The characters care a lot about each other. They have officially become a couple.
40 – 50+ – The characters know everything about each other. They are deeply in love and trust each other completely.
Here, the ranges are the same for every approval “level”, but they don’t have to be. Some levels could require fewer amounts of points (i.e. the “getting to know each other” range could be accomplished in 5 points, and the “caring a lot about each other” range could take 20 points). It could also change depending on the character, with some NPCs being more open to the player character right away and others taking more time to warm up to them.
How large your ranges are will depend on how many opportunities you plan to give the player to raise their approval level. If you only intend to provide a handful of opportunities to raise approval, then you won’t need ranges quite as large as this one.
Consider the scale of your game and what the long-term progression of the PC/NPC is; that will help you determine how many approval points you are working with. You should always know where the end point is.
Bi-Directional Approval Systems
Bi-directional approval systems are more difficult to implement than linear ones, but they are much more flexible. If you intend your PC and NPCs relationships to have any kind of rivalry, for them to fall in and out of love, or for them to end up hating each other over the course of your game, a bi-directional approval system may be better. This system creates a scale. The player can gain and lose approval over the course of the game, and depending on their actions, the PC/NPC relationship will either increase or decrease.
For this kind of system, you will want to think about your minimum point and maximum point for your scale (i.e. where does it start and where does it finish?). While you can set 0 as the neutral point and work with positive and negative numbers (anything above 0 being in the “like” range, anything below 0 being in the “dislike” range), this can be difficult to indicate visually later on if you want to use a meter or a progress bar.
I like to use 0 and 100 as my min and max points for sake of ease, but you can really set it to whatever you want.
Similarly to the linear approval system, you will want to define the numerical ranges that your PC/NPC relationship falls into. Here, it’s important to know where the where the mid point is—what value indicates the neutral ground between like and dislike.
It could look something like this:
0 - 19 — Extreme dislike
20 - 39 — Dislike
40 - 59 — Neutral feelings
60 - 79 — Friendly
80 - 100 — Loving/close friends
Here, I’ve divided the approval stat (0-100) into 5 approval ranges that increase in units of 20 points. 50 is the center—it is the mid point of the approval bar and the mid point of the neutral range.
Just like the linear system, how big your ranges are will depend on how many opportunities you plan to give the player to increase/decrease their approval stat.
Why Work in Ranges?
Having ranges in your approval system allows for more flexibility and control over the approval stat. It increases the amount of opportunities the player will have to change the course of their relationships, which makes for a more satisfying roleplaying experience.
For example, here’s a ten point approval system:
1 – We hate each other
2 – I can’t stand you
3 – I dislike you
4 – You bother me
5 – Neutral
6 – You’re okay
7 – I like you
8 – We’re good friends
9 – We’re close friends
10 – We unconditionally love each other
If gaining nine approval points is all it takes to go from “we hate each other” to “we unconditionally love each other”, then it only takes the player nine interactions for that growth to happen. The pacing of the relationship is going to feel off. When there’s less room for growth, growth between these extremes will happen very rapidly.
Working in ranges let’s the PC sit in different stages of the relationship for a longer amount of time. Because it takes more points (and therefore more time), any relationship progress or regression will feel more natural. At the same time, you don’t want the ranges to be too big, otherwise it will feel like no progress is happening. This will, of course, depend on how many points you are adding/subtracting with each approval gain and loss.
Adding/Subtracting Approval and Using Conditional Statements to Control Flavour Text, Dialogue, Choices & NPC Behaviour
Once you have your system established and you know your ranges, approval stats work very similarity to any other stat. You can use conditional statements that check the numerical value of the approval stat to show different flavour text, dialogue, choices and options.
I’m going to use the bi-directional system as an example here, with a range of 0-100.
Let’s say we have a character named Eliza and her approval is stored in a variable called $eliza_approval. Because she has just met the PC, let’s set her approval to 50, so she is in the exact centre of the neutral approval range.
<<set $eliza_approval to 50>>
If the player selects an option that coincides with something she approves of, you can add approval to her approval stat with:
<<set $eliza_approval +=1>>
(This adds +1 to her approval stat.)
<<set $eliza_approval -=1>>
(This subtracts -1 from her approval stat.)
You can accomplish the same thing inside a link, using SugarCube’s link markup:
[[1. Nice choice.|Next Named Passage][$eliza_approval +=1]]
[[2. Mean choice.|Next Named Passage][$eliza_approval -=1]]
In the text of your game, you can control what options and flavour text the player sees depending on Eliza’s approval stat by using conditional statements.
<<if $eliza_approval >=80>> Shows text/options for a loving/close friends relationship.
<<elseif $eliza_approval >=60 && $eliza_approval <=79>> Shows text/options for a friendly relationship.
<<elseif $eliza_approval >=40 && $eliza_approval <=59>> Shows text/options for a neutral relationship.
<<elseif $eliza_approval >=20 && $eliza_approval <=39>> Shows text/options for a relationship where they dislike each other.
<<elseif $eliza_approval >=0 && $eliza_approval <=19>> Shows text/options for a relationship where they hate each other.<</if>>
You could also close the statement with an <<else>> instead of the last <<elseif>>.
Depending on the context of the scene and options, you may not need flavour text or choices for all of your available ranges. Often when working with a bi-directional system, you may only need to have two options (one for low approval, one for high approval). What counts as “low” and what counts as “high” may change depending on where you are in the game, the current tensions, and what’s at stake.
To divide your ranges into low approval and high approval, you could do something like this:
<<if $eliza_approval >=60>> Shows the high approval option.
<<else>>Shows the low approval option.<</if>>
Here, high approval counts as anything that is 60 or over (the “friendly” range and above).
Later on, I may run into a situation where I want “high” approval to count anything in the neutral range. So I may change the code to this:
<<if $eliza_approval >=40>> Shows the high approval option.
<<else>>Shows the low approval option.<</if>>
How much differing flavour text and options will depend on the context of each individual moment in your game. Sometimes you will want to have more restrictions and more flavour text; other times, you’ll want to simplify.
A basic rule of thumb is that if the flavour text for a neutral relationship and a friendly relationship in a given scenario is basically the same, then you probably don’t need to separate them out (for that scenario). Even if you have your relationship stats divided into five ranges, you don’t always need to come up with text and options for all five.
Clamping Approval
I think the most important part of creating a relationship system that feels organic is pacing and offering a broad selection of player choice. One of the challenges with approval systems is crafting a system that allows the player to feel like they’re roleplaying their character. Sometimes, the choices that gain approval are out-of-character for the player and they won’t want to select them, even if they want to form a relationship with that NPC.
This can be frustrating for the player in games that have romance. Systems that don’t have enough varied opportunities for the player to gain approval can significantly hinder roleplaying and cause players to take out-of-character actions to get the RO they want.
However, developers may not want to offer a lot of opportunities for approval gain because players could max out (or deplete) their relationship stats too early. To circumvent this, I highly recommend clamping your approval.
Clamping keeps your relationship stats between a min/max range and prevents it from exceeding the limit. SugarCube can clamp numerical variables with a function called Math.clamp.
If we take Eliza’s approval variable from earlier and clamp it, it will look something like this:
<<set $eliza_approval to Math.clamp($eliza_approval + 5, 0, 100)>>
<<set $eliza_approval to Math.clamp($eliza_approval - 5, 0, 100)>>
The first code adds +5 to $eliza_approval, the second subtracts -5. Both clamp it between the range of 0 and 100.
This means that if $eliza_approval was at 98 and the game added +5 to it, it would max out at 100. And if $eliza_approval was at 3 and the game subtracted -5, it would only decrease to 0.
To clamp inside SugarCube’s link markup, you can do it like this:
[[1. Nice choice.|Next Passage][$eliza_approval to Math.clamp($eliza_approval + 5, 0, 100)]]
[[2. Mean choice.|Next Passage][$eliza_approval to Math.clamp($eliza_approval - 5, 0, 100)]]
You can use clamping to manipulate approval gains and loses at different stages of your game.
For example, in Wayfarer, the player has the opportunity to set the approval level of a major character with whom they have a pre-established relationship. If the player sets Aeran’s approval level to 80, then the game treats them as very close friends.
Because there are multiple opportunities to raise that approval level throughout Chapter 1, Aeran’s approval is clamped between 5 (as the minimum) and 90 (as the maximum) as I did not want players to fully deplete or max out his approval bar in the first chapter of a 14-chapter game.
It doesn’t matter if the player hits all of the possible approval gains available in the chapter, Aeran’s approval will always stop at 90 in Chapter 1.
Clamping approval gains and loses at different points in the game can be helpful for allowing more opportunities to affect approval. Instead of preventing players from maxing out their stats too soon by offering fewer choices, you can offer more choices and let the engine do the work for you to keep the player’s relationships within the desired range.
How Many Points to Add?
How many approval points you add or subtract will depend on your system’s range and your game’s needs. Approval gain/loss can always be static (+1 or -1), or it could depend on the action taken.
If the PC does something an NPC really likes, it could garner more approval points – +5, +10, or even enough to put them into the next range. Likewise, if the PC does something the NPC despises, it could net greater loses.
If the PC does something the NPC believes is unforgiveable, sometimes an approval loss is not enough because the PC could gain those relationship points back. You may want to add an additional check to control the NPC’s behaviour in regards to the Unforgiveable Event that supersedes the approval, or block the PC off from gaining approval with the NPC all together.
In SugarCube, this bit of code could look like this:
<<if $UnforgiveableEvent is true>>Unique flavour text that shows that Eliza is upset with the PC
<<elseif $eliza_approval <= 39>>Unique flavour text for a generic low approval interaction with Eliza
<<else>>Flavour text that isn’t covered by the above two situations (so, in this case, unique flavour text for a generic medium/high approval interaction with Eliza).<</if>>
Relationship Bars
If relationships are a crucial element of your game, you may want the player to access that information so they can track where their approval level is at.
There are multiple ways to do this, so it all depends on the design of your game and how much time you want to spend on it.
You can use conditional statements show relationship status through words, with no visuals. Something like this:
Eliza <<if $eliza_approval >=80>><b>loves</b> you.
<<elseif $eliza_approval >=60 && $eliza_approval <=79>>is a <b>close friend</b>.
<<elseif $eliza_approval >=40 && $eliza_approval <=59>>is <b>indifferent</b> towards you.
You could also create an approval bar that visually indicates approval level. I prefer using the progress element for this (explained here), but you could also use Chapel’s Meter Macro to accomplish the same thing.
Th progress element and meters cannot show negative values, which is why I recommended having 0 as your lowest value on any given relationship stat.
You could do a combination of the two, or even use image assets (controlled by conditional statements) to indicate approval. Visually indicated approval level can be as complicated or as simple as you want it to be.
Using Multiple Relationship Stats
Depending on the complexity of your relationship system, you may end up splitting your approval systems into multiple parts. For example, you could have separate variables for:
Friendship
Romance
Rivalry
This would allow you to have greater control over a wider arrange of combinations. A relationship that is high friendship and low romance would be different from a relationship that is high friendship and high romance. A relationship that is low friendship, high romance and high rivalry would again be different from a relationship that is low friendship, but high romance and high rivalry.
All of this can be controlled with effective use of conditional statements. For example, if you were working with separate friendship and romance systems, you would need to set two stats: one for friendship and one for romance.
Conditional statements would then look something like this:
<<if $eliza_approval >=40 and $eliza_romance >=80>>Options for a neutral or friendly Eliza who is romanced.
<<elseif $eliza_approval <=39 and $eliza_romance >=80>>Options for a hostile Eliza who still has feelings for the PC.
<<elseif $eliza_approval >=40 and $eliza_romance <=79>>Options for a neutral or friendly Eliza who is not romancing the PC.
<<elseif $eliza_approval <=39 and $eliza_romance <=79>>Options for a hostile Eliza who is not romancing the PC.
<<else>>Options for if none of the above is true.<</if>>
The more in-depth you make your system, the more complex it will be to maintain and the more variations you will have to manage. You will want to be careful about adding too many of these. Think about what your game needs and how you can make it effective; if something can be managed with fewer systems, then it probably should be.
hi vahnya! i'm trying twine (sugarcube) for the first time and my tiny brain refuses to understand how codes work :'( could you please share with us how to do a character creation passage that includes name, gender, pronouns, appearance, etc? how do we make twine remember this? sending much love to you and your big brain <3
Hi there! ✨ Absolutely, I'll do my best to explain. I'm not sure of you meant that you wanted one single passage to set all of the character creations, or if you meant spread out over several passages as most games do, but it doesn't really matter. You can definitely have the entire character creator on one single page.
Also, thank you for calling my brain big, I think it spurred on the creation of a new brain cell, so now I have 3 lmao!! 🙏🏻
✨ Twine Variables/Character Creation - a tutorial ✨
So, Twine has two types of variables, a temporary variable and a story variable. Temporary variables are declared with an _, and can only be used within one single passage to store information, so if you attempt to use a temporary variable in another passage, Twine will no longer remember the information you put in it.
So you'll mostly be using the story variables in Twine, which are declared using the $, as Twine carries the information in those throughout the entire story. And for characteristics for MC, you'll obviously want to use those as well.
There are several ways of setting variables in Twine using various Macros, so I'll try to cover some of the most regular ones. You can use any of these ways to set variables for anything.
Name:
So for setting names, most games have a list of suggestions, as well as the option to type in your own name, like this:
For suggestions, you only need to have a regular link that sets a variable, which can be done either by using the [[]] link syntax or the <<link>><</link>> macro, like I have done here:
So for the first four names above, I've used the [[]] syntax to set the $firstname variable:
In the first part of the syntax, I write what I want to display in my link, which in the first example is the name Emma, then after the | I have the name of the passage that I want the link to take the player to next, which most logically would be the passage to set the last name (just an example, of course). Then I tell the syntax which variable to set whenever the player clicks on Emma, which is $firstname, as well as what information to store in that variable, which is Emma. So we're basically telling Twine to set $firstname to "Emma", so that whenever we write $firstname in our story, it will show up as Emma after this.
-
For the next four names, I've done the exact same as above, just by using the <<link>><</link>> syntax. These two are legitimately the same, but sometimes it's better to use one over the other for coding purposes.
in <<link>> between the first two "" I've again put the name I want the link to display for the user, then in the next "" I've put the next passage, but this time we have to use the <<set>> macro between the <<link>> and the <</link>> to set the variable. So we're doing exactly the same thing as above, telling Twine to set $firstname to "Tobias" if the user clicks Tobias.
Sidenote: Whether you use the = sign to set variables or the word to, doesn't matter. It's all preference, they do the exact same thing. Also the * that I have in front of the links is simply to make the name suggestions an unordered list with list items, for styling purposes.
-
Now for the player to type in their own name, you will use the <<textbox>> macro and do basically the same as above:
Inside the first "" we'll tell Twine which variable we want to set, which is $firstname, then in the next "" we tell Twine what value the textbox should hold by default. You can use this to tell the player what the textbox is for, ie. "Type your own name here", or you can put a name suggestion in there if you want. Then in the last "" we're telling Twine which passage to take the player to next, as soon as the enter button is hit. You don't have to include this if you'd rather the user had to navigate to the passage some other way, like a button.
When the player goes to the next passage, Twine will fetch the value inside the textbox and save it inside the $firstname variable.
Other ways to set variables
Generally, you can the [[]] syntax or the <<link>><</link>> macro to set any variables, whether it be name, gender, pronouns or appearance, like I have used it here to set the $gender variable:
I basically just use one of those for setting most variable, and I think most games do too, but I'll still cover some other ways of setting variables to show you how they work..
Radiobutton / <<radiobutton>>
Let's say we want to use Radio Buttons to set $gender like we did above. This will will look like this in Twine:
This result is achieved by this code:
Again, in between the first "" we're telling Twine which variable to set, which is $gender, then which information we want that variable to store, depending on which radio button is selected, then you have the option to tell Twine if you want a button to be autocheck-ed, which means that Twine will automatically check which value $gender currently holds and check that option, but in our case $gender has no value, so none is checked. The other option is to set one radio button to checked by default.
So, if the player checks of the Woman option, whenever they click through to the next passage, the $gender variable will set to "Woman".
Listbox / <<listbox>>
Let's say we're setting $haircolour by using Listbox. How it will look in game + code:
Inside of <<listbox>>'s first "" we're telling Twine which variable to set, in this case it's $hairColour.
Then we have a selection of <<options>> where the first "" will be the text that is displayed to the player, and the second "" is the value that the variable will actually hold. So in the first example, the player will see Blonde hair in the selection menu, and when selected, $hairColour will be set to "blonde".
Cycle link / <<cycle>>
This one is quite popular to use in Twine, it's the link that will function like this:
And is achieved by this code:
We use the <<cycle>> macro, and inside <<cycle>>'s "" we'll tell Twine which variable we want to set, in this case it will be $eyeColour, then between <<cycle>> and <</cycle>> we will once again use the <<option>> macro to set the selection of options the player can chose from, like we did above with the <<listbox>>
Protip:
If you wanted to set more than one variable with one single link, there's a simple way to do so. Let's use pronouns as an example, since you specifically asked for that. How it looks in game + code:
So above, we're doing the exact same thing as we did in the first example at the top of this post using the [[]] link or the <<link>><</link>> to set variables with a link, except we're setting several variables at the same time simply by separating them with a ;
So in the first example, if She/Her is clicked, we're setting $they to "she", $them to "her", $their to "her", etc. — all within the same link.
-
I think that covers the most basic and most popular ways of setting variables in Twine. I've linked all the macros as well, if you want to read more about them.
I really hope this was understandable and helpful! Feel free to ask if something was unclear or you need help with anything ✨🤎
Yeah, it's the middle of the week but it's been too long since I did an update on this blog, so I'm doing one now. (I'm gonna start doing shorter updates every weekend starting with the new year.)
I want to start off by mentioning that I'm working on a Twine tutorial template
I ended up making a (sugarcube) Twine tutorial template for a friend a couple weeks ago. Since then I've been turning that template into a detailed tutorial on coding and Twine that will be released very soon. Hopefully, it'll be useful to people who are in the process of switching from cog to Twine, who've decided that they want to make an IF game as their New Year's resolution, or anyone else who may be interested. I may even produce a few video tutorials to accompany it if I have the time. But until it comes out, if you have any questions or requests for specific things you'd like to see in the template, please let me know! ☺️
As a note, I'll be trying to show a variety of writing/coding styles in addition to my own and, as a general rule, would never judge or look down on someone for not doing things like me.
Okay, onto Hades' Kitchen...
With Hades' Kitchen, the first episode is fully planned and I'm about halfway through writing what will be the first demo release. I'm currently polishing up this first half and will be sending it out to beta testers soon. I'm currently aiming for a realistic and comfortably vague spring 2022 release.
Hades' Guide has a small update coming tomorrow that will include:
In-depth profiles for the olympian and chthonic deities
New MyShade profiles for Alex and Julio as well as updated profiles for the ROs
Better navigation mechanics that should make moving through the app faster and easier
Some minor bug fixes, grammar and spelling corrections, and accessibility improvements
There's also gonna be a larger Hades' Guide update coming within the next few weeks that will include:
Full lists of mortal and monstrous beings with explanations of each
The story of Hades and Persephone
More information about Underworld society, politics, and urban legends
A map of Neo Olympus with more info on the cities/regions MC can be from
Miscellaneous entries on background lore like the Trojan War, ripper surgeons + cybernetic enhancements, ECHO, prophets, wanted criminals, CirceTV + The Odyssey, and more...
Inevitable bug fixes and corrections from the smaller update
Other HK stuff I've been doing:
Making artbreeder portraits for the characters
Drawing actual portraits for the characters (but who knows if I'll ever have the guts to share them)
Playing with/improving the game's UI
Updating all the existing posts on this blog with accurate info and better tags
Getting the other short stories ready for release
Drafting lore posts and individual character profiles for Tumblr
Working on the last few asks I've yet to answer (mainly just cause they're longer)
Writing a little "which character are you"-type quiz
Coordinating with the giveaway winners
My other projects are truly on the backburner right now. My attention is solely on getting the demo for HK completed and finishing up this tutorial. (But I'm debating revealing the name of the secret IF soon, idk, let me know if you're interested in that or learning about my other projects).
That's all for now! I hope you've all managed to survive the holiday season and truly wish you the very best for this upcoming year. Thank you so much for your support, it truly means the world to me. 💜
It is a tale as old as time. The app crashes, your cache is cleared, your laptop breaks, and hours or days or weeks of work is lost. It's a terrible experience, and you never think about what to do in that situation until it happens to you- and by that time, it's already too late. So here's your prompt to get ahead of things and keep your project protected before something goes wrong.
So here, I'll be going over some layers of security you can use...
1. NEVER use the web app
I know this one's gonna be controversial. I know, a lot of people use the web app! It exists for a reason! But if you do, you're leaving your work very vulnerable.
When you use a local installation of Twine, your files are being saved to local storage. That means that everything is saved on your hardware, and with the exception of a freak event, it's not going anywhere. Don't get me wrong, those freak events aren't rare enough to dismiss (we'll talk about that later), but it's not quite as bad as the web app.
Instead of saving your files locally, the web app saves your progress to your browser's cache- the same thing that saves your cookies and keeps you logged in on websites. If your cache is cleared for any reason, your games will be gone.
2. Write your documents in a separate program
Chances are, if you're using Twine, there's a lot of stuff you can do outside of Twine before moving it into the program itself. A common practice is to write prose in a separate program, and then move it all into Twine when you're finished and write the code in Twine. This is a great way to back up your work, because if Twine has an error, you'll still have all the source files to reconstruct what you had before.
I'd recommend trying to use a stable program to write in. That means something that saves locally and doesn't frequently crash. In other words, do not use Google Docs. Instead of Docs, try one of these:
Microsoft Word (expensive, subscription, but stable)
LibreOffice (free, stable)
Scrivener (one time purchase, stable)
3. Back EVERYTHING up
I can not stress this enough. Back up your damn work. Back it up in multiple places if possible.
"Oh, but I'm using Google Docs, it's already backed up!" NO. No it is not. To keep your work truly safe, you need multiple copies hosted on multiple pieces of hardware. If one of those is a Google server, great! But if it's just one, that means that one single failure in that hardware (or the software associated) will mean everything is lost.
You can back up your files from the Twine program by going under the Build tab and selecting Publish to File or Export as Twee. Saving that to your device is already better than having it saved by the Twine app, but you'll be even safer if you back that file up to an external hard drive (or just a cheap USB drive) and a cloud hosting service like Dropbox or Google Drive. To make it extra safe and minimize lost progress, make sure you replace these files regularly.
That seems like a lot of work though, right? Yeah. So here's my final piece of advice...
4. Use Git
Git is how I've been backing up my latest project, Signal Hill. It's intimidating at first, but there are simple and easy ways to use platforms like Github to keep your work safe and fix big errors. To teach you how, I've created a whole separate tutorial, which you can find here.