<h1>Index</h1>
<h3>The Basics</h3>\
* ''[[About Twine and SugarCube|About]]''
* ''[[Starting with SugarCube|Basics]]''
** [[The Elements on the Page|Basics-UI]]
** [[Linking Passages|Macro-Link-Basic]]
** [[Tracking Information|Macro-Set-Basic]]
** [[Display Variation|Macro-If-Basic]]
** [[The Basics of Variables|Variables-Base]]
** [[Basic Demo|Demo-Basic]]
<h3> The Basics+</h3>\
* ''[[SugarCube Markup and Basic Styling|Markup]]''
** [[Showing the Value of a Variable|Markup-Variable]]
** [[Using a Variable inside a Link|Markup-Link]]
** [[Display an Image, and as a Link|Markup-Image]]
** [[Removing a Line-break|Markup-Nobr]]
** [[Basic Text Styling|Markup-Styling]] (long)
* ''[[Going Further with the Basics|Macro-Basic]]''
** [[Displaying more than text in Links|Macro-Link]]
** [[Setting and Changing Variables|Macro-Set]]
** [[Unsetting Variables|Macro-Unset]]
** [[More Conditional Statements|Macro-If]]
** [[Display Variables, the Print Macro and Variants|Macro-Print]]
* ''[[Adding some Interactivity|Macro-Interact]]''
** [[Multi or Single Option Choices|Macro-CheckRadio]]
** [[Cycles and Conditional Options|Macro-Cycle]]
** [[Revealing Extra Text and Disappearing Links|Macro-Link-AppPreRep]]
** [[Listboxes and Conditional Options|Macro-Listbox]]
** [[Player Input in three macros|Macro-Input]]
* ''[[Basic Special Passages|Special-Passage]]''
** [[Headers and Footers|SP-HeaderFooter]]
** [[Special Passages for the UI Bar|SP-UIBar]]
** [[Setting Important Variables before Start|SP-Init]]
** [[Special Passage Demo|SP-Demo]]
* ''[[About JavaScript and the StyleSheet|Base-JS-CSS]]''
* ''[[ULRs for Assets and Testing|URL-Types]]''
<h3>Intermediate Use</h3>\
* ''[[More Interactivity Macros|Macro-Interact-Adv]]''
** [[DOM Macros and Revealing Text in Targeted Spots|Macro-ApPreRepCopy]]
** [[Single-Use Choice Lists|Macro-Action-Choice]]
** [[Delaying Displaying Text or Running Code|Macro-Timed]]
** [[Displaying Text Letter by Letter|Macro-Type]]
** [[Using Custom Macro|Custom-Macro]]
* ''[[Macros of Convenience|Macro-Conv]]''
** [[An Alternative to Conditional Statements|Macro-Switch]]
** [[Removing Blank Space and Hiding Code|Macro-Nobr-Silent]]
** [[Including a Passage inside another|Macro-Include]]
** [[Creating and Using a Widget|Macro-Widget]]
** [[Going Back or Returning to a Passage with a Special Link|Macro-Back-Return]]
** [[Sending the Player to a Passage|Macro-Goto]]
** [[Using JavaScript in the Passage|Macro-Script-Run]]
* ''[[More Special Passages and Tags|Special-Tags]]''
** [[Special Tags creating Special Passages and Functionalities|Tags-Built]]
** [[Process Code Before and After Rendering a Passage|SP-PassageReady-Done]]
** [[Changing the UI of the Project|SP-StoryInterface]]
** [[Customising Passages with Tags|Tags-CSS]]
* ''[[Harness the Power of Functions|Functions]]''
** [[Cloning Variables, and Random Values Functions|Function-Clone-Random]]
** [[Using Play, Passage, and Tags information|Function-Pass-Tag]]
** [[Memorizing Information and Metadata|Function-Metadata]]
** [[JavaScript-only Functions|Function-JS]]
* ''[[Using Methods to change Variables|Methods]] ''
** [[Methods and String Variables|Method-String]]
** [[Methods and Numbers|Method-Number]]
** [[Methods and Arrays|Method-Array]]
* ''[[Adding Sound with the Audio Macros|Macro-Audio]]''
** [[Setting up the Audio Tracks|CacheAudio]]
** [[Create Track Groups and Playlists|Macro-Group-Playlist]]
** [[Playing Tracks in a Passage|Audio-Macro]]
** ''[[Other Audio Macros|Audio-Other]]''
* ''[[Going further in Styling with CSS and JavaScript|Int-JS-CSS]]''
** [[The Different Targetable Elements|Int-JS-CSS-Elements]]
** [[Ensuring that Elements Start at the Top when Opened|Int-JS-CSS-Events]]
** [[Import and Change the Font|Int-JS-CSS-Font]]
** [[Using the Root and CSS var|Int-JS-CSS-Root]]
** [[Formating for Different Screen Size|Int-JS-CSS-Media]]
** [[Intro to Animation|Int-JS-CSS-Animation]]
** [[Creating a Stat Bar|Int-JS-CSS-Stat]]
* ''[[Some Useful Basic APIs|Basic-API]]''
** [[Moving back and forth in the History|Basic-API-Engine]]
** [[Create a PopUp|Basic-API-Dialog]]
** [[Handle the SideBar|Basic-API-UIBar]]
** [[Open the JumpTo, Restart, Saves, and Settings PopUp|Basic-API-UI]]
** [[Overriding the Navigation to a Passage|Basic-Config-Navig]]
** [[Some Useful Configuration API for your Project|Basic-API-Config]]
* ''[[Edit the Built-In Text or Change the Game's Language|Localization]]''
** [[l10nStrings, and How to Edit Them|Local-L10n]]
** [[Localization, and Pre-Translated Templates|Local-Trans]]
** [[Providing Multiple Languages In-Game|Local-Setting]]
<h3>''Advanced Mode''</h3>\
> Note: This Section will be completeted at a later date.
* ''[[Advanced Macros|Macro-Adv]]''
** [[DOM Macros and Changing Class of an Element|Macro-DOM-Adv]]
** [[Loops and Repeats - Two Ways|Macro-For-Repeat]]
** [[Capturing the Value of a Variable|Macro-Capture]]
** [[Emulating PassageDone for one Passage|Macro-Done]]
* ''[[The Settings API|Settings]]''
** [[Adding Headers|SettingsHeader]]
** [[Creating a Toggle Setting|SettingsToggle]]
** [[Creating a List Setting|SettingsList]]
** [[Creating a Slider|SettingsRange]]
** [[Going Further with Settings|Settings-More]]
* ''[[Going further with the Engine API|Engine-API]]''
** [[Checking the State of the Game|Engine-State]]
** [[Move through the Player's History|Engine-Go]]
** [[(Re-)Play a Passage|Engine-Play]]
** [[Restarting without the Built-In PopUp|Engine-Restart]]
* ''[[Trigger Code with Special Events|Events]]''
** [[Dialog Events|Events-Dialog]]
** [[Passage and Navigation Events|Events-Passage]]
** [[System Events|Events-System]]
** [[Type Macro Events|Events-Type]]
# [[Some Random Stuff That will be Organised Later|Organise]]
## [[Make the Cycle Macro Accessible|Accessibility-Cycle]]
## [[Arbitrarily Long Returns|Long-Return-JS]]
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>Macro List</h1>
Below you will find the alphabetical list of SugarCube macro, and where they are discussed in this guide.
{{{<<actions>>}}}: [[1|Macro-Action-Choice]]
{{{<<addclass>>}}}: [[1|Macro-DOM-Adv]]
{{{<<append>>}}}: [[1|Macro-ApPreRepCopy]]
{{{<<audio>>}}}: [[1|Audio-Macro]]
{{{<<back>>}}}: [[1|Macro-Back-Return]]
{{{<<break>>}}}: [[1|Macro-For-Repeat]]
{{{<<button>>}}}: See {{{<<link>>}}}
{{{<<cacheaudio>>}}}: [[1|CacheAudio]]
{{{<<capture>>}}}: [[1|Macro-Capture]]
{{{<<checkbox>>}}}: [[1|Macro-CheckRadio]]
{{{<<choice>>}}}: [[1|Macro-Action-Choice]]
{{{<<continue>>}}}: [[1|Macro-For-Repeat]]
{{{<<copy>>}}}: [[1|Macro-ApPreRepCopy]]
{{{<<createaudiogroup>>}}}: [[1|Macro-Group-Playlist]]
{{{<<createplaylist>>}}}: [[1|Macro-Group-Playlist]]
{{{<<cycle>>}}}: [[1|Macro-Cycle]]
{{{<<done>>}}}: [[1|Macro-Done]]
{{{<<for>>}}}: [[1|Macro-For-Repeat]]
{{{<<if>>}}}: [[1|Macro-If-Basic]], [[2|Macro-If]]
{{{<<include>>}}}: [[1|Macro-Include]]
{{{<<goto>>}}}: [[1|Macro-Goto]]
{{{<<link>>}}}: [[1|Macro-Link-Basic]], [[2|Macro-Link]]
{{{<<linkappend>>}}}: [[1|Macro-Link-AppPreRep]]
{{{<<linkprepend>>}}}: [[1|Macro-Link-AppPreRep]]
{{{<<linkreplace>>}}}: [[1|Macro-Link-AppPreRep]]
{{{<<listbox>>}}}: [[1|Macro-Listbox]]
{{{<<masteraudio>>}}}: [[1|Audio-Other]]
{{{<<nobr>>}}}: [[1|Macro-Nobr-Silent]]
{{{<<numberbox>>}}}: [[1|Macro-Input]]
{{{<<playlist>>}}}: [[1|Audio-Macro]]
{{{<<prepend>>}}}: [[1|Macro-ApPreRepCopy]]
{{{<<print>>}}} / {{{<<=>>}}} / {{{<<->>}}}: [[1|Macro-Print]]
{{{<<radiobutton>>}}}: [[1|Macro-CheckRadio]]
{{{<<remove>>}}}: [[1|Macro-ApPreRepCopy]]
{{{<<removeaudiogroup>>}}}: [[1|Audio-Other]]
{{{<<removeclass>>}}}: [[1|Macro-DOM-Adv]]
{{{<<removeplaylist>>}}}: [[1|Audio-Other]]
{{{<<repeat>>}}}: [[1|Macro-For-Repeat]]
{{{<<replace>>}}}: [[1|Macro-ApPreRepCopy]]
{{{<<return>>}}}: [[1|Macro-Back-Return]]
{{{<<run>>}}}: [[1|Macro-Unset]], [[2|Macro-Script-Run]]
{{{<<script>>}}}: [[1|Macro-Script-Run]]
{{{<<set>>}}}: [[1|Macro-Set-Basic]], [[2|Macro-Set]]
{{{<<silently>>}}}: [[1|Macro-Nobr-Silent]]
{{{<<stop>>}}}: [[1|Macro-For-Repeat]]
{{{<<switch>>}}}: [[1|Macro-Switch]]
{{{<<textarea>>}}}: [[1|Macro-Input]]
{{{<<textbox>>}}}: [[1|Macro-Input]]
{{{<<timed>>}}}: [[1|Macro-Timed]]
{{{<<toggleclass>>}}}: [[1|Macro-DOM-Adv]]
{{{<<type>>}}}: [[1|Macro-Type]]
{{{<<unset>>}}}: [[1|Macro-Unset]]
{{{<<waitforaudio>>}}}: [[1|CacheAudio]]
{{{<<widget>>}}}: [[1|Macro-Widget]]<h1>Some Random Stuff That will be Organised Later</h1>
Here are some SugarCube relevant bits, which I haven't found a good place to put right now.
The links below won't change but may be located in a different Sub Menu at a later date. See [[Update Log]] for more information.
* [[Make the Cycle Macro Accessible|Accessibility-Cycle]]
* [[Arbitrarily Long Returns|Long-Return-JS]]
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>Make the Cycle Macro Accessible</h1>
While it can be a fun way to have Interactivity in your project, the {{{<<cycle>>}}} [[macro|Macro-Cycle]] has some issues with accessiblity (screen readers). This can be remedied with the code below, created by [[HiEv|https://www.reddit.com/r/twinegames/comments/qo1p1j/cycling_links_and_accessibility/]] to include in your JavaScript.
{{{
$(document).on(":passagerender", function (event) {
var clinks = $(event.content).find(".macro-cycle");
if (clinks.length) {
clinks.attr("aria-label", function (event) {
return "(click to change) " + $(this).text();
});
clinks.on("click", function (evnt) {
$(this).find("p").contents().unwrap(); // Fix SugarCube bug with <<cycle>>+Config.cleanupWikifierOutput
$(this).attr("aria-label", "(click to change) " + $(this).text());
});
}
});
}}}
> Note: if you are not using the {{{Config.cleanupWikifierOutput}}} [[API|Basic-API-Config]] in your project, the Fix Bug code line can be removed.
<div id="link-menu">[[Back to Menu|Organise]] - [[Back to the Start Menu|Start]]</div><h1>Arbitrarily Long Returns</h1>
While the {{{<<return>>}}} macro or {{{previous()}}} function can be useful in sending the player back to the Story when visiting a Codex or Inventory page, it can also create inescapable loops, making it impossible for the player to go back to the Story.
This can be solved in different ways:
* Using the {{{<<back>>}}} macro as is or the {{{Engine.backwards()}}} API,
** If multiple non-Story passages are clicked, the player will have to click each //Back// link.
* Creating Popups to display those non-Story passages,
** This will avoid navigating between passages.
* Using the JavaScript code below.
<h3>How to Code the Arbitrarily Long Return</h3>
The //Arbitrarily Long Return// will record the last Story passage the player visited and store it in a variable, which can then be used inside a link, to send the player back to the Story. We will call here the variable {{{$return}}}.
The code also requires something to differenciate Story and non-Story passages: a tag. We will calle it here {{{noreturn}}}.
When all your non-Story passages are tagged correctly, add this code in your JavaScript passage:
{{{
$(document).on(':passagestart', function (ev) {
if (!ev.passage.tags.includes('noreturn')) {
State.variables.return = ev.passage.title;
}
});
}}}
> Note: you may change the name of the variable or the tag, if you prefer another name for either.
> Note 2: if you want to use multiple tags instead of one, change {{{!ev.passage.tags.includes('one-tag')}}} into {{{!ev.passage.tags.includesAny('one-tag two-tags')}}}.
When this is set, you can add your links in the non-Story passages to send the player back to the Story:
* {{{[[Return|$return]]}}}
* <<link "Return" $return>><</link>>
* {{{<<return $return>>}}} / {{{<<return [[Return|$return]]>>}}}
* {{{<<back $return>>}}} / {{{<<back [[Return|$return]]>>}}}
> Note: since Twine automatically creates a new passage when using the {{{[[link]]}}} Markup, you will need to delete the new passage (here {{{$passage}}}) after coding the macros. Otherwise, the player will be sent to a blank page instead of the wanted passage. Or you can use the {{{<<link>>}}} macro instead.
<h3>A Note on Navigating to a Previous Passage</h3>
Navigating back to a previously visited passage can be problematic, especially when code could run into issues when re-executing the content of the passage. Code may have some side-effect, like changing the value of a variable, or printing a different text on the page (ex: using the [[-visited() functions|Function-Pass-Tag]] to display variation).
This can be avoided if you:
* ensure the passages contain no code with side effect,
* wrap the code in something to prevent re-execution,
** ex: {{{<if visited() is 1>>only show on the first view<</if>>}}}
* use the code above with {{{<<back>>}}} macro to send the player back to the passage, erasing the record of visiting the non-Story passages,
** ex: {{{<<back $return>>}}} / {{{<<back [[Return|$return]]>>}}}
* move the non-Story passages into a PopUp with the Dialog API.
<div id="link-menu">[[Back to Menu|Organise]] - [[Back to the Start Menu|Start]]</div>Dialog API
Dialog.append()
Dialog.body()
Dialog.isOpen()
UIBar API
UIBar.isHidden()
UIBar.isStowed()
UIBar.update()
UI API
UI.alert()
UI.share()Config API
Config.macros.maxLoopIterations
Config.macros.typeSkipKey
Config.macros.typeVisitedPassages
Config.audio.pauseOnFadeToZero
Config.audio.preloadMetadata
Passages Settings
Config.passages.descriptions
Config.passages.displayTitles
Config.passages.onProcess
Config.passages.start
Config.passages.transitionOut
Saves Settings
Config.saves.autoload
Config.saves.autosave
Config.saves.id
Config.saves.isAllowed
Config.saves.tryDiskOnMobile
Config.saves.version
UI Settings
Config.ui.stowBarInitially
Config.ui.updateStoryElements
Miscellaneous Settings
Config.addVisitedLinkClass
Config.debug
Config.loadDelay<h1>Going further in Styling with CSS and JavaScript</h1>
* [[The Different Targetable Elements|Int-JS-CSS-Elements]]
* [[Ensuring that Elements Start at the Top when Opened|Int-JS-CSS-Events]]
* [[Import and Change the Font|Int-JS-CSS-Font]]
* [[Using the Root and CSS var|Int-JS-CSS-Root]]
* [[Formating for Different Screen Size|Int-JS-CSS-Media]]
* [[Intro to Animation|Int-JS-CSS-Animation]] [ ★ NEW ★ ]
/* [[Creating a Stat Bar|Int-JS-CSS-Stat]] [ ★ NEW ★ ]*/
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>Formating for Different Screen Size</h1>
While the Base SugarCube UI is fitted for different screen sizes, from laptop to mobile, changing the size of elements on the page in the StyleSheet or the structure of the page in {{{StoryInterface}}} will require a fitting in smaller/larger screen sizes.
This can be done with the {{{@media}}} rule.
{{{
@media screen and (size) {
[element] {
/* CSS Rule */
}
}
}}}
With this, you can target certain range of screen size or ratio, and apply different CSS rules to elements than the base. For example:
{{{
#passages {
width: 50vw;
}
@media screen and (max-size: 585px) {
#passages {
width: 100%;
}
}
}}}
In a screen wider than 585px, the width of the passage will be half of the page. However, if the screen is 585px or less, the width of the passage will take the whole screen.
<div id="link-menu">[[Back to the Styling Menu|Int-JS-CSS]] - [[Back to the Start Menu|Start]]</div><h1>Ensuring that Elements Start at the Top when Opened</h1>
When going from one long passage to another, or opening a multiple popups whose content does not fit the container, the system might not automatically scroll the element to the top of the page/element. Especially if the UI has been modified.
However, this can be easily fixed with a bit of jQuery in the JavaScript passage, and [[Events]]:
{{{
$(document).on(":passagedisplay", function() {
$("#passages").scrollTop(0);
});
For the Dialog Box:
$(document).on(":dialogopened", function() {
$("#ui-dialog-body").scrollTop(0);
});
}}}
> Note: you can change {{{#passages}}} with any other relevant container, like {{{#story}}}.
<div id="link-menu">[[Back to the Styling Menu|Int-JS-CSS]] - [[Back to the Start Menu|Start]]</div><h1>Using the Root and CSS var</h1>
As the UI gets more complex, whether because of its base customisation, or with because of the addition of [[Settings]], some organisation of cetain values, like colours or fonts, may help. This can be done through the creation of CSS variables ({{{--var}}}) inside the {{{:root}}} selector.
> Note: this is used quite often in templates, to make changing colours of the UI easier for the user. Instead of finding all the different iterations of a value, there is only one to change!
In your StyleSheet, after any imported element:
{{{
:root {
/* the listed variable */
}
:root {
--sansserif: 'Montserrat', sans-serif;
--font-colour: #000;
--dm-font-colour: #eee;
--width: 50px;
--timer: 3s;
}
}}}
> Note: new versions of root can be included inside the {{{@media}}} selector if a certain variable need to change in different screen size.
The CSS variable can then be used as many times as needed in relevant CSS rules in other elements:
{{{
.passage {
color: var(--font-colour);
}
.dm #ui-dialog-body {
color: var(--dm-font-colour);
}
.sansserif .passage {
font-family: var(--sansserif);
}
}}}
<div id="link-menu">[[Back to the Styling Menu|Int-JS-CSS]] - [[Back to the Start Menu|Start]]</div><h1>Import and Change the Font</h1>
As with [[images|URL-Types]], how to import fonts will depend on the location of the font in the first place. This can be done either as a local import or an import from a third-party server (e.g. Google),
> IMPORTANT: the import of a font should be the first thing in your StyleSheet, before any other CSS rules!
\
<h3>The Different Imports</h3>\
For a server import, the {{{@import url()}}} should be used. You only need to add the relevant URL of the font. For example, Google will provide one just as the one below.
> Note: when selecting multiple fonts (type or families), Google will provide one link for all selected fonts.
{{{@import url('https://fonts.googleapis.com/css2?family=Georgia:wght@400;700&display=swap');}}}
Depending on the servives used, the URL for the font may look differently. For comparison, here's the one of an old FontAwesome version:
{{{@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.0/css/all.min.css’);}}}
On the other hand, local import will use the {{{@font-face}}}, with a relative URL, and require a few more informtation. This will include the name of the font-family, the URL, the format of the file, the style (normal/italic) and the weight (400-normal/700-bold).
For example, trying to import an OpenDyslexic font (normal, italics, bold, bold+italic):
{{{
@font-face {
font-family: "Dyslexic";
src: url(fonts/OpenDyslexic-Regular.otf) format("opentype");
font-style: normal;
font-weight: 400;
}
@font-face {
font-family: "Dyslexic";
src: url(fonts/OpenDyslexic-Italic.otf) format("opentype");
font-style: italic;
font-weight: 400;
}
@font-face {
font-family: "Dyslexic";
src: url(fonts/OpenDyslexic-BoldItalic.otf) format("opentype");
font-style: italic;
font-weight: 700;
}
@font-face {
font-family: "Dyslexic";
src: url(fonts/OpenDyslexic-Bold.otf) format("opentype");
font-style: normal;
font-weight: 700;
}
}}}
> Note: a new {{{@font-face}}} is required for each new font type.
\
<h3>Changing the Font of the project</h3>\
In the Base UI, the font is defined in the {{{html}}} element. If the new font should apply to the whole project, you can simply do:
{{{
html {
font-family: 'Font-Name', kind;
}
→ For the OpenDyslexic, as saved above:
html {
font-family: 'Dyslexic', sans-serif;
}
}}}
If the font is supposed to apply to a specific element, you only need to change the targetted element from the example above. For example, wanting to change the font of the header:
{{{
h1 {
font-family: 'Roboto', sans-serif;
}
→ to target the title of the popup:
#ui-dialog-title {
font-family: 'Bacasime Antique', serif;
}
}}}
\
<h3>Let the Player Change the Font*</h3>\
*from a preset list of fonts.
To accomodate players, you can let them change the reading font through a [[List Setting|SettingsList]], within which you have indicated a list of imported fonts (serif, sans-serif, monospace) to choose from.
Assuming that a font //Georgia//, //Montserrat// and //OpenDyslexic// have been imported, the code below could be added to the JavaScript:
{{{
var settingFontFamily = ["Georgia", "Montserrat", "OpenDyslexic"];
var fontFamily = function() {
var $html = $("html");
$html.removeClass("sansserif serif opendyslexic");
switch (settings.fontFamily) {
case "Georgia":
$html.addClass("serif");
break;
case "Montserrat":
$html.addClass("sansserif");
break;
case "OpenDyslexic":
$html.addClass("opendyslexic");
break;
}
};
Setting.addList("fontFamily", {
label : "Change font style.",
list : settingFontFamily,
default : "Georgia",
onInit : fontFamily,
onChange : fontFamily
});
}}}
You can find a Font setting in my [[Setting Template|https://manonamora.itch.io/twine-sugarcube-templates]].
And in the CSS:
{{{
.sansserif body {font-family: var(–sansserif);}
.opendyslexic body {font-family: var(–opendyslexic);}
.serif body {font-family: var(–serif);}
}}}
> Note: this will affect all elements on the page. Change the {{{body}}} to another element.
<div id="link-menu">[[Back to the Styling Menu|Int-JS-CSS]] - [[Back to the Start Menu|Start]]</div><h1>The Different Targetable Elements</h1>
From its [[base UI|http://www.motoslave.net/sugarcube/2/docs/#html]], SugarCube creates multiple elements on the page, which can be targetted in the StyleSheet with CSS or with some JavaScript.
The different elements have also relationships with other elements, depending on where they are located, and how the Built-In CSS coded them.
> Note: when an element is located inside another, the first is called a child of the second, while the second is the parent of the first. CSS rules in the parent element may affect the child element.
\
<h3>Main Block Elements</h3>\
<table>
<tr>
<th>Selector</th><th>Description</th><th>Relationship</th>
</tr>
<tr>
<td>{{{html}}}</td><td>The document element, necessary to set up the HTML page. Should not be included in {{{StoryInterface}}}.
If a story-passage is tagged, the {{{data-tags}}} will be added to this element.
The element sets the font size for the whole document.</td>
<td>{{{html}}} is the parent element to all elements below, but most closely to {{{body}}}</td>
</tr>
<tr>
<td>{{{body}}}</td><td>The body of the page. Should not be included in {{{StoryInterface}}}.
If a story-passage is tagged, the {{{data-tags}}} and special classes will be added to this element.
The element sets the default background and font colours.</td>
<td>{{{body}}} is the child element of {{{html}}}, and the parent element of all the elements below, most closely {{{#ui-dialog}}}, {{{#ui-bar}}}, and {{{#story}}}.</td>
</tr>
<tr>
<td>{{{#ui-dialog}}}</td><td>The popup element container. Should not be included in {{{StoryInterface}}}.</td>
<td>{{{#ui-dialog}}} is the child element of {{{body}}}, and the parent element of {{{#ui-dialog-titlebar}}} and {{{#ui-dialog-body}}}. </td>
</tr>
<tr>
<td>{{{#ui-bar}}}</td><td>The left sidebar. Can be included in {{{StoryInterface}}}, if want to be kept.
This element will affect how {{{#story}}} is positionned on the page.</td>
<td>{{{#ui-bar}}} is a child element of {{{body}}}, and the parent element of the Special Passage elements, among others.</td>
</tr>
<tr>
<td>{{{#story}}}</td><td>Container for the {{{#passages}}} element.
This element's width and position is affected by {{{#ui-bar}}}'s position on the page.</td>
<td>{{{#story}}} is the child element of {{{body}}}, and the parent of {{{#passages}}}</td>
</tr>
<tr>
<td>{{{#passages}}}</td><td>Container for the passage element. HAS TO BE included in {{{StoryInterface}}}.
All created passages will appear as a children of this element, in {{{.passage}}}.</td>
<td>{{{#passages}}} is the child element of {{{#story}}}, and the parent element of {{{.passage}}}</td>
</tr>
<tr>
<td>{{{.passage}}}</td><td>The passage element. Should not really be included in {{{StoryInterface}}}.
The active story-passage will determine the ID of this element.
If a story-passage is tagged, the {{{data-tags}}} and special classes will be added to this element.</td>
<td>{{{.passage}}} is the child element of {{{#passages}}}, and the parent element of any element coded in the story-passage.</td>
</tr>
</table>
> Note: When using the base UI, {{{StoryInterface}}} is not a necessary passage to have in your project.
\
<h3>Notes on the Links Elements and Special Link Classes</h3>\
Targetting the links with the element {{{a}}} or the buttons with {{{button}}} with the without a parent element, the CSS rules will affect every link and button in the project, from the passage, the sidebar, and the dialog box. On the other hand targetting {{{.passage a}}} or {{{.passage button}}} will only select the links or buttons in the passage element.
The {{{a}}} element will affect any interactive macro using a link, such as {{{<<link>>}}}, {{{<<linkappend>>}}}, {{{<<linkprepend>>}}}, {{{<<linkreplace>>}}}, and the {{{<<cycle>>}}} macros, as well as the {{{[[link]]}}} markup. Targetting a certain macro can be done as follow: {{{a.macro-[name]}}} or {{{.macro-[name]}}}.
> Note: targetting the macro class will not affect the [[link]] markup.
To differenciate internal and external links, aside from the icon at the end of the link, a specific class is added to every link(-related) element: {{{.link-internal}}} or {{{.link-external}}}. Only the links going to another website will get the second class, all others will get the first.
> Note: the macros listed in the paragraph above will have the {{{.link-internal}}} class.
To change how a link looks when hovered/in focus/being clicked on, compared to the link when not in use, you can add a special selector to the link: {{{:hover}}}, {{{:focus}}}, and {{{:active}}}. If all these three states will look the same, {{{a:hover, a:focus { /* CSS rules */ }}}} will be sufficient.
If the {{{a}}} has not been modified in the StyleSheet, you may notice some links going nowhere will be formatted differently than working links. This is because those "broken" links have a special class: {{{.link-broken}}}.
When using the macro {{{<<choice>>}}}, links will become disabled, and get the class {{{.link-disabled}}} attached to them.
> Note: this should not be mistaken for the {{{.disabled}}} class added by the {{{<<disable>>}}} [[Custom Macro from Chapel|https://github.com/ChapelR/custom-macros-for-sugarcube-2/blob/master/docs/disable-macro.md]].
If the project should display to the player whether a passage has been visited through the link, you can target the {{{.link-visited}}} class.
> Note: the class is not enabled by default, but should be unlocked with {{{Config.addVisitedLinkClass = true;}}} in the JavaScript.
<div id="link-menu">[[Back to the Styling Menu|Int-JS-CSS]] - [[Back to the Start Menu|Start]]</div><h1>Intro to Animation</h1>
To elevate your project and customize it further, you can decide to animate elements on your game's page (text, images, other...). The animations can be as simple as a flicker to more complex movement over the page. It might seem daunting to create animations, as code out there can look quite complicated. However, animations rests only on three essential elements in the StyleSheet:
* the {{{@keyframes}}}: defining the trajectory of the animation (e.g. change of position, or colour, or opacity, etc...)
* the {{{animation}}} CSS rule: linking and setting the animation to the relevant block (e.g. length, looping, delay, etc...)
* the element targetted: which can be an HTML markup ({{{h1}}}, {{{span}}}), a class ({{{.class}}}), or an ID ({{{#id}}})
> Note: certain animations may require the element to have {{{display: block}}}, {{{display: inline-block}}}, {{{display: absolute}}} to work.
\
<h3>{{{@keyframes}}}</h3>\
Every keyframe are set up in the same way:
{{{
@keyframes animation-name {
keyframes-selector {css-styles;}
}
}}}
As such, you will need to fill the following:
* {{{animation-name}}}: or the name you will give to the animation. For example, let's take {{{flicker}}}.
* {{{keyframes-selector}}}: the percentage in the animation sequence where something changes for the element.
** can be set with percentages ({{{0-100%}}}), or with {{{from}}}/{{{to}}} (same as 0% and 100%), or a combination of both.
*** Here, let's have the flicker happen half-way through the animation (50%).
* {{{css-styles}}}: or the css rules to indicate what changes at that step. Here, the flickering will need {{{opacity}}}.
If we combine it all, we get the following example:
{{{
@keyframes flicker {
0% { opacity:1; }
50% { opacity:0; }
100% { opacity:1; }
}
}}}
> Note: Testing and tweaking is ''very important'' here.
\
<h3>The {{{animation}}} Rule</h3>\
Linking the animation to an element is necessary for the animation to display on the page. The {{{animation}}} CSS rule is a compiled version of 8 different separate rules ({{{animation-[insertname]}}}):
{{{
animation: name duration timing-function delay iteration-count direction fill-mode play-state;
}}}
The minimal required however, is the following:
{{{
animation: name duration iteration-count;
}}}
Thus, you will need to define:
* {{{name}}} (or {{{animation-name}}}): the name of the keyframe animation. Here, we defined it as {{{flicker}}}.
* {{{duration}}} (or {{{animation-duration}}}): the duration of the whole animation. Let's make it {{{1 second}}} here.
* {{{iteration-count}}} (or {{{animation-iteration-count}}}): how many times the animation goes. Let's make it {{{infinite}}}.
{{{
animation: flicker 1s infinite;
}}}
If you want to go further, you can also defined the following aspects:
* {{{timing-function}}} (or {{{animation-timing-function}}}): indicates the curve of the animation speed (slow start, slow end, etc...)
* {{{delay}}} (or {{{animation-delay}}}): delaying the start of an animation.
* {{{direction}}} (or {{{animation-direction}}}): whether an animation should be played forward, backward, or alternating.
* {{{fill-mode}}} (or {{{animation-fill-mode}}}): define whether an animation takes the styling in the start of the animation or the one at the end.
* {{{play-state}}} (or {{{animation-play-state}}}): define whether the animation is playing or paused.
\
<h3>Linking to an element</h3>\
Finally we need to add the {{{animation}}} rule in an element, to make it flicker.
Let's have some text as an example:
{{{
<span class="flickering">Some Text</span>
}}}
In the StyleSheet, you'd need to add the flicker animation to the span defined above with the {{{flickering}}} class:
{{{
.flickering {
animation: flicker 1s infinite;
}
}}}
Giving the following result:
<span class="flickering">Some Text</span>
\
<h3>A note on Accessibility</h3>\
While animations can be quite fun to have, giving some spice to the displayed elements, some players may not find it comfortable. Fast moving elements, flickering animation, or bright flashes, may causes sensory issues to some. It is generally a good idea to warn player of such animation before they start the game, as well as create an [[Accessible Setting|SettingsToggle]], so player can toggle on/off the animation.
<div id="link-menu">[[Back to the Styling Menu|Int-JS-CSS]] - [[Back to the Start Menu|Start]]</div><h1>Creating a Stat Bar</h1>
Multiple ways of doing this:
* HTML progress bar
* Build your down from DIVs
* custom macro
<div id="link-menu">[[Back to the Styling Menu|Int-JS-CSS]] - [[Back to the Start Menu|Start]]</div><h1>Key Binding</h1>
Key Binding is a process of linking a key on a key board to a piece of code. For example, pressing 'S' here will open the Save dialog box.
There are, as of making this guide, three custom macro or code allowing for some sort of Key Binding: HiEv's Keyboard Link Navigation, Chapel's Event Macro, and Maliface's custom Link/Button macro. The first two are included in the code of this guide.
* [[HiEv's Keyboard Link Navigation|HiEvKB]]
* [[Chapel's Event Macro|ChapelKB]]
* [[Maliface's Custom Links|MalifaceKB]]
> Note: If you are mixing and matching those macros, please make sure a single key is triggered by more than one macro.<h1>HiEv's Keyboard Link Navigation</h1>
HiEv's JavaScript [[Code|https://qjzhvmqlzvoo5lqnrvuhmg.on.drv.tw/UInv/Sample_Code.html#Keyboard%20Link%20Navigation]] will key bing each link within a passage to a number for the player to press. This will only work up to 10 links in a passage.
You can get HiEv's code from his [[website directly|https://qjzhvmqlzvoo5lqnrvuhmg.on.drv.tw/UInv/Sample_Code.html#Keyboard%20Link%20Navigation]] or use my modified version in the JavaScript of this file. The latter has been put to its bare use, but you can always edit it to fit your need. I do recommend some knowledge of JavaScript before doing so.
I have made a setting for this as well:
{{{
Setting.addToggle("linkkeybindnumber", {
label : "<b>Numbered Links</b><br>If enabled, you will see the corresponding number to press for each link on the passage (if there are more than one link).<br>Reload the page to see the changes.",
default : false,
});
}}}
\
> Some notes:
* If there is only one link, the user can use {{{1}}} or {{{→}}} to trigger the link.
* If there are more than one link up to 10, the keys {{{0}}} to {{{9}}} should be used.
* Links will get marked as such: link^^[1]^^, unless there are more than 10 links or the setting is turned off.
* Some browsers, like Opera, will require user to play the game in a separate window. Otherwise, it will select a different tab.
* Keyboard navigation will be ignored if an {{{<input>}}} element has focus (like a textbox).
* The {{{←}}} and {{{→}}} keys can be used to go back and forth in the user's history.
* Tags can be used to disable keyboard navigation: {{{DisableKeyLinks}}} will remove marking and disable number navigation, {{{IgnoreArrowKeys}}} will disable the arrow navigation.
* Addding {{{data-nokeys="true"}}} to a link or its parent will be ignored by the code. For example: {{{<a data-nokeys="true" href="http://google.com">Google</a>}}} or {{{<span data-nokeys="true">[[Main Menu]]</span>}}}.
\
> Customisation Notes:
* I do advise against using {{{Space}}} as key to move the story forward if there is only one link, as it is used by browsers to go down the page.
* If you are looking for the JavaScript code for a key, you can use this [[website|https://www.toptal.com/developers/keycode]].<h1>Chapel's Event Macro</h1>
Chapel's [[Custom Macro|https://github.com/ChapelR/custom-macros-for-sugarcube-2/blob/master/docs/event-macros.md]] will bind keys to a piece of code. This works great to trigger the opening of non-story passage (Journal, Codex...) or Built-In APIs (Setting, Saves, Restart).
You can get Chapel's code from his [[GitHub|https://github.com/ChapelR/custom-macros-for-sugarcube-2/blob/master/docs/event-macros.m]] or use my modified version in the JavaScript of this file. The latter has been edited to not trigger when {{{<input>}}} (textbox) is in focus, but you can always edit further it to fit your need. I do recommend some knowledge of JavaScript before doing so.
While the macro can be used throughout a game, if you intend on using certain set triggers, it is recommended to code the macro in the {{{StoryInit}}} passage.
> Example:
{{{
<<on 'keyup'>>
<<which 83>> /% the S key %/
<<script>>UI.saves();<</script>>
<<which 81>> /*Q for settings */
<<script>>UI.settings();<</script>>
<<which 82>> /* R for Restart*/
<<script>>UI.restart();<</script>>
<</on>>
<<on 'keydown'>> /*Escape*/
<<which 27>><<trigger 'click' '#ui-dialog-close'>>
<</on>>
}}}
> Note: If you are looking for the JavaScript code for a key, you can use this [[website|https://www.toptal.com/developers/keycode]].<h1>Maliface's Custom Links</h1>
Maliface's [[Custom Macro|https://github.com/MalifaciousGames/Mali-s-Macros/blob/main/a-macro/a-macro.md]] has links and buttons that take any HTML attributes, with built-in keybindings support and multiple ouput options. You can find the [[code here|https://github.com/MalifaciousGames/Mali-s-Macros/blob/main/a-macro/a-macro.js]].
While this macro can do a lot, the focus here is on the key binding.
To key bind a link with a key, you need to add {{{key}}} after the displayable text, followed by the key(s). Unlike [[HiEv|HiEvKB]]'s code, you need to do this for each link on your passage but you are not restricted to 10 links per passage.
> Example:
{{{
<<a "Push forward." key 'w,z' goto 'NextPassage'>><</a>>
<<a "Go back." key 's' goto 'PreviousPassage'>><</a>>
}}}
> Note: If you are looking for the JavaScript code for a key, you can use this [[website|https://www.toptal.com/developers/keycode]].[[Font Types|FontsUI]]EXAMPLES WRAPPED IN CSS
[[FontsSizeUI]]
Font
Colour
Element Display<h1>Fonts Types</h1>
Choosing a Font is important to set the ambiance and the theme of your project. A fitting font will enhance what you are trying to convey, while an illegible one will make it hard to translate your message to the reader.
There are multiple categories of fonts:
* Serif: @@font-family:serif;example@@
* Sans-serif: @@font-family:sans-serif;example@@
* Monospace: @@font-family:monospace;example@@
* Cursive: @@font-family:curstive;example@@
* Fantasy: @@font-family:fantast;example@@
\
When considering a font for your project, please note that different people find different fonts comfortable. If you are able, consider including different fonts for your users (serif/sans-serif).
\
> Settting
Here is below the code found in this guide:
{{{
//-- JavaScript Setting
var settingFontFamily = ["Serif", "Sans Serif", "OpenDyslexic"];
var fontFamily = function() {
var $html = $("html");
$html.removeClass("sansserif serif opendyslexic");
switch (settings.fontFamily) {
case "Serif":
$html.addClass("serif");
break;
case "Sans Serif":
$html.addClass("sansserif");
break;
case "OpenDyslexic":
$html.addClass("opendyslexic");
break;
}};
Setting.addList("fontFamily", {
label : "<b>Change font style</b>",
list : settingFontFamily,
default : "Serif",
onInit : fontFamily,
onChange : fontFamily
});
//-- CSS Code
.serif .passage, .serif #ui-dialog-body {font-family: Tinos, serif;}
.sansserif .passage, .sansserif #ui-dialog-body {font-family: Montserrat, sansserif;}
.opendyslexic .passage, .opendyslexic #ui-dialog-body {font-family: Dyslexic, serif;}
}}}
\
> Open Dyslexic
In 2011, Abelardo González released an Open Source font called OpenDyslexic to help mitigate reading errors for users with Dyslexia. The font can be downloaded [[here|http://opendyslexic.org/]] for free.
Or the other one<h1>Fonts Size</h1>
Font sizes are important when it comes to displaying your content. Different screen sizes and resolutions will show your text differently. To accomodate this, a font size setting can be considered.
Note: the base size of a font on SugarCube is 16px.
\
> Setting
{{{
//--Basic Setting with JavaScript Only, the new font size is a percentage of the base one (16px)
var settingFontSize = ["100%", "130%", "150%"];
var resizeFont = function() {
var size = document.getElementById("passages");
switch (settings.fontSize) {
case "100%":
size.style.fontSize = "100%";
break;
case "130%":
size.style.fontSize = "130%";
break;
case "150%":
size.style.fontSize = "150%";
break;
}
};
Setting.addList("fontSize", {
label : "Change font size.",
list : settingFontSize,
default : "100%",
onInit : resizeFont,
onChange : resizeFont
});
}}}
{{{
//--Font Setting with a CSS class setting the new font
var settingFontSizeNames = ["Default", "Medium", "Large"];
var settingFontSizeHandler = function () {
var $html = $("html");
$html.removeClass("fontsize-medium fontsize-large");
switch (settings.fontsize) {
case "Medium":
$html.addClass("fontsize-medium");
break;
case "Large":
$html.addClass("fontsize-large");
break;
}};
Setting.addList("fontsize", {
label : "Change the font size."",
list : settingFontSizeNames,
onInit : settingFontSizeHandler,
onChange : settingFontSizeHandler
});
// and in your CSS
html.fontsize-medium #passages {font-size: 26px;}
html.fontsize-large #passages {font-size: 31px;}
}}}
Note: HiEv has another method, which inclues two buttons in the sidebar to change the font. You can find it [[here|https://qjzhvmqlzvoo5lqnrvuhmg.on.drv.tw/UInv/Sample_Code.html#Font%20Size%20Buttons]].<<widget "SomeWidget">>
Wow Some Text
<</widget>>
<<widget "SimonSays">>
<<set _array to ["Raise your hands!", "Jump!", "Dance!"]>>
<<print _array.random()>>
<</widget>>
<<widget "SimonSpecialSay">>
<<if _args[0]>>
<<print _args[0]>>
<<else>>
<<SimonSays>>
<</if>>
<</widget>>
<<widget "SimonDoes" container>>
<div class="simon">
<hr class="before-simon">
<p class="simon-does">_contents</p>
</div>
<</widget>><<if tags().includes("sp-demo")>>SG SUPER GUIDE YO@!<<else>>100% Good Twine SugarCube Guide<</if>><<if tags().includes("sp-demo")>>This is made by me! Manon :D<</if>><<if tags().includes("sp-demo")>>I can't think of a good caption... so here's some text<</if>><<if tags().includes("sp-demo")>>You can put a picture here... If I forgot to add one, let me know !<</if>><<if tags().includes("sp-demo")>>[[This will only accept links, and this one is broken]]
[[But this one will send you back to the main menu!|Start]]<<else>>[[Index]]
<<link "Credits">><<popup "Credits" "Credits">><</link>>
[[Update Log]]<</if>><<if tags().includes("sp-demo")>>The bestest of guides!<<else>>Version 1.1.0<</if>><<if tags().includes("sp-demo")>>The Header in action! included in a horizontal bar<hr><</if>><<if tags().includes("sp-demo")>><hr>The Footer in action! included in a horizontal bar<<else>><hr>
<center><<link "Lexicon">><<popup 'Lexicon' "Lexicon">><</link>> - [[Index]] - [[Macros List]] - <<link "Credits">><<popup "Credits" "Credits">><</link>> - [[Need More Help?|https://manonamora-if.tumblr.com/ask]]</center>
<</if>><div style="text-align:right;font-size:75%;">Last Updated: 05 Aug '23</div>
<h1>100% Good Twine SugarCube Guide</h1>
> Note: This Guide is in a pre-release state. It may contain missing passages, links going nowhere, and typos. These will be resolved ASAP.
This guide is meant as an alternative to the documentation, with simpler explanations, meant to increase the accessibility of the SugarCube format. The guide will touch upon different aspects of SugarCube format, from its markup, to its macros, its functions and APIs. /*It will also brush upon some accessibility aspects in terms of code, design and formatting.*/
> This guide is based on the [[official SugarCube documentation|https://www.motoslave.net/sugarcube/2/docs/]], and is up to date as of the version 2.36.1.
The guide is separated in different categories: The Basics(+), Intermediate Use, and Advanced Mode. Only the Basics are necessary to understand to start out with SugarCube.
> Note: Coding in SugarCube is case and character sensitive. This means that {{{name ≠ Name}}} or {{{" " ≠ “ ”}}}.
> ''The Basics''
* [[About Twine and SugarCube|About]]
* [[Starting with SugarCube|Basics]]
> ''The Basics+''
* [[SugarCube Markup and Basic Styling|Markup]]
* [[Going Further with the Basics|Macro-Basic]]
* [[Adding some Interactivity|Macro-Interact]]
* [[Basic Special Passages|Special-Passage]]
* [[About JavaScript and the StyleSheet|Base-JS-CSS]]
* [[ULRs for Assets and Testing|URL-Types]]
> ''Intermediate Use''
* [[More Interactivity Macros|Macro-Interact-Adv]]
* [[Macros of Convenience|Macro-Conv]]
* [[More Special Passages and Tags|Special-Tags]]
* [[Harness the Power of Functions|Functions]]
* [[Using Methods to change Variables|Methods]]
* [[Adding Sound with the Audio Macros|Macro-Audio]]
* [[Going further in Styling with CSS and JavaScript|Int-JS-CSS]] [ ★ UPDATE ★ ] /*FINISH STAT*/
* [[Some Useful Basic APIs|Basic-API]]
* [[Edit the Built-In Text or Change the Game's Language|Localization]] [ ★ NEW ★ ]
> ''Advanced Mode''
> Note: New elements will be added in this section as I go through the documentation.
* [[Advanced Macros|Macro-Adv]]/* [[Going further with Basic APIs?]] TODO [ ★ NEW ★ ]*/
* [[The Settings APIs|Settings]]
* [[Going further with the Engine API|Engine-API]] [ ★ NEW ★ ]/* [[More Config APIs|Config-API]] TO DO [ ★ NEW ★ ]*/
* [[Trigger Code with Special Events|Events]] [ ★ NEW ★ ]
> [[Some Random Stuff That will be Organised Later|Organise]]
/*
-> to finish
> Accessibility
* [[Key Binding - An Alternative|KeyBinding]] HIEV SETTING TO FIX
* [[An Accessible UI|UIDesign]]
*/
If something is unclear, if you find an error in this guide, if you think I missing an important element, or if I did not provide enough examples, please [[let me know|https://manonamora-if.tumblr.com/ask]]!<h1>About Twine and SugarCube</h1>
//''Twine''// is a free and open-source tool to create interactive, non-linear stories, created by Chris Klimas in 2009. It is now maintained by multiple individuals, in [[several repositories|https://github.com/tweecode]]. ''//Twine//'' is also a registered trademark of the [[Interactive Fiction Technology Foundation|https://iftechfoundation.org/]].
''//Twine//'' offers both a desktop and browser application on [[its website|https://twinery.org]], giving creator a visual representation of each passage in their game.
Over the years, Twine has seen [[multiple story formats|http://mcdemarco.net/tools/hyperfic/twine/catalog/]], among others SugarCube. Twine compiles the code of the format to create a file in the format's choice (usually HTML) or Twee.
''//SugarCube//'' is a free (gratis and libre) coding format for Twine/Twee created and maintained by Thomas M. Edwards. It is based on JavaScript and jQuery, and can be styled with HTML and CSS.
Thomas M. Edwards is also the creator of //''Tweego''//, a free (gratis and libre) command line compiler for Twine/Twee story formats written in Go. It is an alternative to Twine, and can be used with any Integrated development environment (IDE), like VSCode.
If you want to support the parties named above, you can find here the links for:
* Chris Klimas (klembot) : [[Patreon|https://www.patreon.com/klembot]]
* Thomas M. Edwards (TME - The Mad Exile) : [[Patreon|https://www.patreon.com/thomasmedwards]] - [[Ko-Fi|https://ko-fi.com/thomasmedwards]]
* The Interactive Fiction Technology Foundation : [[Donations|https://iftechfoundation.org/give/]]
> Note: to support other parties creating assets and resources for Twine, check this [[list|https://manonamora-if.tumblr.com/post/700577877042888704/]].
<<back>>This guide was constructed by ''manonamora''.
It is based on the SugarCube official documentation, created by Thomas M. Edwards, the developer of the SugarCube format.
<h3>manonamora</h3>\
You can find:
* my other templates on [[Itch|https://manonamora.itch.io/]], as well as my guides:
** [[Ready-to-Use Tweego and Guide|https://manonamora.itch.io/twine-sugarcube-templates]]
** [[ChoiceScript to SugarCube Guide|https://manonamora.itch.io/choicescript-sugarcube-tweego-folder]]
* my games and IF experiments on [[Itch|https://manonamora.itch.io/]]
* me, and ask me questions, over on [[Tumblr|https://manonamora-if.tumblr.com]] or [[my website|https://manonamora.neocities.org/]]
* my Twine Resource Masterlist [[here|https://manonamora-if.tumblr.com/post/700577877042888704/]]
<h3>Twine and SugarCube</h3>\
[[About Twine and SugarCube|About]]
You can download Twine over on the [[Twinery.org|https://twinery.org/]] website, which includes the SugarCube format.
Thomas M. Edwards hosts the Documentation for the SugarCube format over on [[his website|https://www.motoslave.net/sugarcube/2/docs/]].
You can also find resources and help with Twine and SugarCube:
* on the [[IntFiction Forum|https://intfiction.org/c/authoring/twine/46]]
* on the [[Twine Subreddit|https://www.reddit.com/r/twinegames/]]
* in the [[Twine Discord|https://discord.gg/n5dJvPp]]
* and more listed in this [[Masterlist|https://manonamora-if.tumblr.com/post/700577877042888704/]]
<h3>HTML, CSS, JavaScript</h3>\
There are many online courses to learn the basics (or further) of the Twine-adjacent languages: HTML, CSS, JavaScript/jQuery.
* the [[W3 School|https://www.w3schools.com/]] has the most beginner explanations, and lets you test and edit their examples.
* [[MDN Web Docs|https://developer.mozilla.org/en-US/]] is more technical but provides a more extensive documentation.
* [[jQuery|https://jquery.com/]] has also a special documentation website.
<h3>This Guide also uses...</h3>\
The {{{<<message>>}}} and {{{Dialog API}}} macros from [[Chapel|https://github.com/ChapelR/custom-macros-for-sugarcube-2/]].
The Accessibility Fix for the {{{<<cycle>>}}} macro by [[HiEv|https://www.patreon.com/HiEv]]
<h3>A Special Thanks to...</h3>\
The Twine Discord, especially Crepes, TRBRY, Gwen, Cyrus, Sjoerd, SleepyFool, TME, for their help and sharing examples when I forgot what certain macros were supposed to do!__Types of Values__
//String// : type of value, word, wrapped in {" "}
//Boolean// : type of value, true/false
//Integer// : type of value, number
//Object// : type of variable, can have multiple variables nested inside
//Array// : type of variable, can have multiple values inside
__Types of Variables__
//Temporary variable// ({{{_temp}}}): an editable variable that disappears when moving to a new passage.
//Permanent variable// ({{{$var}}}): an editable variable that tracks a value until changed or unset.
//Setup variable// ({{{setup.var}}}): a variable set at the start of the game, and cannot be edited
__Other Concepts__
//API// : Application Programming Interface, code that will trigger hidden built-in fuctions
//Macro// : a block of code designed to do a specific task
//Function// : JavaScript blocks of code designed to do a specific task
//Method// : JavaScript blocks of code designed to do a specific task, linked to a reciever
> If something is missing here, let me know!!!!<h1>100% Good Twine SugarCube Guide</h1>
Versio 1.1.0
[05-Aug] - Clean up and check for update
[02-Aug] - Added the Event pages
[02-Aug] - Added the {Intro to Animation} page
[01-Aug] - Addition in the {Going Further with Settings} page.
[01-Aug] - Added the Engine API pages
[01-Aug] - Added the Localization pages
Version 1.0.2
[30-Jul] - Fixed broken links
[30-Jul] - Added external links
[30-Jul] - Added extra explanation on the Back vs Return macros, and the Conditional Statements.
[30-Jul] - Fixed errors in Typed code, Basic Macro code, Styling Markup
[30-Jul] - Corrected wrong information in the Further CSS, Interactive Macros (cycle, listbox)
[30-Jul] - Updated the Index
[30-Jul] - Completed the Macro List Page
[30-Jul] - Updated the Lexicon
<hr>
Version 1.0.1
[29-Jul] - Fixed errors in Method code (array, string)
[29-Jul] - Fixed broken links
[29-Jul] - Fixed markup errors
[29-Jul] - Fixed inconsistencies in formatting
[29-Jul] - Cleaned up TODO notes on published pages
<hr>
Version 1.0.0
[30-Jun] - Release<h1>ULRs for Assets and Testing</h1>
When wanting to include any non-Twine element into a project (i.e. image, sound, font, etc...), a URL for the file is required, as you cannot import it directly into Twine (or compile in Tweego). This URL will tell the page where to find the relevant asset and (dis)play it in the game. There are essentially two locations for assets:
* Online assets, requiring an Online URL {{{html://website/file}}}
* Local assets:
** located in the user's device, using the Absolute path URL {{{C:\User\Documents\Folder\file}}}
** located in the project folder, using Relative path URL {{{folder\file}}}
> Note: as different players will organise their devices different, the Absolute path is not recommended to include assets in a Twine project meant to be shared (online or otherwise).
\
<h3>Online Assets</h3>\
For assets hosted in a third party platform, a simple URL towards the file is needed. For example, here's the URL for a the Google-hosted font Roboto:
{{{
https://fonts.googleapis.com/css2?family=Roboto&display=swap
Importing in the StyleSheet:
@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
}}}
For the logo of the Wikimedia Foundation, the URL will look like this:
{{{
https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Wikimedia_Foundation_logo_-_vertical.svg/1024px-Wikimedia_Foundation_logo_-_vertical.svg.png
}}}
> Note: if the project is meant to be played offline, those assets will not load.
\
<h3>Relative Path</h3>\
For assets located in the gamefile, we turn to Relative paths, which is a path the operating system will take to find the wanted asset, starting from the file or program the code is triggered. For Twine projects, the starting point is the project HTML file. Assuming that the game folder is organised as follow:
{{{
index.html
images\
introduction\
cool.jpg
}}}
The image //cool.jpg// is located in the folder //introduction// which is located in the folder //images//. As such from the HTML file, the relative URL for that image would be:
{{{images\introduction\cool.jpg}}}
''But'', to ensure this will work properly, the back slashes {{{\}}} from the relative path should become forward slashes {{{/}}}
{{{images/introduction/cool.jpg}}}
\
<h3>Note on Case Sensitivity</h3>\
Like with Online URLs, Relative paths are case sensitive. This means that if a the path includes both lower and upper case characters, but the URL only includes lowercases, the asset will not load. This is relevant for:
* folder names
* asset names
* file extension (.png =/= .PNG)
It is important that all these aspects are coded in the proper case.
\
<h3>Some Recomendations</h3>\
To avoid issues with loading assets, I recommend:
* using only plain letters (a-z) and numbers (if necessary), instead of special characters (é, ñ, à, etc…)
* using {{{-}}} or {{{_}}} to replace space in the folder/file names
* be consistent in the casing (all upper or all lower case)
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>Adding Sound with the Audio Macros</h1>
Adding any asset to a project can be daunting, especially when it can involve so many macros. But adding audio is actually quite simple and only requires the use of 2 macros: {{{<<audio>>}}} and {{{<<cacheaudio>>}}}.
* [[Setting up the Audio Tracks|CacheAudio]]
* [[Create Track Groups and Playlists|Macro-Group-Playlist]]
* [[Playing Tracks in a Passage|Audio-Macro]]
* [[Other Audio Macros|Audio-Other]]
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>Setting up the Audio Tracks</h1>
To use audio tracks in your project, SugarCube requires you to cache the tracks at the start of the game by using the {{{<<cacheaudio>>}}} macro in the {{{StoryInit}}} [[Special Passage|SP-Init]].
The macro has 2 arguments:
* the ID for the track, as a reference
* the [[URL|URL-Types]] of the file, or files if a track has multiple formats.
{{{
: : StoryInit
<<cacheaudio "boom" "music/explosion.mp3">>
<<cacheaudio "synth" "music/synth.mp3" "music/synth.wav" "music/synth.aac">>
}}}
> Note: if possible, take into account browser support when adding audio tracks to a project. [[Not every format is compatible|https://caniuse.com/?search=audio%20format]].
\
<h3>Pre-loading some tracks</h3>\
If some tracks will be played from the first few screens and should be pre-loaded, the {{{<<waitforaudio>>}}} macro will do just that, by increasing the loading screen until the track(s) is(are) ready to play.
Place the macro in {{{StoryInit}}} below the necessary tracks, to load ahead. The tracks below the macro will only be cached.
{{{
: : StoryInit
<<cacheaudio "boom" "music/explosion.mp3">>
<<waitforaudio>>
<<cacheaudio "synth" "music/synth.mp3">>
<<cacheaudio "wind" "music/wind.mp3">>
<<cacheaudio "water" "music/water.mp3">>
}}}
<div id="link-menu">[[Back to the Audio Macros Menu|Macro-Audio]] - [[Back to the Start Menu|Start]]</div><h1>Create Track Groups and Playlists</h1>
On top of adding audio tracks to your project, you can also create groups of tracks, for a better control over multiple tracks at once, and playlists. The first is set by the {{{<<createaudiogroup>>}}} macro, while the second is done through {{{<<createplaylist>>}}}. Both macros need to be set in {{{StoryInit}}} ''after'' the tracks are cached.
\
<h3>Create a Track Group</h3>\
The macro only has one argument for the container, and one arugment for the sub-macro:
* {{{<<createaudiogroup>>}}}
** the name of the group, starting with {{{:}}}
* {{{<<track>>}}}
** the ID of the track
Assuming that the tracks {{{beep}}}, {{{boop}}}, and {{{swish}}} were defined above:
{{{
<<createaudiogroup ":controls">>
<<track "beep">>
<<track "boop">>
<<track "swish">>
<</createaudiogroup>>
}}}
> Note: You cannot name your group with the following: {{{:all}}}, {{{:looped}}}, {{{:muted}}}, {{{:not}}}, {{{:paused}}}, {{{:playing}}}.
\
<h3>Create a Playlist</h3>\
The macro only has one argument for the container, and three arugment for the sub-macro:
* {{{<<createplaylist>>}}}
** the ID of the playlist
* {{{<<track>>}}}
** the ID of the track
** {{{volume}}} (optional), to set the volume of the track, set from 0 (for 0%) to 1 (for 100%).
** {{{own}}} (optional), to create an independant copy of the track for the playlist
Assuming that the tracks {{{beep}}}, {{{boop}}}, and {{{swish}}} were defined above:
{{{
<<createplaylist "controls">>
<<track "beep" own>>
<<track "boop" volume 0.5>>
<<track "swish" volume 0.3 own>>
<</createplaylist>>
}}}
<div id="link-menu">[[Back to the Audio Macros Menu|Macro-Audio]] - [[Back to the Start Menu|Start]]</div><h1>Playing Tracks in a Passage</h1>
After setting tracks in {{{StoryInit}}}, you can those tracks to a passage with the {{{<<audio>>}}} macro. You also use this macro to target track groups, as well as controling the playback (ex: pause, volume change...).
The macro can be coded as is in a passage, or can be nested inside other macros, like a {{{<<link>>}}} or with a delay in {{{<<timed>>}}}.
When started, a track will play until it ends or another action is set with the {{{<<audio>>}}} macro.
The macro has 2 main arguments:
* the ID of the track or the group
* the list of action to perform (can be combined)
{{{
<<audio "ID" action>>
}}}
\
<h3>Action List</h3>\
There are 14 actions that can be included in the {{{<<audio>>}}} macro to control how a track or group of tracks is played:
<<nobr>>
<table id="audio">
<tr>
<th>Argument</th><th>Explanation</th><th>Example</th>
</tr>
<tr>
<td>{{{play}}}</td><td>Start/Restart to play the track(s)</td><td>{{{<<audio "track" play>>}}}</td>
</tr>
<tr>
<td>{{{pause}}}</td><td>Pause the track(s)</td><td>{{{<<audio "track" pause>>}}}</td>
</tr>
<tr>
<td>{{{stop}}}</td><td>Stop the track(s)</td><td>{{{<<audio "track" stop>>}}}</td>
</tr>
<tr>
<td>{{{mute}}}</td><td>Reduce the volume to 0, without pausing the track</td><td>{{{<<audio "track" mute>>}}}</td>
</tr>
<tr>
<td>{{{volume}}}</td><td>Change the volume of the track(s)</td><td>{{{<<audio "track" volume 0.5>>}}}</td>
</tr>
<tr>
<td>{{{loop}}}</td><td>Set the track(s) to repeat when reahcing the end</td><td>{{{<<audio "track" loop>>}}}</td>
</tr>
<tr>
<td>{{{unloop}}}</td><td>Remove the looping (default)</td><td>{{{<<audio "track" unloop>>}}}</td>
</tr>
<tr>
<td>{{{fadein}}}</td><td>Start/Continue to play the track(s), fading in from their current volume to max over 5 seconds</td><td>{{{<<audio "track" fadein>>}}}</td>
</tr>
<tr>
<td>{{{fadeout}}}</td><td>Start/Continues to play the track(s), fading out from their current volume to 0 over 5 seconds</td><td>{{{<<audio "track" fadeout>>}}}</td>
</tr>
<tr>
<td>{{{fadeoverto}}}</td><td>Start/Continue to play the track(s), fading it over a set amount of seconds to a certain volume level </td><td>{{{<<audio "track" 5 0.5>>}}}</td>
</tr>
<tr>
<td>{{{fadeto}}}</td><td>Start/Continue to play the track(s), fading to a certai volume level over 5 seconds</td><td>{{{<<audio "track" fadeto 0.9>>}}}</td>
</tr>
<tr>
<td>{{{goto}}}</td><td>Send the player to a certain passage at the end of the track(s)</td><td>{{{<<audio "track" goto "Home">>}}}</td>
</tr>
<tr>
<td>{{{time}}}</td><td>Move the play of the track to a certain amount of seconds from 0 (start) to the max of the file.</td><td>{{{<<audio "track" time 60>>}}}</td>
</tr>
</table>
<</nobr>>
Assuming that the track {{{space}}}, inside the group {{{:space}}}, has been cached, here are some extra examples:
{{{
<<audio ":space" play>>
→ Will start to play the group of tracks called :space, all at the same time.
<<audio "space" volume 0.65 play>>
→ Will start playing the track {space} at 65% volume
<<audio "space" time 92 play>>
→ Will start playing the track {space} from the 92th second
<<audio "space" loop play>>
→ Will start playing the track {space} on repeat
<<audio "space" volume 10 fadein>>
→ Will start playing the track {space}, fading in from 10% to max volume
<<audio "space" volume 0.15 fadeto 0.78>>
→ Will start playing the track {space}, fading from 15% to 78% volume
<<audio "space" volume 0.04 fadeoverto 27 0.96>>
→ Will start playing the track {space}, fading from 4% to 96% volume over 27 seconds
<<audio "space" play goto "Home">>
→ Will start playing the track {space}, and send the player to the passage "Home" when the track ends.
}}}
<h3>Group IDs</h3>\
Aside from targetting groups, the {{{<<audio>>}}} macro can also target the state of tracks.
{{{
<<audio ":paused" play>>
→ Will start playing all tracks previously paused
<<audio ":playing" pause>>
→ Will pause all tracks currently playing
<<audio ":playing" stop>>
→ Will stop all tracks currently playing
<<audio ":all" stop>>
→ Will stop all tracks (playing and paused)
<<audio ":playing:not(:space)" stop>>
→ Will stop all tracks currently playing, except the ones in the ":space" group
<<audio ":all:not(:space)" volume 0.40>>
→ Will change the volume of all tracks not in the ":space" group to 40%
}}}
\
<h3>The {{{<<playlist>>}}} macro</h3>\
This macro will work similarly to the {{{<<audio>>}}} macro, aside from targetting playlists set in {{{StoryInit}}} instead of groups or single tracks.
The macro has 2 main arguments:
* the ID of the playlist
* the list of action to perform (can be combined)
{{{
<<playlist "ID" action>>
}}}
This macro has three extra actions:
* {{{shuffle}}}, shuffling the order of the tracks
* {{{unshuffle}}}, reorganising the order of the tracks to its original form
* {{{skip}}}, skipping the next track in the playlist
{{{
<<playlist "playlist" shuffle>>
<<playlist "playlist" unshuffle>>
<<playlist "playlist" skip>>
}}}
> Note: The action {{{goto}}} will not work with {{{<<playlist>>}}}
<div id="link-menu">[[Back to the Audio Macros Menu|Macro-Audio]] - [[Back to the Start Menu|Start]]</div><h1>Other Audio Macros</h1>
There are three extra macros that can affect the played audio.
\
<h3>{{{<<masteraudio>>}}}</h3>\
This macro will control the master volume of the game (overall volume), as well as affect all registered tracks, regardless of their state.
This macro only has one argument, the action:
* {{{mute}}} and {{{unmute}}}, muting or unmuting the master volume of the game.
* {{{muteonhide}}} and {{{nomuteonhide}}}, which will either mute or unmute (default) the master volume when the player moves to another tab or minimize the browser.
* {{{stop}}}, which will stop all registered tracks.
* {{{volume}}}, which will change the master volume to a specified level
{{{
<<masteraudio action>>
}}}
> Note: the master audio volume can be changed at will by the player with a [[Slider Setting|SettingsRange]]
\
<h3>{{{<<removeaudiogroup>>}}}</h3>\
This macro will delete a track group, which was previously set with {{{<<createaudiogroup>>}}}, by targetting the ID of the group. As with the latter macro, it will not accept the following IDs: {{{:all}}}, {{{:looped}}}, {{{:muted}}}, {{{:not}}}, {{{:paused}}}, {{{:playing}}}.
{{{
<<removeaudiogroup ":space">>
}}}
\
<h3>{{{<<removeplaylist>>}}}</h3>\
This macro will delete a playlist, which was previously set with {{{<<createplaylist>>}}}, by targetting the ID of the playlist.
{{{
<<removeplaylist "playlist">>
}}}
<div id="link-menu">[[Back to the Audio Macros Menu|Macro-Audio]] - [[Back to the Start Menu|Start]]</div><h1>Some Useful Basic APIs</h1>
Along with macros, there are further APIs to trigger an event in the game, such as undoing an action, opening a popup, or configuring some functionalities in the engine.
Those APIs are JavaScript-based code that should either be included in the JavaScript or within the {{{<<run>>}}} or {{{<<script>>}}} macros to work.
* [[Moving back and forth in the History|Basic-API-Engine]]
* [[Create a PopUp|Basic-API-Dialog]]
* [[Handle the SideBar|Basic-API-UIBar]]
* [[Open the JumpTo, Restart, Saves, and Settings PopUp|Basic-API-UI]]
* [[Overriding the Navigation to a Passage|Basic-Config-Navig]]
* [[Some Useful Configuration API for your Project|Basic-API-Config]]
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>Moving back and forth in the History</h1>
Moving back and forth in the Player's History is possible in the base SugarCube UI with the History buttons at the top of the SideBar.
However, if those buttons are removed, through with [[Config API|Basic-API-Config]] or because the SideBar is not on the page, there is still one way to let the player go back and forth: with the {{{Engine.backward()}}} and {{{Engine.forward()}}}, nested inside a {{{<<link>>}}} or a {{{<<button>>}}}.
{{{
<<run Engine.backward()>>
<<script>>Engine.forward()<</script>>
With a link/button:
<<link "Back">><<run Engine.backward()>><</link>>
<<button "Forward">><<script>>Engine.forward()<</script>><</button>>
}}}
While, this API can also be used without player interaction, by simply including the API in a non-interactive macro (e.g. {{{<<timed>>}}}), to automatically rewind/redo the action, I would not recommend it.
<div id="link-menu">[[Back to the Basic API Menu|Basic-API]] - [[Back to the Start Menu|Start]]</div><h1>Create a PopUp</h1>
Instead of moving to another passage to show a bit of text to the player, the Dialog API is here to create <<link "PopUps">><<popup "Basic-UI-Dialog" "Dialog Box">><</link>>!
To create a popup, you will need 3 APIs, in this order:
* {{{Dialog.setup()}}}, to prepare the popup, and add a title (optional)
* {{{Dialog.wiki()}}}, to include text in the popup
* {{{Dialog.open()}}}, to open the dialog box
{{{
Dialog.setup('This a PopUp');
Dialog.wiki("And here is the text. Even some //italics// and ''bold''!");
Dialog.open();
}}}
> Note: be mindful of quotes in {{{Dialog.wiki()}}}, as it could have issues.
For longer popups, to avoid messy code blocks and have a bit more control over the text, you can use {{{Story.get().processText()}}} to pull the content of a passage instead.
{{{
Dialog.wiki(Story.get("Passage Name").processText());
}}}
> Note: Chapel has created a [[Macro Set|https://github.com/ChapelR/custom-macros-for-sugarcube-2/blob/master/docs/dialog-api-macro-set.md]] to make the process of coding Popups easier. This macro is used in this guide.
While Dialog box have built-in close buttons in the top-right corner, and by clicking outside of th dialog box, if the popup has interactive elements that triggers further code (like moving to a different passage), you will need to use {{{Dialog.close()}}} to automatically close the popup.
{{{
Dialog.close()
}}}
<div id="link-menu">[[Back to the Basic API Menu|Basic-API]] - [[Back to the Start Menu|Start]]</div><h1>Open the JumpTo, Restart, Saves, and Settings PopUp</h1>
The elements above are included in the base SugarCube UI, as buttons in the menu (if they are populated), but can be called at any time with the APIs below:
* {{{UI.jumpto()}}}, will open the JumpTo Menu, allowing the player to go back in the History to a [[bookmarked passage|Tags-Built]].
* {{{UI.restart()}}}, will open a popup asking the player if they would like to Restart the Game.
* {{{UI.saves()}}}, will open the Save popup.
* {{{UI.settings()}}}, will open the Settings popup
Those APIs are most useful inside a {{{<<link>>}}} or {{{<<button>>}}} when:
* the UI of the project doesn't include the built-in SideBar
* when the menu has been removed from the SideBar
* in a Starting Menu Passage or an Ending Passage
<div id="link-menu">[[Back to the Basic API Menu|Basic-API]] - [[Back to the Start Menu|Start]]</div><h1>Handle the SideBar</h1>
With the APIs below, you can control when/where the SideBar will appear on the page. These can be included directly on the passage (with either {{{<<run>>}}} or {{{<<script>>}}}), or in the JavaScript.
{{{UIBar.hide()}}} will hide the SideBar on the page, and stay hidden until {{{UIBar.show()}}} is triggered. Even if it won't appear on the page, the element {{{#ui-bar}}} will still be included in the HTML, but with a display value of {{{none}}} when hidden.
Similarly, {{{UIBar.stow()}}} will stow the SideBar to the side (but still visible), and stay stowed until {{{UIBar.unstow()}}} is triggered. The element {{{#ui-bar}}} will receive a special class {{{.stowed}}}, and transition from one state to another with a smooth animation.
{{{UIBar.destroy()}}}, on the other hand will remove the the element {{{#ui-bar}}} completely.
> Note: if {{{StoryInterface}}} is in use, and does not include the element {{{#ui-bar}}} within this Special Passage, there is no need to include this API.
<div id="link-menu">[[Back to the Basic API Menu|Basic-API]] - [[Back to the Start Menu|Start]]</div><h1>Some Useful Configuration API for your Project</h1>
To customise your project further, here are a few Config APIs you might find useful.
\
<h3>Remove the History Buttons</h3>\
To force players to move forwards, it is possible to remove the //Forward// and //Backwards// button at the top of the SideBar, with the following code in the JavaScript:
{{{
Config.history.controls = false;
}}}
> Note: this is only useful if the Base UI is in use or the element {{{#ui-bar-history}}} appears on the page.
> Note 2: when removing those controls, you may need to ensure the player will always find a way to go backward and forward in the story.
\
<h3>Change the Max Amount of States</h3>\
To avoid the player rewinding too much, you change the maximum number of state the history can save. These are active passages visited the player can go back to by pressing the //Backwards// button. If the player has visited more passage than the limit, the earlier visited states are moved to an "Expired" state, and won't be available to go back to with the back arrow or {{{Engine.backward()}}}.
{{{
Config.history.maxStates = 40; //(default)
Config.history.maxStates = 1; //(will not allow player to go backward)
}}}
> Note: the larger the {{{maxStates}}}, the bigger the chance of lag when loading new passages.
\
<h3>Change the Number of Save Slots</h3>\
With a default of 8 save slots (+ autosave and export), players have many opportunities to save a play through. Still, the number of save slots can be modified:
{{{
Config.saves.slots = 4;
}}}
> Note: the higher the number, the more the game will save in the player's cache.
\
<h3>Removing Unwanted Blank Space</h3>\
Aside from using the {{{<<nobr>>}}} macro or {{{nobr}}} tag, there are two Config APIs which will remove the unnecessary blank space in your project: {{{Config.cleanupWikifierOutput}}} and {{{Config.passages.nobr}}}.
{{{Config.cleanupWikifierOutput}}} will transform any {{{<br>}}} on the page into empty {{{<p>}}} (thus, "disappear"), as well as wrap any non {{{<div>}}} elements with {{{<p>}}}.
> Note: {{{Config.cleanupWikifierOutput}}} runs into strange issues sometimes, like working strangely with the {{{<<cycle>>}}} macro ([[this can be fixed|Accessibility-Cycle]]).
On the other hand, {{{Config.passages.nobr}}} will only remove any break on the page. This means that you will need to wrap every paragraph or bit of text with a block HTML makrup (i.e. {{{<p>}}}, {{{<div>}}}, {{{<h1>}}}, etc...) manually.
{{{
Config.cleanupWikifierOutput = true;
Config.passages.nobr = true;
}}}
> Note: if both are included, no matter the order, {{{Config.passages.nobr}}} will remove all breaks on the page.
<div id="link-menu">[[Back to the Basic API Menu|Basic-API]] - [[Back to the Start Menu|Start]]</div><h1>Overriding the Navigation to a Passage</h1>
While moving from passage to passage is dictated by the Passage Name in a link or in a {{{<<goto>>}}} macro, there is still a possibility to override the original destination, sending the player to a new passage. This is where {{{Config.navigation.override}}} comes in:
{{{
Config.navigation.override = function (dest) {
/* code */
};
}}}
> Note: this requires a bit of JavaScript knowledge to fill in the Config (or edit the example below).
Assuming that you want to send the player to an End Screen ({{{"You Died"}}}) because their {{{$health}}} is too low (0 or less):
{{{
Config.navigation.override = function (dest) {
var sv = State.variables;
if (sv.health <= 0) {
return "You Died";
}
};
}}}
> Note: {{{State.variables}}} is how to code a variable (here $health) in JavaScript that was set in a SugarCube passage.
If there are multiple situations where the player should be sent to a special passage:
{{{
Config.navigation.override = function (dest) {
var sv = State.variables;
if (sv.health <= 0) {
return "You Died";
}
else if (sv.coins = 0) {
return "You Poor";
}
};
}}}
An important note: if there is a link to a different passage in the End Screen and the variable still has a value that would run the code above, the Navigation will be overriden again when that link is clicked. You can avoid this by:
* change the value of the variable
* unset the variable
* remove any link that would move the player to a new passage
\
<h3>A non-JavaScript Alternative</h3>\
While the method above is prefered, this navigation override is also possible to do in SugarCube code, inside the {{{PassageReady}}} with a couple of conditional statements and {{{<<goto>>}}} macros:
{{{
: :PassageReady
<<if !$ending>>
<<if $health <= 0>>
<<set $ending to true>>
<<goto "You Died">>
<<elseif $coins = 0>>
<<set $ending to true>>
<<goto "You Poor">>
<</if>>
<</if>>
}}}
Since this is run before the passage is [[fully rendered|SP-PassageReady-Done]], it is important that the {{{$ending}}} variable is included here, and set as true before the {{{<<goto>>}}} macro, otherwise the player will run into an endless loop.
<div id="link-menu">[[Back to the Basic API Menu|Basic-API]] - [[Back to the Start Menu|Start]]</div><h1>Starting with SugarCube</h1>
When starting an IF project, it is best to start with the Basic. For SugarCube, this means linking passages to move the player to a different part of the story, saving information and player choices in [[variables|Variables-Base]], and tracking those variables to display variations down the line.
For each, you essentially need 3 macros : {{{<<link>>}}}, {{{<<set>>}}}, and {{{<<if>>}}}.
* [[The Basics of Variables|Variables-Base]]
* [[The Elements on the Page|Basics-UI]]
* [[Linking Passages|Macro-Link-Basic]]
* [[Tracking Information|Macro-Set-Basic]]
* [[Display Variation|Macro-If-Basic]]
> Note: Any code on the page will be displayed top to bottom by the program. Code at the top of the passage can affect code further down.
Want to see this in action? Try this [[Demo|Demo-Basic]]!
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>The Elements on the Page</h1>
There are essentially 3 main elements on the page:
* the passage (in green)
* the UI-Bar (in red)
* the dialog box (<<link "click here">><<popup "Basic-UI-Dialog" "Dialog Box">><</link>>)
\
The content in the passages are generated by the story passages in Twine. Every time the player clicks on a link to advance the story, the passage will refresh with the new content.
In the UI-Bar, you will find arrows to go back and forth in the player passage history (the visited passage), an arrow to hide/show the sidebar, as well as the Save and Restart buttons.
To add or change content in the UI-Bar, you need to use a [[Special Passage|SP-UIBar]].
Dialog boxes are elements that will appear on top of the page. It is used by the Menu buttons in the sidebar, but can also contain text from a story passage (like the Lexicon link below). To create a dialog box, [[see this page|Basic-API-Dialog]].
<style>#story {background: #012f01;} #ui-bar {background-color: #330404;}</style>
<div id="link-menu">[[Back to the Basics Menu|Basics]] - [[Back to the Start Menu|Start]]</div>You found the dialog box!<h1>Linking Passages and the {{{<<link>>}}} Macro</h1>
To move the player from one part of the story to another, you need to link the passages. This can be done in two ways: the link markup {{{[[Link]]}}} or the {{{<<link>>}}} macro. While both options will essentially achieve the same thing, the latter is more flexible and has more interactive uses. However, in some cases, {{{<<link>>}}} will not create a visual link between passage blocks in Twine.
\
<h3>The {{{[[Link]]}}} markup</h3>\
To create a link using the {{{[[Link]]}}} markup, you need to wrap a bit of text with double quare brackets.
> Note: In the Twine application, wrapping a bit of text with the square brackers will automatically create a passage with the text inside the brakets as that passage's name.
{{{
[[Go to the Garden]]
→ will send the player to the passage called "Go to the Garden"
}}}
If you prefer to have a different text than the name of the passage displayed as the link, you can use a pipe separator {{{ | }}}.
This way of coding a link is useful when you have multiple links toward one passage.
{{{
[[Go to the Garden|Garden]]
→ will display the text "Go to the Garden" and will send the player to the passage called "Garden"
}}}
> For more advanced uses of the link markup, see [[this page|Markup-Link]].
\
<h3>The {{{<<link>>}}} macro</h3>\
One of the use of the {{{<<link>>}}} macro is to send the player to a different passage. This can be formatted in different ways:
{{{
In combination with the link markup:
<<link [[Go to the Garden]]>><</link>>
→ will send the player to the passage called "Go to the Garden"
<<link [[Go to the Garden|Garden]]>><</link>>
→ will display the text "Go to the Garden" and will send the player to the passage called "Garden"
}}}
{{{
Without the link markup:
<<link "Go to the Garden" "Garden">><</link>>
→ will display the text "Go to the Garden" and will send the player to the passage called "Garden"
}}}
> Note: Without the link markup, this ''won't create a visual link between passage blocks'' in the story map on the Twine application.
Because the link macro is a container (with an opening and a closing block), you can include more code inside, like another macro:
{{{
<<link "Text">>/*Code Here*/<</link>>
Example:
<<link "Take Coin">><<unset $coin>><</link>>
}}}
> Note: you can switch the {{{<<link>>}}} macro for the {{{<<button>>}}} macro, as their only difference is how they are formatted on the page.
> For more advanced uses of the link macro, see [[this page|Macro-Link]].
<div id="link-menu">[[Back to the Basics Menu|Basics]] - [[Back to the Start Menu|Start]]</div><h1>Tracking Information and the {{{<<set>>}}} Macro</h1>
To track information and choices made by the player, you would need to set [[variables|Variables-Base]] and save this information as a value, by using the {{{<<set>>}}} Macro.
There are multiple ways of saving a value, by useing either a ''temporary'' or ''permanent'' variable. Like their names suggests, a temporary variable will disappear when the player move passage, while the permanant variable will stick around (until you [[destroy|Macro-Unset]] it).
{{{
<<set $variable to 5>>
<<set $variable to 'some words'>>
<<set $variable to true>>
<<set _temporary to 5>>
}}}
You can also set multiple variables inside one macro:
{{{<<set $var to 5, $var2 to 'some words', $var3 to true, _temp to 5>>}}}
If you want to track the choice of a player before the passage changes, you can set a variable inside a link.
> Note: setting a temporary variable in a forwarding link is useless...
{{{
Link markup:
[[Displayed Text|PassageName][$variable to 5]]
[[Displayed Text|PassageName][$variable to 5, $var2 to 'some words', $var3 to true]]
}}}
{{{
Link macro:
<<link [[Displayed Text|PassageName]]>><<set $variable to 5>><</link>>
<<link [[Displayed Text|PassageName]]>><<set $var to 5, $var2 to 'some words', $var3 to true, _temp to 5>><</link>>
}}}
> Note: the type of value in a variable is not set in stone the moment the variable is set. You can set a variable as a integer (number), before setting it as a string (words) a few passages later, without having to unset it in between.
For other mathematical operators or advanced uses of the {{{<<set>>}}} Macro, [[see this page|Macro-Set]].
For formatting links, [[see this page|Macro-Link-Basic]].
<div id="link-menu">[[Back to the Basics Menu|Basics]] - [[Back to the Start Menu|Start]]</div><h1>Display Variation and the {{{<<if>>}}} Macro</h1>
Following a choice from the player, you may want to show different variations of a passage depending on that choice. This can be done with a conditional statement, using the {{{<<if>>}}} Macro, which requires a [[set variable|Macro-Set-Basic]].
Note: in the examples below, the variables could have [[any type of value|Variables-Base]] to work.
{{{
A single variation:
<<if $choice is 1>>This text will only show if the value of variable $choice is 1<</if>>
Two variations:
<<if $choice is true>>This text will show if the variable $choice is true<<else>>If not, this text will show<</if>>
Two specific variations:
<<if $choice is "stone">>This text will show if the value of variable $choice is "stone"<<elseif $choice is "grass">>But if the value of the variable $choice is "grass", then this text will show<</if>>
Three variations:
At the store you picked <<if $pet is "dog">>a dog<<elseif $pet is "car">>a cat<<else>>a bird<</if>>.
}}}
Conditional statements can also be nested inside one another:
{{{
<<if $choice is 1>>
<<if $pet is "dog">>
This will show this sentence on the page.
<<elseif $pet is "cat">>
Or maybe this one.
<</if>>
<<else>>
Otherwise it will be this one.
<</if>>
}}}
For other operators and more advanced uses of the {{{<<if>>}}} Macro, see [[this page|Macro-If]].
<div id="link-menu">[[Back to the Basics Menu|Basics]] - [[Back to the Start Menu|Start]]</div><h1>Variables and Values in SugarCube</h1>
<h3>Value Types</h3>\
Values are bits of data stocked inside a variable, which can be:
* numbers (also called integer)
* words (also called strings)
* Boolean (true/false)
* functions (advanced - not covered)
> Note: You can have numbers in strings, but you won't be able to change the value of this number (unless you make the value an integer).
\
<h3>Variable Types</h3>\
To organise those values, there are three types of variables to consider:
* //basic//: one value only
* //array//: a list of values, each with a set position
* //object//: values linked to properties
Depending on how much information is tracked, the latter two options are a great way to keep it organised (but they are not necessary for simple IF projects). To set a variable, see [[the Set Macro|Macro-Set-Basic]].
In SugarCube, variables can been viewed as followed:
{{{
basic:
$variable = 5
$variable = "some words"
$variable = true
array:
$variable = [5, "some words", true]
object:
$variable = {number: 5, string: 'some words', boolean: true}
}}}
\
<h3>Variable Storage</h3>\
Variables can be store in different places:
* temporary ({{{_temporary}}}), where the variable disappears when moving to a new passage
* permanant ({{{$variable}}}), where the variable is stored until you [[destroy|Macro-Unset]] it
* settings* ({{{settings.var}}}), or variables related to the Settings
* setup* ({{{setup.var}}} - should be set in StoryInit), which is meant for unchanging values (ex: the price of an object)
*it is unlikely you will need those in a basic project.
<div id="link-menu">[[Back to the Basics Menu|Basics]] - [[Back to the Start Menu|Start]]</div>A simple choice.
In front of you sit three boxes: a blue one, a green one, and a red one. Inside each box but one, there is a treat.
Which box do you choose?
* [[the blue box|Demo-Basic-Reveal][$box to "blue"]]
* [[the green box|Demo-Basic-Reveal][$box to "green"]]
* [[the red box|Demo-Basic-Reveal][$box to "red"]]
* [[no box|Demo-Basic-Reveal][$box to false]]
<hr>
<<message "Code">>
{{{
A simple choice.
In front of you sit three boxes: a blue one, a green one, and a red one. Inside each box but one, there is a treat.
Which box do you choose?
* [[the blue box|Demo-Basic-Reveal][$box to "blue"]]
* [[the green box|Demo-Basic-Reveal][$box to "green"]]
* [[the red box|Demo-Basic-Reveal][$box to "red"]]
* [[no box|Demo-Basic-Reveal][$box to false]]
}}}
<</message>><<if $box is false>>You did not choose a box.<<else>>You chose the <<if $box is "blue">>blue box, and found a cookie.<<elseif $box is "red">>red box, but found nothing.<<else>>green box, and found an apple<</if>><</if>>
* [[Try again?|Demo-Basic]]
<hr>
<<message "Code">>
{{{
<<if $box is false>>You did not choose a box.<<else>>You chose the <<if $box is "blue">>blue box, and found a cookie.<<elseif $box is "red">>red box, but found nothing.<<else>>green box, and found an apple<</if>><</if>>
* [[Try again?|Demo-Basic]]
}}}
<</message>>
<div id="link-menu">[[Back to the Basics Menu|Basics]] - [[Back to the Start Menu|Start]]</div><h1>The Engine APIs</h1>
Aside from [[moving back and forth|Basic-API-Engine]] in the player history, the Engine APIs has some useful functions to customize the gameplay of your project. Some of these APIs are more useful in JavaScript code than in TwineScript code in the passage.
* [[Checking the State of the Game|Engine-State]]
* [[Move through the Player's History|Engine-Go]]
* [[(Re-)Play a Passage|Engine-Play]]
* [[Restarting without the Built-In PopUp|Engine-Restart]]
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>Checking the State of the Game</h1>
There are instences where knowing the state of the game before triggering a certain bit of code is important, such as with macros needing the passage to be fully idle to change something on the screen, or if the game has a server connection, this set of Engine API will show whether the game is in one of the following three states:
* {{{idle}}}: the page is idle (default)
* {{{playing}}}: nagivation to a new passage has been triggered
* {{{rendering}}}: a passage is rendering on the screen
You can check which state the game is currently at with {{{Engine.state}}}:
{{{
<<print Engine.state>>
in JavaScript:
if (Engine.state === "rendering") {/* your JS code */}
}}}
SugarCube has also three other Engine API to check for a specific state:
* {{{Engine.isIdle()}}}, checking if the page is idle
* {{{Engine.isPlaying()}}}, checking is the navigation to a new passage has been triggered
* {{{Engine.isRendering()}}}, checking if a passage is rendering on the screen
{{{
if (Engine.isIdle()) {/* your JS code */}
else if (Engine.isRendering()) {/* your JS code */}
}}}
> Note: while those are useful, if you are looking to target a more specific time during the redering of a passage or element, you may want to check the [[Events]], instead.
<div id="link-menu">[[Back to the Engine API Menu|Engine-API]] - [[Back to the Start Menu|Start]]</div><h1>Move through the Player's History</h1>
While there are already [[options to go back and forth|Basic-API-Engine]] in the player's history, you can move further back and forth with the {{{Engine.go()}}} API.
{{{
Engine.go(number)
}}}
By indicating a number - positive to move forward, negative to move back - you will be telling the engine to undo or redo the player's actions as many times as the number. For example:
{{{
Engine.go(2) → Redoes two moments, forwards the player twice
Engine.go(-4) → Undoes four moments, send the player back four times
}}}
Another method, to target a specific turn in the player's history is to use {{{Engine.goTo()}}}:
{{{
Engine.goTo(number)
}}}
Unlike the previous method, the number indicates the specific passage in the player's history, with {{{0}}} being the starting page.
{{{
Engine.goTo(0) → Goes to the first screen
Engine.goTo(9) → Goes to the tenth screen
}}}
> Note: as it is hard to predict how a player will interact with a game, and what path they take, this method can be quite unreliable.
<div id="link-menu">[[Back to the Engine API Menu|Engine-API]] - [[Back to the Start Menu|Start]]</div><h1>(Re-)Play a Passage</h1>
While you can use links to move the player to a new passage, there is as well an Engine API to show said passage to the player:
{{{
Engine.play("PassageName" [, noHistory])
}}}
In a passage, you will need to use the API the {{{<<run>>}}} or {{{<<script>>}}} macro:
{{{
<<run Engine.play("PassageName")>>
}}}
The passage will then load, and will be added to the history of the player.
> Note: if you want to know when the last time {{{Engine.play()}}} was used, {{{Engine.lastPlay}}} will give you that information.
\
<h3>Not adding to the History</h3>\
{{{Engine.play()}}} allows showing a passage without adding to the player's history. To do so, you need to code it as follow:
{{{
Engine.play("PassageName", true)
}}}
> Note: if the passage you want to show is the same as the current passage (a sort of refreshing the page), you can use {{{Engine.show()}}} instead.
When triggered, the page will display the new passage. It will also change the value of variables if coded, which may affect what is displayed ont the screen. For example:
{{{
:: StoryInit
<<set $words = 'I say hello'>>
:: Passage
<<print $words>>
<<button " Click">>
<<set $words = 'You say goodbye'>>
<<run Engine.play('beat',true)>>
<</button>>
}}}
When the passage is first displayed, the page will show {{{I say hello}}}. After clicking on the button, the passage will refresh and will now show: {{{You say goodbye}}}.
''HOWEVER'', any changed value in the previous passage or the currently displayed one ''won't'' save until a new moment is created in the player's history. If the player refreshed the browser tap (F5) after {{{Engine.play("PassageName", true)}}} has been triggered, any action done or change in value since the display of the original passage will be lost.
<div id="link-menu">[[Back to the Engine API Menu|Engine-API]] - [[Back to the Start Menu|Start]]</div><h1>Restarting without the Built-In PopUp</h1>
Outside of the base [[Restart API|Basic-API-UI]], SugarCube has another way to restart a game, withe {{{Engine.restart()}}}. Unlike its counterpart {{{UI.restart()}}}, which will create a popup warning the player to save their progress, {{{Engine.restart()}}} will restart the file when triggered and without warning.
This method can useful when wanting a more custom Restart screen, if the game does not have any saves, or at an end screen.
Whatever reason for its use, {{{Engine.restart()}}} should be triggered through a link or a button, inside the {{{<<run>>}}} or {{{<<script>>}}} macro:
{{{
<<button "Restart">>
<<run Engine.restart()>>
<</button>>
}}}
Another way to edit the Built-In PopUp is to change the relevant [[l10nStrings|Local-L10n]] in the JavaScript.
<div id="link-menu">[[Back to the Engine API Menu|Engine-API]] - [[Back to the Start Menu|Start]]</div><h1>Trigger Code with Special Events</h1>
Events are messages sent within the game file to notify special code that something has happened, whether the latter was automated or from a player interacting. Each event is formatted as an object and contains information about the state at the moment of the event and what happened during the event.
You can find these events used plainly in JavaScript (e.g. scroll back to the top) or within macros.
> Note: The events discussed here are specific to SugarCube. The format, however, does accept more [[standardized events|https://developer.mozilla.org/en-US/docs/Web/Events]].
* [[Dialog Events|Events-Dialog]]
* [[Passage and Navigation Events|Events-Passage]]
* [[System Events|Events-System]]
* [[Type Macro Events|Events-Type]]
/* [[Audio Events|Events-Audio]]*/
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>Dialog Events</h1>
The following events allow the execution of JavaScript code at specific points during the opening and closing of popups. The events will be triggered when using the [[Dialog API|Basic-API-Dialog]]. They happen in the following order:
{{{
:dialogopening
:dialogopened
//Player Interaction inside the Dialog Box//
:dialogclosing
:dialogclosed
}}}
> Note : The events are triggered by the body element of the popup {{{#ui-dialog-body}}}.
\
<h3> {{{:dialogopening}}}</h3>\
This event is triggered as the popup is opening (as the first step of {{{Dialog.open()}}}). You can include any JavaScript code inside the following container:
{{{
$(document).on(':dialogopening', function (ev) {
/* JavaScript code */
});
}}}
> Note: to execute the code only once throughout the whole game, replace {{{.on}}} by {{{.one}}}
\
<h3> {{{:dialogopened}}}</h3>\
This event is triggered when the popup is fully rendered (as the last step of {{{Dialog.open()}}}). You can include any JavaScript code inside the following container:
{{{
$(document).on(':dialogopened', function (ev) {
/* JavaScript code */
});
}}}
> Note: to execute the code only once throughout the whole game, replace {{{.on}}} by {{{.one}}}
An usefule example, where any new popup with overflow will have its text displayed from the top.
{{{
$(document).on(':dialogopened', function (ev) {
$("#ui-dialog-body").scrollTop(0);
});
}}}
\
<h3> {{{:dialogclosing}}}</h3>\
This event is triggered as the popup is closing (as the first step of {{{Dialog.close()}}}). You can include any JavaScript code inside the following container:
{{{
$(document).on(':dialogclosing', function (ev) {
/* JavaScript code */
});
}}}
> Note: to execute the code only once throughout the whole game, replace {{{.on}}} by {{{.one}}}
\
<h3> {{{:dialogclosed}}}</h3>\
This event is triggered when the popup is fully closed (as the last step of {{{Dialog.close()}}}). You can include any JavaScript code inside the following container:
{{{
$(document).on(':dialogclosed', function (ev) {
/* JavaScript code */
});
}}}
> Note: to execute the code only once throughout the whole game, replace {{{.on}}} by {{{.one}}}
<div id="link-menu">[[Back to the Events Menu|Events]] - [[Back to the Start Menu|Start]]</div><h1>Passage and Navigation Events</h1>
The following events allow the execution of JavaScript code at specific points during the rendering of a passage, as well as [[Special Passages|Special-Passage]], a.k.a passage navigation. The order of those events go as follow:
{{{
1- Passage initiation (before change in history)
:passageinit event
2- Passage start (before passage rendering)
PassageReady
:passagestart event
PassageHeader
3- Passage render (after passage rendering)
PassageFooter
:passagerender event
4- Passage display (after passage displayed)
PassageDone
:passagedisplay event
5- UI bar special passages update
StoryBanner
StoryDisplayTitle
StorySubtitle
StoryAuthor
StoryCaption
StoryMenu
6- Passage end (end of passage navigation)
:passageend event
}}}
\
<h3>{{{:passageinit}}}</h3>\
This event is triggered before the player's history is modified (a.k.a just after the start to navigation is called). It also will contain the elements of the passage to display next.
You can include any JavaScript code inside the following container:
{{{
$(document).on(':passageinit', function (ev) {
/* JavaScript code */
});
}}}
> Note: to execute the code only once throughout the whole game, replace {{{.on}}} by {{{.one}}}
\
<h3>{{{:passagestart}}}</h3>\
This event is triggered before the rendering of the incoming passage. It will also contain the elements of the passage to display next, and the HTML (currently empty) elements to render.
You can include any JavaScript code inside the following container:
{{{
$(document).on(':passagestart', function (ev) {
/* JavaScript code */
});
}}}
> Note: to execute the code only once throughout the whole game, replace {{{.on}}} by {{{.one}}}
\
<h3>{{{:passagerender}}}</h3>\
This event is triggered after the rendering of the incoming passage. It will also contain the elements of the passage rendering, and the HTML elements rendered.
You can include any JavaScript code inside the following container:
{{{
$(document).on(':passagerender', function (ev) {
/* JavaScript code */
});
}}}
> Note: to execute the code only once throughout the whole game, replace {{{.on}}} by {{{.one}}}
\
<h3>{{{:passagedisplay}}}</h3>\
This event is triggered after the incoming passage is displayed. It will also contain the elements of the passage displayed, and the HTML elements rendered.
You can include any JavaScript code inside the following container:
{{{
$(document).on(':passagedisplay', function (ev) {
/* JavaScript code */
});
}}}
> Note: to execute the code only once throughout the whole game, replace {{{.on}}} by {{{.one}}}
An example where the incoming passage with overflow will be displayed from the top, useful when the previous passage required some scrolling.
{{{
$(document).on(":passagedisplay", function() {
$("#passages").scrollTop(0);
});
}}}
\
<h3>{{{:passageend}}}</h3>\
This event is triggered at the end of the passage navigation. It will also contain the elements of the passage displayed, and the HTML elements rendered.
You can include any JavaScript code inside the following container:
{{{
$(document).on(':passageend', function (ev) {
/* JavaScript code */
});
}}}
> Note: to execute the code only once throughout the whole game, replace {{{.on}}} by {{{.one}}}
<div id="link-menu">[[Back to the Events Menu|Events]] - [[Back to the Start Menu|Start]]</div><h1>System Events</h1>
The following events allow the execution of JavaScript code at specific points during story startup and restart.
\
<h3>{{{:storyready}}}</h3>\
This is a global event that will be triggered just before the loading screen disappears at startup.
You can include any JavaScript code inside the following container:
{{{
$(document).one(':storyready', function (ev) {
/* JavaScript code */
});
}}}
\
<h3>{{{:enginerestart}}}</h3>\
This is a global event that will be triggered just before the page is reloaded when using {{{Engine.restart()}}}.
You can include any JavaScript code inside the following container:
{{{
$(document).one(':enginerestart', function (ev) {
/* JavaScript code */
});
}}}
> Note: these events are only triggered once.
<div id="link-menu">[[Back to the Events Menu|Events]] - [[Back to the Start Menu|Start]]</div><h1>Type Macro Events</h1>
The {{{<<type>>}}} macro has events allowing the execution of JavaScript code at specific points during typing. They are sequenced as follow:
{{{
:typingstart
:typingstop
:typingcomplete
}}}
> Note: every new addition of the {{{<<type>>}}} macro after a {{{:typingcomplete}}} is triggered will start the sequence again.
\
<h3>{{{:typingstop}}}</h3>\
This is a local event that will be triggered when the typing of a section starts.
You can include any JavaScript code inside the following container:
{{{
$(document).on(':typingstop', function (ev) {
/* JavaScript code */
});
}}}
\
<h3>{{{:typingstart}}}</h3>\
This is a local event that will be triggered when the typing of a section stops.
You can include any JavaScript code inside the following container:
{{{
$(document).on(':typingstart', function (ev) {
/* JavaScript code */
});
}}}
\
<h3>{{{:typingcomplete}}}</h3>\
This is a global event that will be triggered all the {{{<<type>>}}} macros within a passage have been completed.
You can include any JavaScript code inside the following container:
{{{
$(document).on(':typingcomplete', function (ev) {
/* JavaScript code */
});
}}}
<div id="link-menu">[[Back to the Events Menu|Events]] - [[Back to the Start Menu|Start]]</div><h1>Harness the Power of Functions</h1>
Functions are JavaScript blocks of code designed to do a specific task, from importing outside scripts, to save information, or setting variables. While some of the functions explained in this chapter can be used in any passage in combination with SugarCube macros, some should be restricted to the JavaScript passage only.
* [[Cloning Variables, and Random Values Functions|Function-Clone-Random]]
* [[Using Play, Passage, and Tags information|Function-Pass-Tag]]
* [[Memorizing Information and Metadata|Function-Metadata]]
* [[JavaScript-only Functions|Function-JS]]
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>Cloning Variables, and Random Values Functions</h1>
SugarCube has a handful of functions to set variables, from cloning objects to randomising a value.
\
<h3>The {{{clone()}}} function</h3>\
Unlike simple variables or arrays, copying an object in another variable will not just copy the current value of the orginal variable but any future changes to that original variable. Assuming that {{{$object = {turn : 1} }}}:
{{{
<<set $var to $object>>
<<set $object.turn to 6>>
→ $object.turn = 6
→ $var.turn = 6
}}}
This is where the {{{clone()}}} function comes in. The function will clone the values of an object, but not any future change.
{{{
<<set $var to clone($object)>>
<<set $object.turn to 6>>
→ $object.turn = 6
→ $var.turn = 1
}}}
\
<h3>Random Values Functions</h3>\
To randomise a value, there are two main functions: {{{either()}}} for strings and arrays, and {{{random()}}}/{{{randomFloat()}}} for integer. Both functions can be used in setting variables or simply printed on the page:
{{{
<<set $var to either('Blueberries', 'Cherries', 'Peaches')>>
→ this will set $var with one of the listed values
<<print random(5)>>
→ this will print on the page a number between 0 and 5 (incl)
<<set _temp to randomFloat(0.0, 5.0)>>
→ this will set _temp a number between 0.0 and 4.99999...
}}}
Instead of listing values, other variables can be used inside the functions. Assuming that {{{_min = 0}}}, {{{_max = 0}}}, {{{_array = ["Apple", "Chocolate"]}}}, {{{_array2 = [1, 2]}}}:
{{{
<<set
$var to either(_array),
$var2 to either(_array, _array2),
$var3 to either(_array, "Peaches"),
$var4 to random(_max),
$var5 to random(_min, _max)
>>
}}}
<div id="link-menu">[[Back to the Functions Menu|Functions]] - [[Back to the Start Menu|Start]]</div><h1>Using Play, Passage, and Tags information</h1>
SugarCube functions can also track where players have (or have not) been, or how many times they have visited a certain passage. These can be useful to show variation in the next, whether certain links appear in a menu, or changing the content of the Header/Footer depending on a location.
\
<h3>Using the {{{tags()}}} and {{{visitedTags()}}} functions</h3>\
To track where the player is or has been based on the tags coded on the passages, we can use respectively the {{{tags()}}} and {{{visitedTags()}}} functions. This is quite useful when trying to target a group of passages rather than a handful of them (and having to list those).
{{{tags()}}} should mainly be used in Special Passages, widgets, or JavaScript code outside of the passage, as it contains the list of tags of the current passage. As passages may have multiple tags, it should be treated as if they were an array variable.
{{{
Example of use:
: :PassageHeader
<<if tags().includes('forest')>>The Dark Forest
<<elseif tags().includes('town')>>The Lovely Town
<<elseif tags().includes('tavern')>>The Thick Table Tavern :P
<</if>>
Display tags:
<<print tags()>>
Set as a value:
<<set $var to tags()>>
}}}
{{{visitedTags()}}} will save all the different tags attached to the previously visited passages, and should be mainly be used in conditional statements:
{{{
<<if visitedTags("forest")>>…</if>>
→ has visited at least one passage tagged 'forest'
<<if visitedTags("forest", "haunted") is 1>>…<</if>>
→ has visited a passage tagged with both 'forest' and 'haunted' exactly once
<<if visitedTags("forest", "burned") gt 3>>…<</if>>
→ has visited a passage tagged with both 'forest' and 'burned' more than three times
}}}
> Note: this functions works similarly to the {{{visited()}}} one. As such, when using more strict conditional statements, as players may unknowingly visit a passage more than once (see {{{<<return>>}}} [[macro|Macro-Back-Return]] or the [[Arbitrarily Long Return|Long-Return-JS]]).
\
<h3>Using the Passage-related functions</h3>\
One can track where the player is or has been based on the passages' name. Aside from {{{passage()}}}, all other functions deal with past events, with {{{visited()}}} and {{{lastVisited()}}} handling both current and past events.
{{{passage()}}} will look at the current passage. It can be used both in conditional statements, setting variables, or reloading a page:
{{{
<<if passage() is "Forest">>...<</if>>
<<set $var to passage()>>
<<link "Reload" `passage()`>><</link>>
}}}
> Note: while it is possible to reload as passage with {{{passage()}}}, this is not recommended, as issues may arise from reloading one passage too many times. If used, it should be done so parsimoniously.
{{{previous()}}} will log the most recent previous passage. It will be most useful in conditional statements or links:
{{{
<<if previous() is "Forest">>...<</if>>
<<link "Go Back" `previous()`>><</link>>
}}}
> Note: using {{{previous()}}} in a link will be the same as using the {{{<<back>>}}} [[macro|Macro-Back-Return]]. It is best to use {{{<<replace '.passage'>><<include `passage()`>><</replace>>}}} instead.
{{{visited()}}} will look at the amount of time a passage has been visited, and is mainly used in conditional statements. When landing on a passage, the {{{visited()}}} counter will increase by 1. The following examples will check if:
{{{
<<if visited() is 2>>...<</if>>
→ this is currently the second visit on this passage
<<if visited('Tavern')>>...<</if>>
→ the player has visited the passage "Tavern" at least once
<<if visited('Tavern') is 2>>...<</if>>
→ the player has visited the passage "Tavern" exactly two times
<<if visited('Tavern', 'Forest')>>...<</if>>
→ the player has visited the passages "Tavern" and "Forest" at least once
}}}
> Note: when using more strict conditional statements, as players may unknowingly visit a passage more than once (see {{{<<return>>}}} [[macro|Macro-Back-Return]] or the [[Arbitrarily Long Return|Long-Return-JS]]).
{{{lastVisited()}}} works similarly to the {{{previous()}}} function, though it will look at the length of turns between the current passage and the one in question. The following examples will check if:
{{{
<<if lastVisited('Tavern') is 0>>...<</if>>
→ the player is currently in the passage "Tavern"
<<if lastVisited('Tavern') is -1>>...<</if>>
→ the player has not yet visited the passage " Tavern"
<<if lastVisited('Tavern') is 1>>...<</if>>
→ the previous passage visited by the player is "Tavern"
<<if lastVisited('Tavern', 'Forest') is 2>>...<</if>>
→ the player has visited both the "Tavern" and "Forest" passage, most recently 2 turns ago
}}}
> Note: the {{{lastVisited()}}} function will look at all passages visited in the order they were visited, no matter whether those passages are not part of the story (i.e. Codex). To avoid seeing those passages in the history, consider avoiding using the {{{<<return>>}}} [[macro|Macro-Back-Return]] or a regular link with the the [[Arbitrarily Long Return|Long-Return-JS]], favouring the {{{<<back>>}}} [[macro|Macro-Back-Return]] instead.
{{{hasVisited()}}} will only check if a passage has been visited or not. The following examples will check if:
{{{
<<if hasVisited('Tavern')>>...<</if>>
→ the player has visited the passage 'Tavern'
<<if not hasVisited('Tavern')>>...<</if>>
→ the player has not yet visited the passage 'Tavern'
<<if hasVisited('Tavern', 'Forest')>>...<</if>>
→ the player has visited BOTH the passages 'Tavern' and 'Forest'
<<if not hasVisited('Tavern', 'Forest')>>...<</if>>
→ the player has not visited 'Tavern', or not visited 'Forest', or not visited both
}}}
\
<h3>Other Play Functions</h3>\
{{{turns()}}} will look at the amount of turns a player has taken since the start of the playthrough. It will count all passages visited as a singular path (including starting menus). As such, rewound/undone actions are not counted. It can be used to display said count on the page, in conditional statements, or saved in a variable.
{{{
<<= turns()>>
→ will print the number of turns
<<print "Turn #" + turns()>>
→ will print the number of turns, with some extra text
<<if turns() gt 5>>...<</if>>
<<set $var to turns()>>
}}}
{{{time()}}} will look at the time spent in the current passage, in milliseconds. It can be useful in forcing the player to do quick decisions, or track how long a player goes through a section.
{{{
<<set $time += time()>>
<<if time() lt 5000>>...<</if>>
→ if the time spent on the passage is less than 5 seconds.
<<link "Run Away!">>
<<if time() lt 5000>>
<<goto "Escaped">>
<<else>>
<<goto "Caught">>
<</if>>
<</link>>
}}}
<div id="link-menu">[[Back to the Functions Menu|Functions]] - [[Back to the Start Menu|Start]]</div><h1>Memorizing Information and Metadata</h1>
Aside form the Built-In Saves, SugarCube has another way of saving information, in the story metadata. While it ''is not and should not'' replace saves, the following functions can be useful for tracking achievements or statistics, or having a New Game+ feature.
> Note: this //will not work with private browsing//, and may affect how the game progresses.
{{{
memorize() → save information
recall() → bring up information
forget() → delete information
}}}
The functions will need the {{{<<run>>}}} macro to be used and is set as follow:
* the function
* the name of the information to save/edit/delete, as a string
* the value of the information, can be a boolean, string or integer
{{{
<<run function('name': value)>>
}}}
{{{
<<run memorize('achievement1': true)>>
<<run forget('achievement1')>>
}}}
The {{{recall}}} function can also be used in conditional statements and saving the information in variables:
{{{
<<if recall('achievement') is true>>
You already achieved this.
<</if>>
<<set $variable to recall('achievement')>>
}}}
<div id="link-menu">[[Back to the Functions Menu|Functions]] - [[Back to the Start Menu|Start]]</div><h1>JavaScript-only Functions</h1>
The functions below can only be used in the JavaScript tab or inside a {{{<<script>>}}} macro.
\
<h3>Importing outside code</h3>\
SugarCube functions allows for importing JavaScript and CSS from outside sources, to use in a project:
{{{
To import JavaScript:
importScripts(URL)
To import CSS:
importStyles(URL)
}}}
You can import multiple scripts or styles in one import:
{{{
importScripts(
"https://somesite/a/path/a.js",
"https://somesite/a/path/b.js",
"https://somesite/a/path/c.js",
"https://somesite/a/path/d.js"
);
importStyles([
"https://somesite/a/path/a.css",
"https://somesite/a/path/b.css",
"https://somesite/a/path/c.css",
"https://somesite/a/path/d.css"
]);
}}}
> Note: the use of {{{[ ]}}} brackets will determine whether the sheets should be loaded one after the other or not.
\
<h3>Calling SugarCube variables in JS code</h3>\
Sometimes, your JavaScript code will need a variable set in SugarCube to run. This is where {{{temporary()}}} and {{{variables()}}} come in.
> Note: knowledge of JavaScript is required.
{{{
temporary().test → _test
variables().colour → $colour
}}}
> Note: those functions are equivalent to {{{State.temporary}}} and {{{State.variables}}}
{{{
if (variables().hasGoldenKey) {
temporary().unlock = true
}
→ if the variable $hasGoldenKey is true, the code will change the value of _unlock to true
}}}
<div id="link-menu">[[Back to the Functions Menu|Functions]] - [[Back to the Start Menu|Start]]</div><h1>Adding some Interactivity</h1>
To make your project a bit more interactive, SugarCube has multiple macros to help add some gameplay elements that is not just clicking a list of links. These can be useful for character creation, creating puzzles, or even in a combat system!
* [[Multi or Single Option Choices|Macro-CheckRadio]]
* [[Cycles and Conditional Options|Macro-Cycle]]
* [[Revealing Extra Text and Disappearing Links|Macro-Link-AppPreRep]]
* [[Listboxes and Conditional Options|Macro-Listbox]]
* [[Player Input in three macros|Macro-Input]]
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>Multi or Single Option Choices</h1>
A different way to display choice options, aside from links, is to use the {{{<<checkbox>>}}} and {{{<<radiobutton>>}}} macros. The first allows the player to choose multiple options from a list, while the second only allows one choice. These macros are great for MC customisation.
\
<h3>{{{<<checkbox>>}}}</h3>\
The {{{<<checkbox>>}}} creates a visual checkbox, which will modify the value of a variable, depending on whether the box is checked or not.
<<checkbox "_pieBlueberry" false true>> I've read the warnings...
This macro has 5 arguments:
* the variable saving the player's choice
* the value to give the variable when the checkbox is //unchecked//
* the value to give the variable when the checkbox is //checked//
* {{{autocheck}}} (optional) whether the checkbox should match the state of the named variable
* {{{checked}}} (optional) whether the checkbox should be checked from the start
{{{
<<checkbox "_example" false true autocheck>> Displayed Text
<<checkbox "_object.property" 1 0 autocheck>> Displayed Text
<<checkbox "_array[0]" "Tim" "Tom" autocheck checked>> Displayed Text
}}}
> Note: the variable should either be different for each option, be a different array position or a different object property. Otherwise, the last choice will override everything.
\
<h3>{{{<<radiobutton>>}}}</h3>\
The {{{<<radiobutton>>}}} creates a visual radio button, which will modify the value of a variable. You can use multiple of these linked to one variable to create a group.
<<radiobutton "_pieBlueberry" false>> I've read the warnings...
This macro has 4 arguments:
* the variable saving the player's choice
* the value to give the variable when the option is //checked//
* {{{autocheck}}} (optional) whether the radiobutton should match the state of the named variable
* {{{checked}}} (optional) whether the option should be checked from the start (only for one per group)
{{{
<<radiobutton "_exmaple" false>> Displayed Text
<<radiobutton "_object.property" 1>> Displayed Text
<<radiobutton "_array[0]" "Tim" checked>> Displayed Text
A radiobutton group:
<<radiobutton "$pie" "blueberry" checked>> Blueberry?
<<radiobutton "$pie" "cherry">> Cherry?
<<radiobutton "$pie" "coconut cream">> Coconut cream?
}}}
\
<h3>Using a {{{<label>}}}</h3>\
For accessiblity reasons, it is recommended to wrap each option of the macros above with the HTML markup {{{<label>}}}. This way, instead of trying to click on the small checkbox or radiobutton, you can click on the displayed text to trigger the macro.
{{{
<label><<checkbox "_example" false true autocheck>> Displayed Text</label>
<label><<radiobutton "_exmaple" false>> Displayed Text</label>
}}}
<label><<checkbox "_example" false true autocheck>> Displayed Text</label>
<label><<radiobutton "_exmaple" false>> Displayed Text</label>
<div id="link-menu">[[Back to the Interactive Macro Menu|Macro-Interact]] - [[Back to the Start Menu|Start]]</div><h1>Revealing Extra Text and Disappearing Links</h1>
Instead of moving to another passage to continue the story or add extra flavour text, SugarCube has three link macros with a twist: {{{<<linkappend>>}}}, {{{<<linkprepend>>}}} and {{{<<linkreplace>>}}}. Like their names suggest, the first adds text after the link, the second adds text before the link, and the third replaces the link with a new text.
The three container macros have each 2 arguments:
* the text to display in the link
* (optional) whether to show the new text with a transition : {{{t8n}}} or {{{transition}}}
\
<h3>{{{<<linkappend>>}}}</h3>\
This macro is essentially a combination of {{{<<link>>}}} and {{{<<append>>}}}, by creating a one-time use link that deactivate itself and add the content inside the container after that link when clicked.
{{{
<<linkappend "text in link" t8n>>text to appear after the link<</linkappend>>
<<linkappend "text in link" t8n>>/* Code */<</linkappend>>
}}}
Ex: I ate a <<linkappend "cookie" t8n>>, which was filled with chocolate<</linkappend>>.
\
<h3>{{{<<linkprepend>>}}}</h3>\
This macro is essentially a combination of {{{<<link>>}}} and {{{<<prepend>>}}}, by creating a one-time use link that deactivate itself and add the content inside the container before that link when clicked.
{{{
<<linkprepend "text in link" t8n>>text to appear before the link<</linkprepend>>
<<linkprepend "text in link" t8n>>/* Code */<</linkprepend>>
}}}
Ex: I ate a <<linkprepend "cookie" t8n>>delicious <</linkprepend>>.
\
<h3>{{{<<linkreplace>>}}}</h3>\
This macro is essentially a combination of {{{<<link>>}}} and {{{<<replace>>}}}, by creating a one-time use link that replaces itself with the content inside the container when clicked.
{{{
<<linkreplace "text in link" t8n>>text to appear before the link<</linkreplace>>
<<linkreplace "text in link" t8n>>/* Code */<</linkreplace>>
}}}
Ex: I ate a <<linkreplace "cookie" t8n>>slice of pie<</linkreplace>>.
> Note: if you are looking for more flexibility in the placement of the link and/or the appearance of the added text, you may want to use their respective [[DOM macros|Macro-ApPreRepCopy]].
<div id="link-menu">[[Back to the Interactive Macro Menu|Macro-Interact]] - [[Back to the Start Menu|Start]]</div><h1>Cycles and Conditional Options</h1>
Cycles can be a fun way to have the player interact with the story, and give a different way to format choices or display different variations. The {{{<<cycle>>}}} can be useful to lists MC characteristics options, or environmental observations.
I looked at her and she <<cycle "_example">>
<<option "seemed fine">>
<<option "was distraught">>
<<option "was in tears">>
<<option "smiled">>
<</cycle>>.
The macro has two sets of arguments: one for the container {{{<<cycle>>}}} and one set for the {{{<<option>>}}}/{{{<<optionfrom>>}}}.
* {{{<<cycle>>}}}:
** the variable to save the player's choice.
** {{{once}}} (optional) whether the cycle stops at the last option
** {{{autoselect}}} (optional): will autoselect the option from the list, if the value of the variable is included in the list of options (listed with {{{<<option>>}}})
* {{{<<option>>}}}
** the name of the option.
** (optional) the value of the option (if different from the name).
* {{{<<optionfrom>>}}}:
** the variable containing the list of options (array or object).
Assuming that the array {{{_pieOptions = ["blueberry", "cherry", "coconut cream"]}}}:
{{{
<<cycle "_example" autoselect>>
<<option "seemed fine" false>>
<<option "was distraught">>
<<option "was in tears" 0>>
<<option "smiled" "bad">>
<</cycle>>
→ this cycle is the same as shown above, aside from most options having different values from their labels.
<<cycle "$pie" once autoselect>>
<<optionsfrom _pieOptions>>
<</cycle>>
→ this cycle will display the options from the array _pieOptions, and will stop when reaching the end.
}}}
\
<h3>Why {{{<<optionfrom>>}}} instead of {{{<<option>>}}}?</h3>\
Choosing {{{<<option>>}}} or {{{<<optionfrom>>}}} will depend on whether the options to choose from are known in advance or whether they depend on a certain condition. Since {{{<<cycle>>}}} is a container, you cannot include another macro inside. It will only accept those two options. This means you cannot add or remove options within the cyclce code (ex: wrapping an option with {{{<<if>>}}} would not remove that option).
If the list of options is already set, {{{<<option>>}}} is the easiest way to go. If the list's content has conditional options, then {{{<<optionfrom>>}}} is the solution.
> Note: You can also have different {{{<<cycle>>}}}/{{{<<option>>}}} combo for each situation...
Even within {{{<<optionfrom>>}}}, you have two options: using an array or an object. The first is the simplest if the displayed options would be the final value, while the latter would work best if the displayed option is linked to a different value. For example:
{{{
_pieOptions = ["blueberry", "cherry", "coconut cream"]
_pieOptions = { "Blueberry" : "1", "Cherry" : "2", "Coconut cream" : "3" }
}}}
<<set _pieOptions = ["blueberry", "cherry", "coconut cream"], _pieOptions2 = { "Blueberry" : "1", "Cherry" : "2", "Coconut cream" : "3" }>>\
The array will show : <<cycle "_pie" autoselect>>
<<optionsfrom _pieOptions>>
<</cycle>> (value of the first option: _pie)
While the object will show: <<cycle "_pie2" autoselect>>
<<optionsfrom _pieOptions2>>
<</cycle>> (value of the first option: _pie2)
> Note on the cycle macro: this macro has some issues with accessiblity (screen readers). While this can be remedied with some [[extra code|Accessibility-Cycle]], this should be taken into account when creating a project.
<div id="link-menu">[[Back to the Interactive Macro Menu|Macro-Interact]] - [[Back to the Start Menu|Start]]</div><h1>Listboxes and Conditional Options</h1>
List boxes are an easy way to have the player interact with the story, and give a different way to format choices. The {{{<<listbox>>}}} can be useful to lists MC characteristics options, or choosing a location to go to.
Where to go next? <<listbox "_example">>
<<option "Home">>
<<option "Garden">>
<<option "Cinema">>
<<option "School">>
<</listbox>>
The macro has two sets of arguments: one for the container {{{<<listbox>>}}} and one set for the {{{<<option>>}}}/{{{<<optionfrom>>}}}.
* {{{<<listbox>>}}}:
** the variable to save the player's choice.
** {{{autoselect}}} (optional): will autoselect the option from the list, if the value of the variable is included in the list of options (listed with {{{<<option>>}}})
* {{{<<option>>}}}
** the name of the option.
** (optional) the value of the option (if different from the name).
* {{{<<optionfrom>>}}}:
** the variable containing the list of options (array or object).
Assuming that the array {{{_pieOptions = ["blueberry", "cherry", "coconut cream"]}}}:
{{{
<<listbox "_example" autoselect>>
<<option "Home" false>>
<<option "Garden">>
<<option "Cinema" 0>>
<<option "School" "bad">>
<</listbox>>
→ this list is the same as shown above, aside from most options having different values from their labels.
<<listbox "$pie" autoselect>>
<<optionsfrom _pieOptions>>
<</listbox>>
→ this list will display the options from the array _pieOptions.
}}}
\
<h3>Why {{{<<optionfrom>>}}} instead of {{{<<option>>}}}?</h3>\
Choosing {{{<<option>>}}} or {{{<<optionfrom>>}}} will depend on whether the options to choose from are known in advance or whether they depend on a certain condition. Since {{{<<listbox>>}}} is a container, you cannot include another macro inside. It will only accept those two options. This means you cannot add or remove options within the list box code (ex: wrapping an option with {{{<<if>>}}} would not remove that option).
If the list of options is already set, {{{<<option>>}}} is the easiest way to go. If the list's content has conditional options, then {{{<<optionfrom>>}}} is the solution.
> Note: You can also have different {{{<<listbox>>}}}/{{{<<option>>}}} combo for each situation...
Even within {{{<<optionfrom>>}}}, you have two options: using an array or an object. The first is the simplest if the displayed options would be the final value, while the latter would work best if the displayed option is linked to a different value. For example:
{{{
_pieOptions = ["blueberry", "cherry", "coconut cream"]
_pieOptions = { "Blueberry" : "1", "Cherry" : "2", "Coconut cream" : "3" }
}}}
<<set _pieOptions = ["blueberry", "cherry", "coconut cream"], _pieOptions2 = { "Blueberry" : "1", "Cherry" : "2", "Coconut cream" : "3" }>>\
The array will show : <<listbox "_pie" autoselect>>
<<optionsfrom _pieOptions>>
<</listbox>> (value of the first option: _pie)
While the object will show: <<listbox "_pie2" autoselect>>
<<optionsfrom _pieOptions2>>
<</listbox>> (value of the first option: _pie2)
<div id="link-menu">[[Back to the Interactive Macro Menu|Macro-Interact]] - [[Back to the Start Menu|Start]]</div><h1>Player Input in three macros</h1>
SugarCube offers three variations of input boxes: the {{{<<textbox>>}}}, the {{{<<textarea>>}}}, and the {{{<<numberbox>>}}}.
<h3>The {{{<<textbox>>}}} macro</h3>\
The textbox allows the player to indicate a string of words. This can be useful for short and simple inputs, like a name.
<<textbox "_wager" "Jane">>
The macro has four arguments:
* the variable to save the player input (must be wrapped in quotes)
* the default text visible to the player
* {{{"PassageName"}}} (optional) whether the player will be sent to another passage when presseing //Enter//
* {{{autofocus}}} (optional) whether the area is automatically in focus
{{{
<<textbox "$variable" "Default Text" "NextPassage" autofocus>>
→ this will be in focus, showing "Default Text", with the final value saved in $variable, and the player sent to "NextPassage" when pressing Enter.
<<textbox "$variable" "">>
→ this will not be in focus, showing 0 as the default value, and saving the input in $variable.
}}}
> Note: if you need to check the value of the textbox before the player moves to another passage, I would not recommend indicating a passage in the macro, but use a separate button/link.
\
<h3>The {{{<<numberbox>>}}} macro</h3>\
The macro works similarly to the {{{<<textbox>>}}}, aside from saving the input as an integer instead of a string.
<<numberbox "_wager" 100>>
The macro has four arguments:
* the variable to save the player input (must be wrapped in quotes)
* the default number visible to the player
* {{{PassageName}}} (optional) whether the player will be sent to another passage when presseing //Enter//
* {{{autofocus}}} (optional) whether the area is automatically in focus
{{{
<<numberbox "$variable" 10 "NextPassage" autofocus>>
→ this will be in focus, showing the number 10, with the final value saved in $variable, and the player sent to "NextPassage" when pressing Enter.
<<numberbox "$variable" "">>
→ this will not be in focus, showing 0 as the default value, and saving the input in $variable.
}}}
> Note: while the macro does not have min or max value, [[the Numberpool custom macro|http://www.motoslave.net/sugarcube/2/#downloads]] does.
> Note 2: if you need to check the value of the numberbox before the player moves to another passage, I would not recommend indicating a passage in the macro, but use a separate button/link.
\
<h3>The {{{<<textarea>>}}} macro</h3>\
This macro creates a multi-line area for the player to input text, and saves this input in a variable. This is a good interactive macro to save longer bits of text, like journal entries.
<<textarea "_example" "This is an example of a text area.">>
The macro has three arguments:
* the variable to save the player input (must be wrapped in quotes)
* the default text visible to the player
* {{{autofocus}}} (optional) whether the area is automatically in focus
{{{
<<textarea "$variable" "Visible Text" autofocus>>
→ this will be in focus and the player will see "Visible Text" in the box, and the player input will be saved in $variable
<<textarea "$variable" "">>
→ this will not be in focus, and will not show any text, but the final input will be saved in $variable
}}}
> Note on autofocus: As of SugarCube 2.36.1, the autofocus function has some issues when: it is located outside of a passage, the passage with those macros is the first one loaded (also during page refresh), more than one macros on the page has autofocus on.
<div id="link-menu">[[Back to the Interactive Macro Menu|Macro-Interact]] - [[Back to the Start Menu|Start]]</div><h1>More Interactivity Macros</h1>
Aside from the [[Base Interactive Macros|Macro-Interact]], there are a handful that can help make the game more interactive or have more flexibility in said interactivity.
* [[DOM Macros and Revealing Text in Targeted Spots|Macro-ApPreRepCopy]]
* [[Single-Use Choice Lists|Macro-Action-Choice]]
* [[Delaying Displaying Text or Running Code|Macro-Timed]]
* [[Displaying Text Letter by Letter|Macro-Type]]
* [[Using Custom Macro|Custom-Macro]]
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>DOM Macros and Revealing Text in Targeted Spots</h1>
DOM (Document Object Model) Macros target HTML elements on a page and affect what content it displays on the page. Those macros have the same functionality as the {{{<<link[insert-DOM]>>}}} [[macros|Macro-Link-AppPreRep]], but have more flexibility and do not require a link to work.
There are four main macros and one extra:
* {{{<<append>>}}}, which will add content after the targeted element.
* {{{<<prepend>>}}}, which will add content before the targeted element.
* {{{<<replace>>}}}, which will replace the content of the targeted element.
* {{{<<remove>>}}}, which will remove the targeted element.
* {{{<<copy>>}}}, which will copy the content of the targeted element.
The macros have 1 argument:
* the element to target, which can be an {{{#id}}}, a {{{.class}}} or an HTML {{{element}}}, or a combination.
> Note: if you are targeting an element that is on the page multiple time, the macro will affect all these elements.
{{{
<<append "#chocolate">>
This text will append the element with the ID "chocolate"
<</append>>
<<prepend h1>>
This text will prepend every h1 element
<</prepend>>
<<replace ".dog">>
This text will replace the element with the Class "dog"
<</replace>>
<<remove p.test>> <- will remove the element of <p class="test">
<<copy span#sweet>> <- will copy the content of the element <span id="sweet">
}}}
> Note: if the element you are trying to target is //not// on the page, you will get an error.
> Note 2: if you want to empty an element, it is best to use an empty {{{<<replace>>}}} than a {{{<<remove>>}}}.
Those macros are best used with other interactive elements, like {{{<<link>>}}}, {{{<<button>>}}}, or even {{{<<timed>>}}}.
<span id="dog">The dog is barking</span>.
<<link "Throw a ball">><<append "#dog">> at the ball<</append>><</link>>
{{{
Code:
<span id="dog">The dog is barking</span>.
<<link "Throw a ball">><<apprend "#dog">> at the ball<</append>><</link>>
}}}
Other examples:
{{{
Replacing a list of links with more text:
<span id="choices">
<<link "Go Home">>
<<replace "#choices">>
You went home. Nothing much happened.
[[Next|Next Day]]
<</replace>>
<</link>>
<<link "Go to the Cinema">>
<<replace "#choices">>
You went to the Cinema, and met Charlie after the movie ended.
[[Next|Convo Charlie]]
<</replace>>
<</link>>
</span>
Copying and Pasting:
This is a <span class="one">terrible</span> idea!
Well, I think this is <span class="two">a grand idea!</span>
<<link "Or is it?">>
<<replace ".two">>actuall a <<copy ".one">> as well...<</replace>>
<</link>>
}}}
\
<h3>An important note on DOM Macros</h3>\
Since the macros require the targetted element to be on the page, they ''cannot'' be coded as is on the page, due to how the [[page renders|SP-PassageReady-Done]]. As such, you will need either to:
* use the {{{<<link>>}}} or {{{<<button>>}}} macro, letting the player interact with the element,
* use the {{{<<done>>}}} macro, which will trigger when the page is fully rendered,
* code it in the {{{PassageDone}}} special passage (same as the {{{<<done>>}}} macro, but will trigger at every passage render).
<div id="link-menu">[[Back to the Advanced interactive Macro Menu|Macro-Interact-Adv]] - [[Back to the Start Menu|Start]]</div><h1>Single-Use Choice Lists</h1>
SugarCube has two macros that will automatically create lists of links, which will disappear when used: the {{{<<actions>>}}} and the {{{<<choice>>}}} one.
<<actions [[You won't be able to go there|LOL]] [[This one also doesn't work|LOL]] [[But here is a list of actions|LOL]]>>
Both macros are coded and formatted similarly, but work slightly differently: {{{actions}}} will only remove the links where the passages have already been visited by the player, while {{{choice}}} will deactivate all listed links when one of them is clicked.
The macros have only 1 argument:
* the passage(s) you want listed
{{{
Indicating the passages names only:
<<actions "Home" "Garden" "Cinema">>
→ this will list the passages as links
Using the link Markup:
<<choice [[Go Home|Home]] [[Go to the Garden|Garden]] [[Go to the Cinema|Cinema]]>>
Using the image Markup:
<<actions [img[URL][PassageName]]>>
}}}
> Note: Both macros are quite limiting if the player should go back to the passage and has visited all listed options, or if the code is more complex than a simple link. In those cases, it might be best to code the list manually with the list markup and some conditional statements.
<div id="link-menu">[[Back to the Advanced interactive Macro Menu|Macro-Interact-Adv]] - [[Back to the Start Menu|Start]]</div><h1>Delaying Displaying Text or Running Code</h1>
When displaying text or triggering code should not happen as soon as the passage is loaded, the {{{<<timed>>}}} macro should come into play. As its name suggests, the macro will trigger a timer before releasing the code/text.
<<timed 5s>>Whoop, there it is!<</timed>>
The macro has 2 arguments for its container, and 1 for the submacro:
* {{{<<timed>>}}}:
** the delay before the macro triggers, can be indicated in seconds or milliseconds.
*** the minumum delay is 40ms.
** {{{t8n}}}/{{{transition}}}, whether the text appearing does so like the transition between passages.
* {{{<<next>>}}}:
** the delay before the next part of the macro triggers, can be indicated in seconds or milliseconds.
*** the minumum delay is 40ms.
*** if not indicated, it will take the delay from the {{{<<timed>>}}} macro.
{{{
<<timed 2s t8b>>
This will appear with a transition after 2 seconds.
<<next>>
And this will appear 2 seconds after the previous text.
<<next 4s>>
While this will appear 4 seconds after the previous block.
<</timed>>
}}}
You can use the {{{<<timed>>}}} macro for other uses:
{{{
Like sending the player to another passage:
<<timed 10s>><<goto "END">><</timed>>
Or replacing some text on the page:
Can I by some <span id="text">eggs</span>?
<<timed 2s>><<replace "#text">>milk<</replace>><</timed>>
}}}
> Note: When using this macro, it is important to test the passage extensively, to ensure it works as intended.
<div id="link-menu">[[Back to the Advanced interactive Macro Menu|Macro-Interact-Adv]] - [[Back to the Start Menu|Start]]</div><h1>Displaying Text Letter by Letter</h1>
Whether wanting to emulate a computer monitor or a typewriter, by displaying a text letter by letter, the {{{<<type>>}}} macro will do the job!
<<type 80ms>>Here is the macro in action! It can also do [[links|Macro-Type]] and ''formatting''...<</type>>
You can have multiple {{{<<type>>}}} on one passage, but they will start one after the other, rather than at the same time. If you nest a {{{<<type>>}}} inside another, the nested {{{<<type>>}}} will start after all the other non-nested ones have ended.
The macro has 8 arguments:
* speed: the amount of time between each letter, can be indicated in seconds or milliseconds.
** 20-60ms is a good printing rate. 0s will show the whole text with a flash.
* {{{start}}} (optional): adding a delay before the typing starts, indicated in seconds or milliseconds
** if only {{{start}}} is indicated, the default will be 400ms.
* {{{class}}} (optional): will assign an extra CSS {{{.class}}} to the typing container.
* {{{id}}} (optional): will assign a CSS {{{#id}}} to the typing container.
* {{{element}}} (optional): will transform the container from a {{{<div>}}} to another HTML element.
* {{{keep}}} (optional): will keep the cursor even after the typing is complete.
* {{{none}}} (optional): will not use the cursor during typing.
* {{{skipkey}}} (optional): when the key is pressed, the typing will display the whole text immediately.
** If only {{{skipkey}}}, the default value must be indicated with [[Config.macros.typeSkipKey]].
{{{
<<type 40ms>>I ate an apple.<</type>>
→ The base required, with characters showing every 40 milliseconds.
<<type 40ms start 2s none>>Oh no, I'm late...<</type>>
→ After a 2-second delay, this will show characters every 40 milliseconds, without the cursor.
<<type 40ms class "menu">>[[Start Now!]]<</type>>
→ This will type the characters of the link every 40 milliseconds, and add the class '.menu' to the container.
<<type 40ms element "span" keep>>Now I'm a span!<</type>>
→ Instead of the base container, this will be a '<span>'. When all text is displayed, the cursor will stay on the page.
<<type 40ms id "words" skipkey "Enter">>Last one!<</type>>
→ This will type the characters every 40 milliseconds, unless the key 'Enter' is pressed to display everything at once. The container will also get the id '#words' added to it.
}}}
> Note: Because the macro is time dependant, it is important to test the passages extensively, to ensure it workds as intended.
\
<h3>Customising the typed text with CSS</h3>\
While the typed text has not default styling, the macro has special classes you can target to edit it:
* {{{.macro-type}}}, to change the base styling of the macro
* {{{.macro-type-done}}}, to change the styling when the macro has printed all text
* {{{.macro-type-cursor:after}}}, to edit the cursor
{{{
.macro-type {
color: limegreen;
font-family: monospace, monospace;
}
.macro-type-cursor:after {
color: limegreen;
content: "\269C\FE0F"; /* Fleur-de-lis emoji */
font-family: monospace, monospace;
}
}}}
<div id="link-menu">[[Back to the Advanced interactive Macro Menu|Macro-Interact-Adv]] - [[Back to the Start Menu|Start]]</div><h1>Using Custom Macro</h1>
There are many macros created by other SugarCube users available, from the [[add-ons|http://www.motoslave.net/sugarcube/2/]] on the SugarCube page, or in the macro creator's code repository (many are available on GitHub, as [[listed here|https://manonamora-if.tumblr.com/post/700577877042888704/]]).
These macros will require you to include special bits of code in the JavaScript tab, the StyleSheet one, or in a Widget Passage, before using them. Not "installing" the code before using the macro will show errors on the page. Almost always, these macros will have their own documentation, explaining how to use them.
> Note: when using multiple macros, it is important to check no two macros have the same name. Otherwise, it will create issues when loading the game.
\
<h3>Creating your own Macro</h3>\
If you have enough JavaScript/jQuery knowledge, and understand how SugarCube works, but need a custom macro for your project, which cannot be done through a [[widget|Macro-Widget]] or with the {{{<<script>>}}} [[macro|Macro-Script-Run]], you could attempt to create your own Macro.
To do so, you will need to use the [[Macro API|http://www.motoslave.net/sugarcube/2/docs/#macro-api]] and a name that ''cannot'' be the same as the Base Sugarcube macros..
> Note: this option is for very advanced users. Many game fuctionalities do not require a custom macro, or may already have been created by someone else. See [[here|https://manonamora-if.tumblr.com/post/700577877042888704/interactive-fiction-twine-resource-megalist]] for a non-exhaustive list of custom macro creators.
<div id="link-menu">[[Back to the Advanced interactive Macro Menu|Macro-Interact-Adv]] - [[Back to the Start Menu|Start]]</div><h1>Edit the Built-In Text or Change the Game's Language</h1>
Further customisation of a SugarCube project can be done with the l10nStrings, bits of JavaScript code that will change what text the Built-In elements will show. This can affect the buttons on the Sidebar, as well as the Restart, Saves, and Settings Popup. You can edit these strings to fit the vibe of your project, change its language entirely, or link them to a function to provide translation of your work.
* [[l10nStrings, and How to Edit Them|Local-L10n]]
* [[Localization, and Pre-Translated Templates|Local-Trans]]
* [[Providing Multiple Languages In-Game|Local-Setting]]
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>{{{l10nStrings}}}, and How to Edit Them</h1>
{{{l10nStrings}}} are strings of words which can only be edited in JavaScript. These strings populate your project pages in very specific spots, as defined by the property attached to it. Depending on the property chosen, it can affect visible text on the screen, text only visible when hovering over an element, text inside a browser alert, or when the game is in Debugging Mode (Test).
{{{
l10nStrings.property = "New Text"
}}}
For example:
{{{
l10nStrings.restartTitle = "Restart"
l10nStrings.restartTitle = "Are You Sure?"
}}}
> Note: any {{{l10nStrings}}} added to your JavaScript will override the built-in text. If multiple iteration of the same property is edited in your file, only the last one will be shown on the page.
You can find the whole list of accepted property in [[this page|https://github.com/tmedwards/sugarcube-2/blob/develop/locale/l10n-template.js]] of the SugarCube repository.
Just Copy-Paste the necessary lines into your JavaScript, and edit the text. The code will accept any [[Unicode Character and Symbols|https://en.wikipedia.org/wiki/List_of_Unicode_characters]] (testing for fonts advised).
> Note: If you remove an element in the UI, like the backward button, the related {{{l10nStrings.propery}}} (here {{{l10nStrings.uiBarBackward}}}) does not need to be included in your project.
You can also use the text of other properties inside an {{{l10nStrings}}} to avoid writing it multiple times, either by using the property itself ({{{l10nStrings.propery}}}) or creating a template ({{{l10nStrings._template}}}). For example, in the Built-In {{{l10nStrings}}}:
{{{
l10nStrings.identity = 'game';
l10nStrings._warningIntroLacking = 'Your browser either lacks or has disabled';
l10nStrings._warningOutroDegraded = ', so this {identity} is running in a degraded mode. You may be able to continue, however, some parts may not work properly.';
l10nStrings.warningNoWebStorage = '{_warningIntroLacking} the Web Storage API{_warningOutroDegraded}';
}}}
The three first {{{l10nStrings}}} (one a property, the two others templates) are used by the last string to create the following text:
> //Your browser either lacks or has disabled// the Web Storage API, //so this ''game'' is running in a degraded mode. You may be able to continue, however, some parts may not work properly.//
<div id="link-menu">[[Back to the Localization Menu|Localization]] - [[Back to the Start Menu|Start]]</div><h1>Localization, and Pre-Translated Templates</h1>
If your project is not in English and you want the Built-In text to reflect this, you will need to include and edit most of the [[l10nStrings|Local-L10n]] defined in the format's code. This can be done by Copy-Pasting into your JavaScript the code from [[this page|https://github.com/tmedwards/sugarcube-2/blob/develop/locale/l10n-template.js]] of the SugarCube repository, and edit the text.
> Note: you can forgo the first and last line of the code in that page (i.e. the {{{function()}}}).
There may be a faster way to translate this built-in text if your language is included in the following list:
{{{
Arabic (ar-EG)
Chinese (chs)
German (de)
Spanish (es-ES)/(es-UNKNOWN)
French (fr)
Italian (it-IT)
Dutch (nl)
Polish (pl)
Portuguese (pt-BR)/(pt-PT)
Russian (ru)
Turk (tr)
}}}
These languages already have a Localization package, downloadable on the [[SugarCube website|http://www.motoslave.net/sugarcube/2/#downloads]], that you can Copy-Paste without needing to translate.
> Note: you //may// want to check the translated version fits with your project, or whether some edits may be required.
If your language (or its regional version) is unfortunately not included in the list above, you will need to edit every {{{l10nStrings}}} manually.
> Note: You may also want to provide this translation to TME, so it may be included in this list for future users. This can be done by forking the GitHub repository, edit [[this folder|https://github.com/tmedwards/sugarcube-2/tree/master/locale]] to include your translation, and open a pull request.
<div id="link-menu">[[Back to the Localization Menu|Localization]] - [[Back to the Start Menu|Start]]</div><h1>Providing Multiple Languages In-Game</h1>
If you want to include more than one language to your project, how to code it will depend on the UI of your project (Base or Custom) and whether the functionalities in your game (i.e. Settings, Saves, ...) use the [[Built-In text|Local-L10n]]. It may be as simple as creating seperate passage paths per language after a starting screen with a list of available languages, to more complicated, like having a Setting the player can use to change the language at anytime.
\
<h3>No Built-In Text and Language Choice at Start</h3>\
In this first case (which can be attainable by removing the Sidebar or creating a Custom UI), an easy way to achieve including localization would be to start with a passage where the player can choose the language from a list of links, each of which would send the player to a path of passages for that specific language:
{{{
: : Start
THIS IS A GAME, REALLY...
[[English|EN-Passage]]
[[Français|FR-Passage]]
[[Español|ES-Passage]]
[[Nederlands|NL-Passage]]
: : EN-Passage
This passage is English.
[[Continue|EN-Next]]
: : FR-Passage
Ce Passage est en Français.
[[Continuer|FR-Next]]
: : EN-Passage
Este pasaje esta en español.
[[Continuar|ES-Next]]
: : EN-Passage
Deze passage is in het Nederlands
[[Doorgaan|NL-Next]]
}}}
You can also choose to merge every translated passage into one, tracking the language choice through a variable:
{{{
: : Start
THIS IS A GAME, REALLY...
[[English|Passage][$language to "English"]]
[[Français|Passage][$language to "French"]]
[[Español|Passage][$language to "Spanish"]]
[[Nederlands|Passage][$language to "Dutch"]]
: : Passage
<<switch $language>><<case "English">>
This passage is English.
[[Continue|Next]]
<<case "French">>
Ce Passage est en Français.
[[Continuer|Next]]
<<case "Spanish">>
Este pasaje esta en español.
[[Continuar|Next]]
<<case "Dutch">>
Deze passage is in het Nederlands
[[Doorgaan|Next]]
<</switch>>
}}}
> Note: this can also be useful if your UI displays text which should be different depending on the language chosen.
\
<h3>Built-In Text and Settings</h3>\
If Built-In Text appears on the page (throug the Base UI or while using Settings or Saves), you will need to not only show the proper Story Text within passages, but the correct version of this Built-In text. This should be done via JavaScript and include [[l10nStrings|Local-L10n]].
While you may choose to built your own, TME has already created a custom version ([[code here|https://gist.github.com/tmedwards/33f3b4b7ada317fc9cc70aa8580c03f0]]), which includes a Setting for the player to switch from one language to another at any time, and explained below.
\
<h4>TME Internalization Code</h4>\
First, Copy-Paste the JavaScript code between the {{{:: Language Switching [script]}}} and {{{:: Start}}} lines into your project's JavaScript. Then you will need to edit it to fit your project's need. Two parts are the most important: changing the list of languages to choose from, and changing the Built-In text for each language.
> Note: TME indicates where to edit the code with his {{{// NOTE: User customization required here.}}} comment.
{{{
langs : {
// NOTE: User customization required here.
'Deutsche' : 'de',
'English' : 'en',
'Français' : 'fr',
},
}}}
In this part, you will want to list the languages you want to display, followed by a language code. This is required for the latter part of the code to work.
You will need to remove unnecessary cases as well.
{{{
switch (setup.i18n.langs[settings.lang]) {
/*
NOTE 1: User customization required here.
NOTE 2: The `l10nStrings` properties shown in the cases below are an
abbreviated set for example purposes. There are many more properties
within the `l10nStrings` object which you'll need to handle.
*/
case 'de':
l10nStrings.settingsTitle = 'Einstellungen';
l10nStrings.settingsOff = 'Deaktivieren';
l10nStrings.settingsOn = 'Aktivieren';
l10nStrings.settingsReset = 'Auf Standardeinstellung zurücksetzen';
break;
case 'fr':
l10nStrings.settingsTitle = 'Paramètres';
l10nStrings.settingsOff = 'Désactiver';
l10nStrings.settingsOn = 'Activer';
l10nStrings.settingsReset = 'Réinitialiser les paramètres par défaut';
break;
}
}}}
In this part, you will need to create the relevant cases with the language codes you created in the previous part of the code, and list the required {{{l10nStrings}}}, so the Built-In text is shown in the chosen language.
The {{{case 'en':}}} is not listed here, as it uses the Built-In text already. If you want to change any of the [[l10nStrings|Local-L10n]] for English, you will need to add it there.
> Note: you can find [[pre-translated packages|Local-Trans]] for the {{{l10nStrings}}}.
\
<h4>Setting up the Passages</h4>\
After the JavaScript code is set, you will then have to set the passages. While similar to the first method, this one requires an empty passage to act as an anchor for the JavaScript code. From that anchor, the code will check the langugage chosen, add the relevant language code as a suffic to the anchor, and display the corresponding passage.
For example, with the passage {{{Start}}}:
# Anchor {{{Start}}}
# Language: {{{English}}}
# Code into Suffix: {{{en}}} -> {{{_en}}}
# Passage to display: {{{Start_en}}}
So, you will need to create as many passages as there are defined languages, on top of the anchor (e.g. 3 languages = 4 passages). In a project, it will look like this:
{{{
: : Start
: : Start_de
Deutsche.
[[Nächster|Next]]
: : Start_en
English.
[[Next]]
: : Start_fr
Français.
[[Prochain|Next]]
}}}
And so on and so forth...
> Note: The links to the next passage MUST go towards the anchor passage. If you link it to a suffixed passage ({{{Start_en}}}), it will add another suffix ({{{Start_en_en}}}) and display and error.
\
<h4>Language Choice at Start and Window Reload</h4>\
While the player can go into the settings to change the language of the game, it is also possible to give the player the option to choose a language as a starting passage. You will need to create a link, where you save the language choice in a setting variable.
{{{
<<link "Français" "Next">>
<<set settings.lang to "Français">>
<<run Setting.save()>>
<</link>>
}}}
If you are using the Sidebar of the Base UI, you will need to refresh the page between saving the setting and moving the to next page, as the visible buttons on the Sidebar will not load the correct {{{l10nStrings}}} version. This can be done by adding a tad extra code:
{{{
<<link "Français" "Next">>
<<set settings.lang to "Français">>
<<run Setting.save()>>
<<run window.location.reload()>>
<</link>>
}}}
> Note: In a fully Custom UI, this //should// be unnecessary.
\
<h4>Edit Settings Language or Other Custom Elements</h4>\
While TME's code allows the automation of displaying different version of Built-In text through the {{{l10nStrings}}}, you do need to do the same for custom text, such as Settings lables and descriptions, or whatever element you created on the page (e.g. Custom Menu in the UI). This, however, can easily be remedied with the {{{<<switch>>}}} macro.
{{{
In a Non-Story Passage:
<<switch settings.lang>>
<<case "English">>Settings
<<case "Français">>Paramètres
<</switch>>
}}}
{{{
In JavaScript Settings:
Setting.addList('lang', {
label : `<<switch settings.lang>><<case "English">>Language<<case "Français">>Langue<</switch>>`,
desc : `<<switch settings.lang>><<case "English">>Select the wanted language<<case "Français">>Choisissez la langue voulue<</switch>>`,
list : setup.i18n.labels(),
default : setup.i18n.labelFromCode('en'),
onInit : initLanguage,
onChange : changeLanguage
});
}}}
<div id="link-menu">[[Back to the Localization Menu|Localization]] - [[Back to the Start Menu|Start]]</div><h1>Advanced Macros</h1>
Below you will find the last of the macros not discussed in the previous chapters. These macros are considered advanced, as they will either require some HTML/CSS knowledge, or full control of coding logics. They are usually not needed for basic projects.
* [[DOM Macros and Changing Class of an Element|Macro-DOM-Adv]]
* [[Loops and Repeats - Two Ways|Macro-For-Repeat]]
* [[Capturing the Value of a Variable|Macro-Capture]]
* [[Emulating PassageDone for one Passage|Macro-Done]]
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>DOM Macros and Changing Class of an Element</h1>
As [[DOM Macros|Macro-ApPreRepCopy]] can affect the content displayed on the page, so can they change //how// elements on the page look, by adding or removing an HTML class from that element. There are three macros in this set:
* {{{<<addclass>>}}}, which will add a class to the targetted element.
* {{{<<removeclass>>}}}, which will remove a class from the targetted element.
* {{{<<toggleclass>>}}}, which will either add or remove a class from the targetted element, depending on whether the class was there in the first place.
<<button "Click Me to Change the Title Colour!">>
<<toggleclass ".passage h1" "colour">>
<</button>>
The macros have 2 arguments:
* {{{selector}}}, or the targetted element
* {{{className(s)}}}, the classe(s) to add/remove/toggle from the element
** This one is optional for {{{<<removeclass>>}}}
\
The macro will target any element you indicate in the first argument. It can be as simple as {{{h1}}}, which will target //all// large header on the page, to more specific like {{{.passage h1}}}, which will only target the large header in the passage.
{{{
<<addclass "h1" "colour">>
→ will add ".colour" to the "h1" element
<<removeclass "#passages">>
→ will remove ALL classes from "#passages"
<<toggleclass ".dog" "sweet">>
→ will add/remove the class ".sweet" from the ".dog" element
}}}
> Note: the element indicated in the macro should be on the page. Otherwise, this will trigger an error.
> Note 2: when using {{{<<removeclass>>}}} to remove classes, please not that it can also affect class created by the Passage Tags, or in JavaScript settings.
\
<h3>An important note on DOM Macros</h3>\
Since the macros require the targetted element to be on the page, they ''cannot'' be coded as is on the page, due to how the [[page renders|SP-PassageReady-Done]]. As such, you will need either to:
* use the {{{<<link>>}}} or {{{<<button>>}}} macro, letting the player interact with the element,
* use the {{{<<done>>}}} macro, which will trigger when the page is fully rendered,
* code it in the {{{PassageDone}}} special passage (same as the {{{<<done>>}}} macro, but will trigger at every passage render).
<div id="link-menu">[[Back to the Advanced Macro Menu|Macro-Adv]] - [[Back to the Start Menu|Start]]</div><h1>Loops and Repeats - Two Ways</h1>
While both {{{<<for>>}}} and {{{<<repeat>>}}} will loop and repeat their action, they do it in different ways. The {{{<<repeat>>}}} macro will trigger its content at an indicated interval until stopped, while the {{{<<for>>}}} macro will trigger an indicated amount of time (almost) at once. Whether time is involved is the biggest difference.
\
<h3>The {{{<<repeat>>}}} macro</h3>\
The macro will repeatedly execute its content after the indicated delay. It can be useful as a countdown, check the value of a variable before triggering some code, or replace elements on the page. It can be stopped either by using the {{{<<stop>>}}} macro inside the container or moving to a new passage.
The macro has 2 arguments:
* {{{delay}}}, or the interval between each iteration, should be indicated in seconds or milliseconds.
** the minimum is 40ms
* {{{t8n}}}/{{{transition}}} (optional), whether any insertion on the page should be done with an animation
{{{
<<repeat 1s t8n>> /* Your Code */ <</repeat>>
}}}
When creating a loop, it should be remembered that the macro will not stop until it encounters a {{{<<stop>>}}} macro within the code (or when moving to a different passage).
An example of a loop, as a countdown timer, updating the text every second, before sending the player to an end passage:
{{{
→ A countdown timer
<<set $seconds to 10>>
Countdown: <span id="countdown">$seconds seconds</span> remaining!
<<repeat 1s>>
<<set $seconds to -->>
<<if $seconds is 1>>
<<replace "#countdown">>$seconds second<</replace>>
<<elseif $seconds gt 0>>
<<replace "#countdown">>$seconds seconds<</replace>>
<<else>>
<<replace "#countdown">>Too Late<</replace>>
<<timed 3s>><<goto "Too Late END">><</timed>>
<<stop>>
<</if>>
<</repeat>>
}}}
\
<h3>The {{{<<for>>}}} macro</h3>\
The macro will repeatedly execute its content for a certain amount of times, set in three forms: conditional, 3-part conditional, and range. Unless used in combination with the submacros {{{<<break>>}}} and {{{<<continue>>}}}, the loop will execute until the condition in the form is fulfilled.
> Note: while the macro does not allow for a set number in the macro ({{{<<for 4>>}}} will give an error), there is a way to circumvent it (see end).
This macro is quite useful in displaying content of an inventory, or doing code loop.
\
<h4>The Conditional forms</h4>\
The conditional forms come in two ways: simple and 3-part. They will execute the content of the macro until the condition is no longer true.
{{{<<for [init]; [conditional]; [post]>>}}}
For this form, the macro has three arguments:
* {{{init}}} (optional), or the initialisation of a counter variable (ex: {{{_i}}})
* {{{conditional}}}, or the conditional expression which should be check at the start of every loop, triggering the code until it is no longer true
* {{{post}}} (optional), the change of value of the counter variable, happening at the end of each loop.
> Note: the arguments HAVE to be seperated by a semi-colon {{{ ; }}}
{{{
Single Conditional:
<<set _filling to ["Apple", "Chocolate", "Cherry", "Pumpkin"]>>
<<for _done isnot true>>
<<if _filling.length is 0>>
<<set _done to true>>
The Pies Have ALL Been Eaten!
<<else>>
<<set _taste to _filling.pluck()>>
You eat the _taste Pie!
<</if>>
<</for>>
}}}
{{{
3-Part Conditional:
<<set $dwarves to ["Doc", "Dopey", "Bashful", "Grumpy", "Sneezy", "Sleepy", "Happy"]>>
<ol>
<<for _i to 0; _i lt $dwarves.length; _i++>>
<li> $dwarves[_i]</li>
<</for>>
</ol>
→ This will print the array as an ordered list
}}}
\
<h4>The Range form</h4>\
This form will go through all entries of a given collection (ex: values of an array), and stop executing the content when the collection has run out.
There are 4 arguments for this form:
* {{{keyVariable}}} (optional), a temporary variable holding the loop iteration number (starting at 0)
* {{{valueVariable}}}, as a {{{$var}}} or {{{_temp}}}, holding the value of the current loop iteration
* {{{range}}}, required to tell the system this is a range form
* {{{collection}}}, the variable holding as many entries are there will be iterations
** among others, it will accept: arrays, objects, strings (as an array of characters)
{{{
<<set $dwarves to ["Doc", "Dopey", "Bashful", "Grumpy", "Sneezy", "Sleepy", "Happy"]>>
<<for _i, _name range $dwarves>>
<<print _i + 1>>. _name
<</for>>
→ will print the content of the array as a list (#. value)
}}}
\
<h4>Using a set number as the amount of iteration</h4>\
While it is not possible to simply do {{{<<for 4>>}}} to have the loop onyl run four times, you can circumvent this in two ways:
* use Maliface's {{{<<times>>}}} [[Custom Macro|https://github.com/MalifaciousGames/Mali-s-Macros#the-times-macro]]
* use a widget to "hide" the 3-part contidional form (below)
{{{
In the Widget Passage:
<<widget "times" container>>
<<for _i = 0; _i lt _args[0]; _i++>>
_contents
<</for>>
<</widget>>
In the wanted Passage:
<<times 5>>
Run code or output stuff five times
<</times>>
}}}
\
<h4>Using {{{<<break>>}}} and {{{<<continue>>}}}</h4>\
The {{{<<for>>}}} macro has also two submacros to skip finishing an iteration or stop the loop altogether before it is completed, respectively with the {{{<<continue>>}}} and {{{<<break>>}}} macros.
For example, the code below is set to run 10 times, and will check if the number of iteration and:
* not print a number if the iteration is 2, 3, or 5
* stop the looping altogether if the iteration is greater than 8
{{{
<<for _i to 0; _i lt 10; _i++>>
<<if [2,3,5].includes(_i)>>
<<continue>>
<<elseif _i gt 8>>
<<break>>
<</if>>
<<print _i>>
<<for>>
Printed output:
0 1 4 6 7 8
}}}
<div id="link-menu">[[Back to the Advanced Macro Menu|Macro-Adv]] - [[Back to the Start Menu|Start]]</div><h1>Emulating PassageDone for one Passage</h1>
The {{{<<done>>}}} macro is akin to the Special Passage {{{PassageDone}}}, in a way that it executes its content when the passage is done rendering. Unlike the Special Passage, the macro will only work in the passage it is coded, rather than on every passage. This macro is especially useful to trigger DOM Macros for [[adding elements to the page|Macro-ApPreRepCopy]] or [[changing the class of that element|Macro-DOM-Adv]].
> Note: the player will not see any delay between the rendering of the passage and triggering the macro. For delayed needs, use the {{{<<timed>>}}} macro.
> Note 2: for multiple passage use, {{{PassageDone}}} should have preference, or assigning code to the {{{:passagedisplay}}} even in the JavaScript.
{{{
@@#spy;@@
<<done>>
<<replace "#spy">>I spy with my little eye, a crab rangoon.<</replace>>
<</done>>
}}}
<div id="link-menu">[[Back to the Advanced Macro Menu|Macro-Adv]] - [[Back to the Start Menu|Start]]</div><h1>Capturing the Value of a Variable</h1>
The {{{<<capture>>}}} macro is considered one of the hardest macro to grasp for most Twine users, as its use is pretty limited (to the more complex form of code). Essentially, the macro allows to create a copy of the value of a variable, for the current passage, regardless of whatever happens to that variable later on.
The macro is most useful with interactive macros, loop macros, or delayed ones.
Assuming {{{_n = 1}}} at the start, but changing later down the code:<<nobr>>
<<set _n = 1>>
<<button "Non-Captured Value">>
<<run alert(_n)>>
<</button>>
<<capture _n>>
<<button "Captured Value">>
<<run alert(_n)>>
<</button>>
<</capture>>
<<set _n = 4>>
<</nobr>>
The macro has 1 argument:
* {{{variableList}}}: the variable, or list of variables, whose value need to be captured
** the macro will work with both {{{$var}}} and {{{_temp}}}
{{{
<<capture $var>>...<</capture>>
<<capture _var, $var, $varvar>>...<</capture>>
}}}
\
<h3>Some Examples</h3>\
Below is the code for the interactive example above:
{{{
<<nobr>>
<<set _n = 1>>
<<button "Non-Captured Value">>
<<run alert(_n)>>
<</button>>
<<capture _n>>
<<button "Captured Value">>
<<run alert(_n)>>
<</button>>
<</capture>>
<<set _n = 4>>
<</nobr>>
}}}
While the value of {{{_n}}} changes, only the first button will show the updated value when clicked, as it will take the most recent value of {{{_n}}} (" 4 "). The second button, on the other hand, copied the value of {{{_n}}} before the variable changed (" 1 "), and kept that value.
A more complex example involving a loop and an interactive element:
<<nobr>><<set _what to [
"a crab rangoon",
"a gaggle of geese",
"an aardvark",
"the world's smallest violin"
]>>
<<for _i to 0; _i lt _what.length; _i++>>
<<capture _i>>
I spy with my little <<linkappend "eye" t8n>>, _what[_i]<</linkappend>>.
<</capture>>
<</for>><</nobr>>
{{{
<<set _what to [
"a crab rangoon",
"a gaggle of geese",
"an aardvark",
"the world's smallest violin"
]>>
<<for _i to 0; _i lt _what.length; _i++>>
<<capture _i>>
I spy with my little <<linkappend "eye" t8n>>, _what[_i]<</linkappend>>.
<</capture>>
<</for>>
}}}
For each element of the array {{{_what}}}, the loop will create a new sentence, within which is linked a different variable of that array.
<div id="link-menu">[[Back to the Advanced Macro Menu|Macro-Adv]] - [[Back to the Start Menu|Start]]</div><h1>Going Further with the Basics</h1>
After making some basic links, setting variables, and creating simple conditional statements, we can add a bit of complexity to these macros, as well as adding a few useful ones along the way.
* [[Displaying more than text in Links|Macro-Link]]
* [[Setting and Changing Variables|Macro-Set]]
* [[Unsetting Variables|Macro-Unset]]
* [[More Conditional Statements|Macro-If]]
* [[Display Variables, the Print Macro and Variants|Macro-Print]]
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>Displaying more than text in Links</h1>
As with the [[Link Markup|Markup-Link]], you can display more than plain text in links. This includes the content of variables, widgets, or even images. You can also use variables to display the link on page or sent the player to a certain passage.
Assuming that {{{$passage = "Garden"}}} and {{{$text = "Go take a walk"}}}:
{{{
<<link $text $passage>><</link>>
will work the same way as
<<link [[Go take a walk|Garden]]>><</link>>
or
<<link "Go take a walk" "Garden">><</link>>
}}}
Displaying the value of a variable is a bit more straightforward than the link markup. Assuming that {{{$name = "Jane"}}} and {{{$location = "Garden"}}} :
{{{
<<link "I am $name" "Passage">><</link>>
→ this will display "I am Jane".
<<link '<<if $location is "Garden">>Go back to the house<<else>>Go to the house<</if>>' "House">><</link>>
<<link `($location === "Garden") ? "Go back to the house" : "Go to the house"` "House">><</link>>
→ depending on the value of $location, the link will show a different text.
}}}
Similarly, for widgets, assuming that {{{<<widget "SomeWidget">>Wow Some Text<</widget>>}}}:
{{{
<<link "<<SomeWidget>>" "Passage">><</link>>
→ this will display "Wow Some Text".
}}}
> Note: the quotes here are important! Otherwise the link will not work.
As for images, you can use the [[Twine markup|Markup-Image]] or the HTML one ({{{<img>}}}). You also need the [[URL of an image|URL-Types]]:
{{{
<<link [img[URL][Passage]]>><</link>>
<<link "[img[URL]]" "Passage">><</link>>
<<link '<img src="URL">' "Passage">><</link>>
}}}
<h3>Quotes or Apostrophes... or both?</h3>
Unlike the Link Markup, the {{{<<link>>}}} macro needs something to contain the text to display on the page. This can be done with Apostrophes {{{'}}} or Quotes {{{"}}}, which are essentially interchangeable (see examples above). However, this can become an issue when using certain markups or widgets, which may also use quotes or apostrophes to work. To fix this, you have two solutions:
{{{
Use one, and wrap the whole in the other:
<<link '"I am speaking!"' "Passage">><</link>>
<<link "I don't think this is a good idea..." "Passage">><</link>>
<<link '<img src="URL">' "Passage">><</link>>
<<link "//''HEY!''//" "Passage">><</link>>
Use the backslash \:
<<link "\"I am speaking!\"" "Passage">><</link>>
<<link 'I don\'t think this is a good idea...' "Passage">><</link>>
<<link "<img src=\"URL\">" "Passage">><</link>>
<<link "//\'\'HEY!\'\'//" "Passage">><</link>>
}}}
> Note: For regular text, I would recommend using curly quotes and apostrophes {{{“” ‘’}}} for the text rather than straight ones. You would not need to think about whether using apostrophes or quotes or a backslash. {{{<<link '“I am speaking!”' "Passage">><</link>>}}}
<div id="link-menu">[[Back to the Base Macro Menu|Macro-Basic]] - [[Back to the Start Menu|Start]]</div><h1>Unsetting Variables with {{{<<unset>>}}}</h1>
To avoid bloating the load time of passages, it is best to keep the number of variables to a minimum. One way of doing so is unsetting variables you don't need anymore. While temporaty variables {{{_temp}}} disappear automatically when the player moves to a new passage, permanant variables {{{$var}}} need the {{{<<unset>>}}} macro.
{{{
<<unset $variable>>
Multiple at a time:
<<unset $var, $var2, $var3>>
}}}
\
<h3>Using the {{{<<run>>}}} macro.</h3>\
There are situations where using the {{{<<unset>>}}} doesn't work the way you would want. For example, trying to unset a property inside an object ({{{<<unset $object.property>>}}}) will unset the whole object instead of the property. To resolve this, you should use the {{{<<run>>}}} macro coupled with the JavaScript {{{delete}}} operator.
Assuming that {{{$mc = {name: "Jane", nickname: "Janie", age: 10}}}}:
{{{
<<run delete $mc.nickname>>
→ will only remove the {nickname} property from the object
<<run delete $mc.nickname, delete $mc.age>>
→ this will remove both the {nickname} and {age} properties from the object
}}}
> Note: you can also unset regular variables with this method.
<div id="link-menu">[[Back to the Base Macro Menu|Macro-Basic]] - [[Back to the Start Menu|Start]]</div><h1>Setting and Changing Variables</h1>
Aside from the TwineScript {{{to}}} operator to set an orginial value to a variable, the {{{<<set>>}}} macro accepts other JavaScript (mathematical) operators to edit that value.
<<nobr>>
<table>
<tr>
<th>Operator</th><th>Explanation</th><th>Example</th>
</tr>
<tr>
<td>{{{=}}}</td><td>Works like {{{to}}}, asign the value to the variable.</td><td>{{{<<set $apples = 6>>}}}</td>
</tr>
<tr>
<td>{{{+=}}}</td><td>Adds to the current value.</td><td>{{{<<set $apples += 6>>}}} or {{{<<set $apples to $apples + 6>>}}} </td>
</tr>
<tr>
<td>{{{-=}}}</td><td>Substract to the current value.</td><td>{{{<<set $apples -= 6>>}}}</td>
</tr>
<tr>
<td>{{{*=}}}</td><td>Multiplies the current value.</td><td>{{{<<set $apples *= 6>>}}}</td>
</tr>
<tr>
<td>{{{/=}}}</td><td>Divides the current value.</td><td>{{{<<set $apples /= 6>>}}}</td>
</tr>
<tr>
<td>{{{%=}}}</td><td>Removes a percentage of the current value.</td><td>{{{<<set $apples %= 6>>}}}</td>
</tr>
<tr>
<td>{{{++}}}</td><td>Adds 1 to the current value.</td><td>{{{<<set $apples ++>>}}}</td>
</tr>
<tr>
<td>{{{--}}}</td><td>Removes 1 to the current value.</td><td>{{{<<set $apples -->>}}}</td>
</tr>
</table>
<</nobr>>
As well, you can set a variable with the value (or combination of values) of other variables.
Assuming that {{{$test = 6}}} and {{{$apple = 4}}}:
{{{
<<set $test to $apple>>
→ $test will have the value of $apple (= 4)
<<set $test += $apple>>
→ $test will have the value of ($test + $apple) (= 10)
<<set $test to (($apple * 4)/($test - 2))>>
→ $test will have the value of ($apple multiplied by 4) divided by ($test minus 2) (= 4)
}}}
This also works with string variables. Assuming that {{{$name = "Jane"}}} and {{{$surname = "Doe"}}}, and the widget {{{<<widget "SomeWidget">>Wow Some Text<</widget>>}}}:
{{{
<<set $wholename to $name + $surname>>
→ $wholename will have the value "JaneDoe"
<<set $wholename to $name + " " + $surname>>
→ $wholename will have the value "Jane Doe"
<<set $address to "Hello, $name">>
→ $address will print "Hello, Jane" on the page.
<<set $address to "<<SomeWidget>>">>
→ $address will print the content of the widget, here "Wow Some Text".
}}}
> Note: for that last example, if {{{$name}}} changes during the story or is unset, {{{$address}}} will not show "Hello, Jane" but the current value of {{{$name}}}. On the other hand, if {{{$name}}} changes, the value of {{{$wholename}}} will not.
> Note 2: You can also mix the types of values when combining them like the examples above. But using certain numerical operators on a string-based variable will break the variable: {{{<<set $name /= 2>>}}}.
\
<h3>Setting up Arrays and Objects</h3>\
{{{
Array:
<<set $array to []>> → defined but empty
<<set $array to [1, "word", true]>>
<<set $inventory to ["pen", "coins", "apple"]>>
Object:
<<set $object to {}>> → defined but empty
<<set $object to {number: 1, string: "word", boolean: true}>>
<<set $mc to {age: 51, hair: "bald", degree: true}>>
}}}
If an object is defined, you can add any property, even if they were not listed in the first place:
{{{<<set $object.newproperty = "value of your choice">>}}}
To edit an array, [[see this page|Method-Array]].
\
<u>Going further:</u>\
You can also use [[functions|Functions]] and [[methods|Methods]] when setting a variable, or edit a value. This can be useful to change how a string is formatted (uppercase) or for statistics.
<div id="link-menu">[[Back to the Base Macro Menu|Macro-Basic]] - [[Back to the Start Menu|Start]]</div><h1>More Conditional Statements</h1>
Depending on the situation, you may need to use a different operator than {{{is}}} to check if a condition applies or not. And, since SugarCube is based on JavaScript, you can use either options interchangeably or mix and match:
<<nobr>>
<table class="ifses">
<tr>
<th>Sugarcube</th><th>JavaScript</th><th>Description</th><th>Example</th>
</tr>
<tr>
<td>{{{is}}}</td><td>{{{===}}}</td><td>Check if //strickly// equal</td><td>{{{<<if $test is 1>>}}} {{{<<if $test === 1>>}}}</td>
</tr>
<tr>
<td>{{{isnot}}}</td><td>{{{!==}}}</td><td>Check if //strickly// NOT equal</td><td>{{{<<if $test isnot "apple">>}}} {{{<<if $test !== "apple">>}}}</td>
</tr>
<tr>
<td>{{{eq}}}</td><td>{{{==}}}</td><td>Check if equivalent</td><td>{{{<<if $test eq 45>>}}} {{{<<if $test == 45>>}}}</td>
</tr>
<tr>
<td>{{{neq}}}</td><td>{{{!=}}}</td><td>Check if //strickly// equal</td><td>{{{<<if $test neq "dinner">>}}} {{{<<if $test != "dinner">>}}}</td>
</tr>
<tr>
<td>{{{gt}}}</td><td>{{{>}}}</td><td>Check if greater than</td><td>{{{<<if $test gt 12>>}}} {{{<<if $test > 12>>}}}</td>
</tr>
<tr>
<td>{{{gte}}}</td><td>{{{>=}}}</td><td>Check if greater or equal</td><td>{{{<<if $test gte $tries>>}}} {{{<<if $test >= $tries>>}}}</td>
</tr>
<tr>
<td>{{{lt}}}</td><td>{{{<}}}</td><td>Check if lower than</td><td>{{{<<if $test lt ($tries + 2)>>}}} {{{<<if $test < ($tries +2)>>}}}</td>
</tr>
<tr>
<td>{{{ltw}}}</td><td>{{{<=}}}</td><td>Check if lower or equal</td><td>{{{<<if $test lte $listparticipant.length>>}}} {{{<<if $test <= $listparticipant.length>>}}}</td>
</tr>
<tr>
<td>{{{def}}}</td><td>/</td><td>Check if variable is defined</td><td>{{{<<if def $test>>}}}</td>
</tr>
<tr>
<td>{{{ndef}}}</td><td>/</td><td>Check if variable is NOT defined</td><td>{{{<<if ndef $test>>}}}</td>
</tr>
<tr>
<td>{{{not}}}</td><td>{{{!}}}</td><td>Check if condition is //false// or Falsy</td><td>{{{<<if not $test>>}}} {{{<<if !$test>>}}}</td>
</tr>
<tr>
<td>{{{ }}}</td><td>{{{ }}}</td><td>Check if condition is //true// or Truthy</td><td>{{{<<if $test>>}}}</td>
</tr>
<tr>
<td>{{{and}}}</td><td>{{{&&}}}</td><td>Evaluate if //all// conditions are true</td><td>{{{<<if $test is 1 and $name is "Jane">>}}} {{{<<if $test === 1 && $name === "Jane">>}}}</td>
</tr>
<tr>
<td>{{{or}}}</td><td>{{{||}}}</td><td>Evaluate if //one// of the conditions is true</td><td>{{{<<if $test is 1 or $test if 4>>}}} {{{<<if $test === 1 || $test === 4>>}}}</td>
</tr>
</table>
<</nobr>>
<h3>Ordering your Conditional Statements</h3>\
When you want to check multiple conditional statements, you need to rememeber to order those statements from ''most strict'' to least. Since Twine reads code from top to bottom, the program will stop at the first condition is fulfilled, even if there is a more specific situation below. For example:
{{{
<<if $turn gt 3>>
The Code will stop here and only show this text...
<<elseif $turn gt 3 && $turn lt 5>>
... even if the value of $turn is 4.
<</if>>
<<if $turn gt 3 && $turn lt 5>>
But this code will only show if the value of $turn is 4...
<<elseif $turn gt 3>>
...while this one will show if the value of $turn is greater then 3 and does not meet the condition above.
<</if>>
}}}
\
<h3>Mixing AND and OR</h3>\
If you have multiple condition that would apply to a same variation, you can merge them together with the {{{and}}} and {{{or}}} operators instead of having a long list of {{{<<elseif>>}}} showing the same text. You can also mix and match those operators for more complex conditional statements (see example below). To organise the different conditions, it is advised to use parentheses {{{( )}}}.
> Note: you must remember that the order of which the operators are applied, work like maths. Inside parentheses first, the rest after.
{{{
<<if ($turn is 1) and ($name is "Jane")>>
→ will only work if $turn has a value of 1 AND $name is "Jane"
<<if ($turn is 3) or ($pet is "dog")>>
→ will work if $turn has the value of 3 OR $pet is "dog"
<<if ($turn is 4 or $pet is "dog") && ($name is "Jane" or $credit gt ($cost * 2))>>
→ will only work if one of the conditions in EACH block is true:
→ if $turn has the value of 4 OR $pet is "dog"
→ if $name is "Jane" OR the value of $credit is greater than the value of $cost multiplied by 2
}}}
> Note: in example 1 and 2, the parentheses are not mandatory, but it IS for example 3.
\
<h3>True/False and Truthy/Falsy</h3>\
There is a difference between //True/False// and //Truthy/Falsy//, with the first being strickly related to Boolean values and situations, while the latter has a broader reach. Checking a Truthy/Falsy condition will not only look at whether a variable is defined, but also what kind of value it holds.
<table>
<tr>
<th>Truthy values</th><th>Falsy values</th>
</tr>
<tr>
<td>true
any number that is not 0
any filled string (inc. 'false' and '0')
[] (empty arrays)
{} (empty objects)
</td>
<td>false
0
{{{''}}} (empty string)
null
undefined
NaN
</td>
</tr>
</table>
Assuming that {{{$test = ''}}}:
{{{
<<if $test>>
This text will not show because $test is an empty string, and so a falsy condition.
<</if>>
<<if !$test>>
This text //will// show, because $test is an empty string, and so a falsy condition.
<</if>>
Note:
<<if def $test>>
This text //will// show, because $test is defined, even as an empty string.
<</if>>
}}}
<style>.ifses th:nth-child(3), .ifses td:nth-child(3) {width: 33%;}</style>
<div id="link-menu">[[Back to the Base Macro Menu|Macro-Basic]] - [[Back to the Start Menu|Start]]</div><h1>Display Variables, the {{{<<print>>}}} Macro and Variants</h1>
There are essentially four ways of displaying a variable:
* [[bare|Markup-Variable]]: {{{$variable}}}
* with the {{{<<print>>}}} macro: {{{<<print $variable>>}}}
* with the {{{<<=>>}}} macro: {{{<<= $variable>>}}}
* with the {{{<<->>}}} macro: {{{<<- $variable>>}}}
Unlike the bare version, the macros will display [[special variables|Variables-Base]] and functions attached to variables.
Assuming that {{{$choice = "dog"}}}: <<set $choice = "dog">>
{{{$choice}}} → $choice
{{{<<print $choice>>}}} → <<print $choice>>
{{{<<= $choice>>}}} → <<= $choice>>
{{{<<- $choice>>}}} → <<- $choice>>
Assuming that {{{$name = "jane"}}}: <<set $name = "jane">>
{{{$name.toUpperCase()}}} → $name.toUpperCase()
{{{<<print $name.toUpperCase()>>}}} → <<print $name.toUpperCase()>>
{{{<<= $name.toUpperCase()>>}}} → <<= $name.toUpperCase()>>
{{{<<- $name.toUpperCase()>>}}} → <<- $name.toUpperCase()>>
> Note: For more functions, [[see this page|Functions]].
All three macros are interchangeable, aside from one distinction: the {{{<<->>}}} macro will show HTML markup and some nested SugarCube code as regular characters.
Assuming that {{{$example = "<i>this</i>"}}} <<set $example = "<i>this</i>">>
{{{$example}}} → $example
{{{<<print $example>>}}} → <<print $example>>
{{{<<= $example>>}}} → <<= $example>>
{{{<<- $example>>}}} → <<- $example>>
Assuming that {{{$test = "<<SomeWidget>>"}}} and the widget {{{<<widget "SomeWidget">>Wow Some Text<</widget>>}}}: <<set $test = "<<SomeWidget>>">>
{{{$test}}} → $test
{{{<<print $test>>}}} → <<print $test>>
{{{<<= $test>>}}} → <<= $test>>
{{{<<- $test>>}}} → <<- $test>>
<h3>Display all the values of an object:</h3>\
To print whole object variables on the page, you need to use a bit of JavaScript:
Assuming that {{{$npc = {name: 'Jane', age: '53'} }}}: <<set $npc = {name: 'Jane', age: '53'}>>
{{{<<print Object.values($npc)>>}}} → <<print Object.values($npc)>>
{{{<<print JSON.stringify($npc)>>}}} → <<print JSON.stringify($npc)>>
<<unset $choice, $name, $example, $test, $npc>>
<div id="link-menu">[[Back to the Base Macro Menu|Macro-Basic]] - [[Back to the Start Menu|Start]]</div><h1>Macros of Convenience</h1>
To make it more convenient to format code and passages, or send the player to a certain passage, SugarCube has a handful of Macro of Convenience.
* [[An Alternative to Conditional Statements|Macro-Switch]]
* [[Removing Blank Space and Hiding Code|Macro-Nobr-Silent]]
* [[Including a Passage inside another|Macro-Include]]
* [[Creating and Using a Widget|Macro-Widget]]
* [[Going Back or Returning to a Passage with a Special Link|Macro-Back-Return]]
* [[Sending the Player to a Passage|Macro-Goto]]
* [[Using JavaScript in the Passage|Macro-Script-Run]]
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>Removing Blank Space and Hiding Code</h1>
It can be very frustrating to code and format a whole passage and realise when playing it that unwanted blank space appears on the page. This can be resolved with the macros {{{<<nobr>>}}} and {{{<<silently>>}}}. Depending on the content of the passage, and what should be achieved, you may want to favour one macro over the other.
\
<h3>{{{<<nobr>>}}} or {{{<<silently>>}}}</h3>\
Both macros will remove any blank space created with the code inside the container. They are both useful when wanting to indent the code to make it clearer to read (especially complex code).
The main difference between the macros is whether an output is expected within the macro, as in: is there text inside the container that should appear on the screen where the macro is coded?
{{{<<silently>>}}} will run any code inside the macro, but will not show anything on the page (unless you play the game in //Test/Debug// mode). {{{<<nobr>>}}} will run the code inside the macro, as well show any output on the page, without any linebreak (like the [[nobr Markup|Markup-Nobr]]).
{{{
I'd like a <<nobr>>
<<if $feeling eq "blue">>
blueberry
<<else>>
cherry
<</if>>
<</nobr>> pie.
→ will show the result in one line
}}}
{{{
<<silently>>
You'll never see any of this! But this code will run...
<<set _time to "9s">>
<<timed _time>>
<<goto "END">>
<</timed>>
<</silently>>
→ will send you to the passage "END" but nothing will appear on the page
}}}
<div id="link-menu">[[Back to the Convenient Macro Menu|Macro-Conv]] - [[Back to the Start Menu|Start]]</div><h1>Including a Passage inside another</h1>
Whether to add extra text or code to a passage without wanting to clutter it, or wanting to include the same bit of code/text in multiple places, you can use the {{{<<include>>}}} macro to do so.
The macro has 2 arguments:
* the passage name
* the HTML element type (optional) to wrap the included passage (ex: h1, div, p, etc...)
{{{
<<include "Passage Name">>
<<include [[Passage Name]]>> <- will create an arrow in Twine
<<include "Passage Name" "div">> <- will wrap the passage in a 'div'
<<include [[Passage Name]] "h1">> <- will wrap the passage in the largest header
}}}
You can use {{{<<include>>}}} in any passage you'd want, even the [[Special Passages|Special-Passage]]! It can be pretty practical for {{{StoryInit}}} if you have a lot of variables or macro to set up and want to organise it.
The HTML element type will also get a class attached to it, to better target the included element. The class will be named after the name of the passage, in all undercase and with {{{-}}} replacing the spaces and removing punctuation. So {{{Passage Name}}} will have the class {{{passage-passage-name}}}, or {{{To the Left !}}} will look like {{{passage-to-the-left-}}}.
> Note: It is not recommended to use punctuation in a passage name.
{{{
: : Start
This is the Start.
<<include "Left">>
: : Left
And now you go left!
→ will appear on the page as:
This is the Start.
And now you go left!
}}}
> Note: unlike the {{{<<widget>>}}} [[macro|Macro-Widget]], {{{<<include>>}}} will add the whole called passage to the page, whether it is a line or 100 long, as well as any space left before / after / inside the text / code.
<div id="link-menu">[[Back to the Convenient Macro Menu|Macro-Conv]] - [[Back to the Start Menu|Start]]</div><h1>Creating and Using a Widget</h1>
Widgets are pretty practical macros that enables you to create special macros without using JavaScript. You can call bits of texts or simple code as many times as you want without having to clutter your passage, or create containers to wrap text from the main passage, avoiding the need to code the HTML markup every time. The {{{<<widget>>}}} macro is great for many things, like characters with different pronouns, or grouping a list of links which needs to appear on different passages, to creating special hovertext, etc...
Widgets need to be set in a non-story passage tagged with {{{widget}}}. You can add as many widgets as you can in the tagged passage. You can also have multiple widgets passages (though it is best to keep it to a minimum). It is recommended to wrap the code inside the {{{<<widget>>}}} with the {{{<<nobr>>}}} [[macro|Macro-Nobr-Silent]] or add the [[tag|Tags-Built]] {{{nobr}}} to the widget passage to remove unwanted space.
The macro has 2 arguments:
* the name of the widget, which:
** has to be one word
** is case sensitive
** canot include punctuation
** cannot start with a number
** cannot have the same name as a Base SugarCube Macro or any custom macro included in your JavaScript
* {{{container}}} (optional), to create a container macro.
{{{
<<widget "Name" container>>
/*Your code*/
<</widget>>
}}}
Example:
{{{
: : Widget [widget]
<<widget "SimonSays">>
<<set _array to ["Raise your hands!", "Jump!", "Dance!"]>>
<<print _array.random()>>
<</widget>>
}}}
When the widget is set up, you can "call" it in the passage, by wrappin the name of the widget with {{{< >}}}. A widget can be used as many times as you'd want, even inside one passage. Assuming that the widget is set as above:
> Simon says: <<SimonSays>>
{{{
Code:
> Simon says: <<SimonSays>>
}}}
<h3>Arguments and Contents</h3>\
On top of regular code, widgets can use extra arguments when called, or become a container. This can be done by using the special temporary variables {{{_args[]}}} and {{{_contents}}} when setting the widget.
An argumented widget can be used to create more complex but general macros, using arguments in the form of text or variables. The arguments are stored in an array called {{{_args[]}}}, which start at 0.
{{{
Argument Widget:
<<widget "SimonSpecialSay">>
<<if _args[0]>>
<<print _args[0]>>
<<else>>
<<SimonSays>>
<</if>>
<</widget>>
→ this will check whether an argument has been included when calling the widget, and if so show the content of the argument.
}}}
> Simon says: <<SimonSpecialSay>>
> Simon says: <<SimonSpecialSay "Fooled you!">>
{{{
Code :
> Simon says? <<SimonSpecialSay>>
> Simon says: <<SimonSpecialSay "Fooled you!">>
}}}
A container widget will create a special macro, with an opening and closing brackets wrapped around the text in the main passage. It uses the variable {{{_contents}}} to link that text.
{{{
Container Widget:
<<widget "SimonDoes" container>>
<div class="simon">
<hr class="before-simon">
<p class="simon-does">_contents</p>
</div>
<</widget>>
CSS:
.simon {
width: 134px;
margin: auto;
}
hr.before-simon {
border-color: darkgreen;
}
.simon-does {
text-transform: capitalize;
}
Code:
<<SimonDoes>>And so he does!<</SimonDoes>>
}}}
<<SimonDoes>>And so he does!<</SimonDoes>>
You can also combined a container with arguments, as seen in the exmaple from the Documentation:
{{{
<<widget "say" container>>
<div class="say-box">
<img class="say-image" @src="'images/' + _args[0].toLowerCase() + '.png'">
<p class="say-text">_contents</p>
</div>
<</widget>>
<<say "Chapel">>
Tweego is a pathway to many abilities some consider to be… unnatural.
<</say>>
}}}
This code will create a dialogue box, showing an image next to the text. The url of image is pulled by the argument.
Though it should not be abused, you can call a widget inside another widget:
{{{
<<widget "Test">>This is a test<</widget>>
<<widget "whoops">>
<<if $var is 0>>
<<Test>>
<<else>>
This is a bug.
<</if>>
<</widget>>
}}}
> Note: this macro differs from the {{{<<include>>}}} [[macro|Macro-Include]], which will include the whole passage on the page.
<div id="link-menu">[[Back to the Convenient Macro Menu|Macro-Conv]] - [[Back to the Start Menu|Start]]</div><h1>Going Back or Returning to a Passage with a Special Link</h1>
Whether it is to return to the story from a Codex page or going back to a certain location, the {{{<<back>>}}} and {{{<<return>>}}} macros create an easy link towards a passage the player has already visited.
> Note: If the player has not visited that passage, they //will// get an error message.
Both macros are formatted the same way and only requires 1 argument:
* (optional) the text to show, the passage to send the player to , or the image to show
{{{
Going back one passage:
<<back>>
<<return>>
Going back one passage, showing the text "Home" in the link:
<<back "Home">>
<<return "Home">>
Going back to a passage with the LinkMarkup:
<<back [[Home]]>>
<<return [[Going Home|Home]]>>
Going back to a passage with an image:
<<back [img[URL]]>>
<<return [img[URL][Home]]>>
}}}
> Note: Going back one passage is essentiall the same as {{{[[Text|previous()]]}}}, see the {{{previous()}}} [[function|Functions]].
\
<h3>{{{<<back>>}}} or {{{<<return>>}}}?</h3>\
Though they look to perfrom the same action (going to a specific passage), the macros behave differently uneder the hood. The {{{<<back>>}}} macro goes back in the player history, undoing any action made between the current passage and the target one. The {{{<<return>>}}} macro goes to the passage by going forward in the player history (like a regular {{{<<link>>}}}), keeping any action performed between the two passages safe.
For example, the player goes to "NPC Codex Page" from the "Tavern" passage. Their history would look like this:
{{{State.history = ["Tavern", "NPC Codex Page"]}}}
In the Codex page, if the player clicks on the {{{<<return>>}}} macro, the history would look liks this:
{{{State.history = ["Tavern", "NPC Codex Page", "Tavern"]}}}
On the other hand, if the player clicks on the {{{<<back>>}}} macro, the history would look like this:
{{{State.history = ["Tavern"]}}}
\
<h3>Using a variable as the targetted passage</h3>\
If you have Codex pages and want to send the player back to the Story without having to indicate the last story passage they visited, you can use the [[Long Arbitrarily Return|Long-Return-JS]] with the {{{<<back>>}}} and {{{<<return>>}}} macros, by indicating a variable instead of the passage name. This can be helpful, as it will avoid creating loops and making the player stuck.
{{{
<<back [[Return to the Story|$passage]]>>
<<return [[Return to the Story|$passage]]>>
}}}
> Note: since Twine automatically creates a new passage when using the {{{[[link]]}}} Markup, you will need to delete the new passage (here {{{$passage}}}) after coding the macros. Otherwise, the player will be sent to a blank page instead of the wanted passage. Or you can use the {{{<<link>>}}} macro instead.
<div id="link-menu">[[Back to the Convenient Macro Menu|Macro-Conv]] - [[Back to the Start Menu|Start]]</div><h1>An Alternative to Conditional Statements</h1>
If you are looking at multiple values of one variable or function, and the conditional statement only looks at one situation at a time, the {{{<<switch>>}}} macro is a useful alternative to the {{{<<if>>}}} macro.
The Macro has one argument for the container, and one for the submacro:
* {{{<<switch>>}}}:
** the element whose value you want to check.
* {{{<<case>>}}}
** the value of the element.
* {{{<<default>>}}} does not have an argument, as it works like {{{<<else>>}}}
Using a variable:
{{{
<<switch $dice>>
<<case 1>>You rolled a 1, this is a critical failure...
<<case 2>>You rolled a 2, this is a failure.
<<case 5>>You rolled a 5, this is a success.
<<case 6>>You rolled a 6, this is a critical success!
<<default>>You rolled a $dice. Nothing happens.
<</switch>>
→ the <<switch>> will look at the value of $dice and display the text depending on the value.
}}}
Using a function:
{{{
<<switch previous()>>
<<case "Home">>Leaving your house, you soon arrive at the park.
<<case "Work">>Finally done with work, you skip towards the park.
<<case "Cinema" "Theater">>Waking up after a boring movie, you sluggishly walk towards the park.
<</switch>>
→ here, the macro will look at the name of the previously visited passage, and if this name is either "Home", "Work" or "Cinema"/"Theater", it will display the text. For any other case, it will not display anything.
}}}
<div id="link-menu">[[Back to the Convenient Macro Menu|Macro-Conv]] - [[Back to the Start Menu|Start]]</div><h1>Sending the Player to a Passage</h1>
Aside from a link, the {{{<<goto>>}}} macro will send the player to the indicated passage. While it should not be overused, as it adds to the player history or already included as an argument in linking macros, it can be useful when the passage to send the player to is conditional.
> Note: using {{{<<goto>>}}} outside of a link/button/timed macro will send the player to that passage without loading fulling the previous passage.
The macro has 1 argument:
* the name of the wanted passage, variable or function
{{{
<<goto "PassageName">>
<<goto [[PassageName]]>>
<<goto $passage>>
<<goto [[$passage]]>>
<<goto `previous()`>>
}}}
> Note: on Twine, using the Link Markup with the variable will automatically create a passage. When using the variable or function, don't forget to remove that newly created passage.
Some example of uses:
{{{
<<link "Attack!">>
<<if $attack gt 5>>
<<goto "Success">>
<<else>>
<<goto "Failure">>
<</if>>
<</link>>
<<timed 3s>>
<<goto "No Action">>
<</timed>>
}}}
> Note: in some instances, it is preferrable to use the [[Navigation Override|Basic-API-Navig]] instead of {{{<<goto>>}}}.
<div id="link-menu">[[Back to the Convenient Macro Menu|Macro-Conv]] - [[Back to the Start Menu|Start]]</div><h1>Using JavaScript in the Passage</h1>
While you can add JavaScript or jQuery to the JavaScript tab, sometimes it is necessary to add it to a passage directly. This will be done with the {{{<<script>>}}} container macro or the {{{<<run>>}}} macro. For small bits of code or coded functions in the JavaScript tab, {{{<<run>>}}} is often the macro to use. On the other hand, {{{<<script>>}}} is usually used for larger amount of code.
> Note: some knowledge of JavaScript/jQuery is necessary to have, especially if the code runs into issues.
If added as is on the page, the code will triggers as soon at the passage is loaded. But it can also be included inside a {{{<<link>>}}} macro, or triggered as a later time with {{{<<timed>>}}}.
{{{
<<script>>
/*Your JavaScript/jQuery code*/
<</script>>
<<script>>
setup.Hi = function (name) {
if (name == undefined) {
return "Hi.";
} else {
return "Hi, " + name + ".";
}
};
<</script>>
<<run $(document.body).append('<div id="report-down"></div>').find('#report-down')>>
<<run setup.ScrollDown()>>
}}}
> Note: when using the {{{<<script>>}}} macro with {{{<<nobr>>}}}, the latter macro will transform the code into one line. If comments are included with backslash {{{//}}}, it will render the rest of the code unuseable. {{{/*Comments*/}}} is prefered in this case.
> Note 2: the {{{<<script>>}}} macro has the same use as the {{{<script>}}} HTML markup, though the latter will only work inside the {{{StoryInit}}} passage.
<div id="link-menu">[[Back to the Convenient Macro Menu|Macro-Conv]] - [[Back to the Start Menu|Start]]</div><h1>SugarCube Markup Basic Styling</h1>
To format text or code, SugarCube has a special markup, separate from HTML and SugarCube Macro. Here would be the most relevant to basic projects.
* [[Showing the Value of a Variable|Markup-Variable]]
* [[Using a Variable inside a Link|Markup-Link]]
* [[Display an Image, and as a Link|Markup-Image]]
* [[Removing a Line-break|Markup-Nobr]]
* [[Basic Text Styling|Markup-Styling]] (long)
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>Showing the Value of a Variable</h1>
While you can use the {{{<<print>>}}} [[macro|Macro-Print]], you can most often show the value of a variable by simply coding {{{$variable}}} to the passage.
Assuming that {{{$name}}} was set with the value "Jane", you would see here its value:<<set $name to "Jane">>
{{{$name}}} → $name
For array, you'd need to indicate the position of a value to print it on the page, inside square brackets. Assuming that {{{$list}}} has been set with the following values {{{[1, 9, 3, 4, 7]}}}, you should see:<<set $list = [1, 9, 3, 4, 7]>>
{{{$list}}} → $list
If you wanted to show the third number:
{{{$list[2]}}} → $list[2]
> Note: the first value inside an array is at position 0
For an object, there are two ways of showing a value: the property inside square brackets or after a dot. Assuming {{{$npc}}} has been set as {{{$npc = {name: 'Jane', age: '53'} }}}: <<set $npc = {name: 'Jane', age: '53'}>>
{{{$npc.name}}} → $npc.name
{{{$npc['age']}}} → $npc['age']
However, you cannot show a whole object as is:
{{{$npc}}} → $npc
> Note: See [[this page|Macro-Print]] for other ways.
<<unset $name, $list, $npc>>
<div id="link-menu">[[Back to the Markup Menu|Markup]] - [[Back to the Start Menu|Start]]</div><h1>Using a Variable inside a Link</h1>
You can also use a variable to show a specific text to display as a link, or send the player to a specific passage. Assuming that {{{$passage = "Garden"}}} and {{{$text = "Go take a walk"}}}:
{{{
[[$text|$passage]]
will work the same way as
[[Go take a walk|Garden]]
}}}
> Note: using a variable to send the player to a passage is quite useful as a //Back to the Story// link.
You can also display the value of a variable with another string of text inside a link, by wrapping the text in quotes. Assuming that {{{$name = "Jane"}}}:
{{{[["I am " + $Name|Passage]]}}} → I am Jane
{{{[["She is " + $Name + ", a friend."|Passage]]}}} → She is Jane, a friend.
> Note: Do not use this markup as {{{[["Text" + $var]]}}}, as it will break the game.
> Note 2: You can use apostrophes instead of quotes.
Using a combination of straight quotes and apostrophe in your text can mess up the code. I recommend using the curly ones {{{“” ‘’}}} instead (not recognised as code by Twine). But adding a {{{\}}} before the non-code character should fix it:
{{{[["/"She/'s " + $Name + ", a friend./""|Passage]]}}}
<div id="link-menu">[[Back to the Markup Menu|Markup]] - [[Back to the Start Menu|Start]]</div><h1>Display an Image, and as a Link</h1>
The markup to display an image works similarly to the [[link one|Markup-Link]], though it requires the [[URL of an image|URL-Types]] to work:
{{{[img[URL]]}}}
> Note: When compiling the code into an HTML file, the code will transorm into {{{<img src="URL">}}}
This URL can be a relative link or an online one, and like the [[link markup|Markup-Link]], it can be stored in a variable. Assuming that
{{{$passage = "Garden"}}} and {{{$url = "garden.png"}}}:
{{{[img[$url][$passage]]}}}
You can also set variables inside an Image Link:
{{{[img[URL][PASSAGE][$var to true]]}}}
> Note: For the link image, I would recomment using the {{{<<link>>}}} macro instead with the {{{<img>}}} HTML markup.
<div id="link-menu">[[Back to the Markup Menu|Markup]] - [[Back to the Start Menu|Start]]</div><h1>Removing a Line-break</h1>
Because Twine creates extra space automatically (with a {{{<br>}}} HTML markup) when compiling, sometimes it creates too many of them. When this happens, you can use a backslash to remove a break:
{{{
This is bat of a sentence... \
... that is broken in two.
or
This is bat of a sentence...
\... that is broken in two.
will show as:
This is bat of a sentence... ... that is broken in two.
}}}
> Note: There are more useful break removing features, such as the {{{<<nobr>>}}} [[macro|Macro-Nobr-Silent]], the {{{nobr}}} [[special tag|Special-Tags]], to the [[Config setting|Basic-API-Config]].
<div id="link-menu">[[Back to the Markup Menu|Markup]] - [[Back to the Start Menu|Start]]</div><h1>Basic Text Styling</h1>
From making headers to changing the colour of one word, one could use HTML (and some CSS) or use some markup...
> Note: when //beginning a line with...// is indicated, the first character of that line needs to be the mentioned character. If you have a space or an intentation, the text will not transform. As well, if text, passage or story uses ont of the [[Line-Break|Markup-Nobr]] features, the Style Markup will not work (but the HTML one will!).
\
<h3>Headings</h3>\
Beginning a line with an exclamation point, you can define different levels of headings. Starting with one (the largest), all the way to 6 (the smalles), each new exclamation point will decrease the type of header.
{{{
!Level 1 → <h1></h1>
!!Level 2 → <h2></h2>
!!!Level 3 → <h3></h3>
!!!!Level 4 → <h4></h4>
!!!!!Level 5 → <h5></h5>
!!!!!!Level 6 → <h6></h6>
}}}
\
<h3>Styling</h3>\
To render a text bold or in italics, you need to wrap it with characters. You can mix and match those styles, as long as you nest them one inside the other.
{{{
//Italics// → <em></em>
''Bold'' → <strong></strong>
__Underline__ → <u></u>
==Strikethrough== → <s></s>
^^Superscript^^ → <sup></sup>
~~Subscript~~ → <sub></sub>
}}}
> Note: using the SugarCube or HTML Markup to style text inside a [[Link Markup|Markup-Link]] often leads to strange results (to plainly not work). The use of the {{{<<link>>}}} [[macro|Macro-Link]] in this case is recommended.
\
<h3>Lists - ordered and unordered</h3>\
Beginning the line with an asterisk or a number sign, you can create respectively unordered or ordered lists. Similarly the headings, adding more than one character will define the indentation of the list.
{{{
* List
** List
will be the same as:
<ul><li> List
<ul><li>List</li></ul>
</li></ul>
# List
## List
will be the same as:
<ol><li> List
<ol><li>List</li></ol>
</li></ol>
}}}
\
<h3>Horizontal Rule</h3>\
Beginning the line with four hyphen characters, will create a line (like the one at the bottom of the page):
{{{ ---- }}}
\
<h3>Custom Style</h3>\
Wrap two {{{@@}}} characters around a bit of text to create a {{{<span>}}} or a {{{<div>}}}:
{{{
@@Text@@ → <span></span>
@@
Text → <div><div>
@@
}}}
> Note: a {{{<div>}}} will create a block of text, while a {{{<span>}}} will stay inside a line.
You can then assign a class, id or CSS rule to those elements, seperating it from the text with a semi-colon:
{{{
@@#id;.class;color:red;Text@@
→ <span id="id" class="class" style="color:red"></span>
@@#id;.class;color:red;
Text
@@
→ <div id="id" class="class" style="color:red"><div>
}}}
\
<h3>Comments</h3>\
There are three ways of leaving a note in your passage which will be hidden to the player:
{{{
/* A comment */ → Passage, JavaScript, Stylesheets
/% A comment %/ → Passage
<!-- A comment --> → Passage, Special Passages
}}}
<div id="link-menu">[[Back to the Markup Menu|Markup]] - [[Back to the Start Menu|Start]]</div><h1>Using Methods to change Variables</h1>
Methods are [[functions|Functions]], JavaScript blocks of code designed to do a specific task, linked to a reciever, like a variable, to run.
{{{
<reciever>.method()
Example:
$var.first()
}}}
In SugarCube, they are mainly used to handle arrays, change the formatting of strings values, or handle numbers.
* [[Methods and String Variables|Method-String]]
* [[Methods and Numbers|Method-Number]]
* [[Methods and Arrays|Method-Array]]
> Note: Other native JavaScript or jQuery methods can be used with SugarCube, but requires knowledge of those languages. The ones listed in this guide would be the most useful.
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>Methods and Arrays</h1>
Arrays are where the methods are most useful, as they are the main way to edit them or check its content. These methods can be used with the {{{<<set>>}}}/{{{<<run>>}}} macros, or in conditional statements.
> Note: These methods do not need to be attached to a variable, they can be attached to a non-saved array (see the {{{<Array>.includes()}}} examples).
\
<h2>Add elements to an array</h2>\
There are multiple ways to add elements to an array, but the methods listed below will do so differently.
The examples below will assume that {{{_array = ['Apple', 'Potatoe', 'Sausage']}}} and {{{_array2 = [1, 2, 3]}}}
<h4>{{{<Array>.concat()}}}</h4>\
{{{<Array>.concat()}}} will merge other arrays or lists of values to the original array, with the new values added at the end of the orginal array:
{{{
_array.concat(value/variable)
}}}
{{{
_array.concat(_array2)
→ ['Apple', 'Potatoe', 'Sausage', 1, 2, 3]
_array.concat(_array2, 'words')
→ ['Apple', 'Potatoe', 'Sausage', 1, 2, 3, 'words']
_array.concat('words')
→ ['Apple', 'Potatoe', 'Sausage', 'words']
}}}
As the method will not edit the original variable, you would need to use the {{{<<set>>}}} macro for the change the stay constant:
{{{<<set _array to _array.concat(_array2)>>}}}
> Note: if you want to only include new values to the array, you would need to use {{{<Array>.concatUnique()}}}
<h4>{{{<Array>.push()}}}</h4>\
{{{<Array>.push()}}} will add values to the original array, with the new values to be added at the end of the orignal array:
{{{
_array.push(value/variable)
}}}
{{{
_array.push(_array2)
→ ['Apple', 'Potatoe', 'Sausage', 1, 2, 3]
_array.push(_array2, 'words')
→ ['Apple', 'Potatoe', 'Sausage', 1, 2, 3, 'words']
_array.push('words')
→ ['Apple', 'Potatoe', 'Sausage', 'words']
}}}
The method can be run on either the {{{<<set>>}}} or {{{<<run>>}}} macros
{{{
<<set _array to _array.push(_array2)>>
<<set _array.push(_array2)>>
<<run _array.push(_array2)>>
}}}
> Note: if you want to only include new values to the array, you would need to use {{{<Array>.pushUnique()}}}
<h4>{{{<Array>.unshift()}}}</h4>\
{{{<Array>.unshift()}}} will add values to the original array, with the new values to be added at the ''beginning'' of the orignal array:
{{{
_array.unshift(value/variable)
}}}
{{{
_array.unshift(_array2)
→ [1, 2, 3, 'Apple', 'Potatoe', 'Sausage']
_array.unshift(_array2, 'words')
→ [1, 2, 3, 'words', 'Apple', 'Potatoe', 'Sausage']
_array.unshift('words')
→ ['words', 'Apple', 'Potatoe', 'Sausage']
}}}
The method can be run on either the {{{<<set>>}}} or {{{<<run>>}}} macros
{{{
<<set _array to _array.unshift(_array2)>>
<<set _array.unshift(_array2)>>
<<run _array.unshift(_array2)>>
}}}
> Note: if you want to only include new values to the array, you would need to use {{{<Array>.unshiftUnique()}}}
\
<h3>Remove elements from an array</h3>\
There are multiple ways to remove elements from an array, but the methods listed below will do so differently.
The examples below will assume that {{{_array = ['Apple', 'Apple', 'Potatoe', 'Sausage', 1, 2, 3]}}} and {{{_array2 = [1, 2, 3]}}}
\
<h4>{{{<Array>.delete()}}}</h4>\
{{{<Array>.delete()}}} will remove any instance of the targetted value.
{{{
_array.delete(value/variable)
}}}
{{{
_array.delete(_array2)
→ ['Apple', 'Apple', 'Potatoe', 'Sausage']
_array.delete(_array2, 'Apple')
→ ['Potatoe', 'Sausage']
_array.delete('Apple')
→ ['Potatoe', 'Sausage', 1, 2, 3]
}}}
The method can be run on either the {{{<<set>>}}} or {{{<<run>>}}} macros
{{{
<<set _array to _array.delete(_array2)>>
<<set _array.delete(_array2)>>
<<run _array.delete(_array2)>>
}}}
<h4>{{{<Array>.deleteAt()}}}</h4>\
{{{<Array>.deleteAt()}}} will work similarly to the previous method, but will target the element at a certain position in the array.
> Note: the first element in an array starts at 0.
> Note 2: you can use an array filled with numbers instead of of multiple values
{{{
_array.deleteAt(value/variable)
}}}
{{{
_array.deleteAt(_array2)
→ ['Apple', 1, 2, 3]
_array.deleteAt(0, _array2)
→ [1, 2, 3]
_array.deleteAt(6)
→ ['Apple', 'Apple', 'Potatoe', 'Sausage', 1, 2,]
}}}
The method can be run on either the {{{<<set>>}}} or {{{<<run>>}}} macros
{{{
<<set _array to _array.deleteAt(_array2)>>
<<set _array.deleteAt(_array2)>>
<<run _array.deleteAt(_array2)>>
}}}
<h4>{{{<Array>.pluck()}}}</h4>\
{{{<Array>.pluck()}}} and {{{<Array>.pluckMany()}}} are two methods what will respectively remove an element/multiple elements from the array in a random manner.
> Note: for {{{<Array>.pluckMany()}}}, you can use an integer variable to indicate the number of elements you want to remove.
{{{
_array.pluck()
_array.pluckMany(number/variable)
}}}
{{{
_array.pluckMany(3)
_array.pluckMany(_var)
}}}
These methods can be run on either the {{{<<set>>}}} or {{{<<run>>}}} macros
{{{
<<set _array to _array.pluck(_array2)>>
<<set _array.pluckMany(_array2)>>
<<run _array.pluck(_array2)>>
}}}
<h4>{{{<Array>.pop()}}} and {{{<Array>.shift()}}}</h4>\
{{{<Array>.pop()}}} and {{{<Array>.shift()}}} will remove respectively the last and first element in an array.
{{{
_array.pop()
→ will remove the element "3" from the array
_array.shift()
→ will remove the element "Apple" from the array
}}}
These methods can be run on either the {{{<<set>>}}} or {{{<<run>>}}} macros
{{{
<<set _array to _array.pluck(_array2)>>
<<set _array.pluckMany(_array2)>>
<<run _array.pluck(_array2)>>
}}}
\
<h3>Check the properties of an array</h3>\
There are multiple ways to check the properties of an array. Depending on what you are looking for, you may find one method working better than another.
<h4>{{{<Array>.includes()}}} and its alternatives</h4>\
{{{<Array>.includes()}}} will check whether an element is included in the array. It also comes in two other flavours: {{{<Array>.includesAll()}}}, which will check if all listed elements are included in an array, and {{{<Array>.includesAny()}}}, which will check whether one of the elements listed is included in an array.
{{{
<Array>.includes(value, position)
<Array>.includesAll(value/variable)
<Array>.includesAny(value/variable)
}}}
> Note: the {{{position}}} parameter of {{{<Array>.includes()}}} will start the search for the wanted element starting that position in the array
The method is best used in conditional statements:
{{{
<<if _array.includes("Apple")>>...<</if>>
→ since the array has the element "Apple", it will run the content
<<if _array.includes("Apple", 3)>>...<</if>>
→ this won't run, since the elements "Apple" are in positions 0 and 1
<<if _array.includesAll(_array2, "Apple")>>...<</if>>
→ since the array has those elements, it will run the content
<<if _array.includesAll(_array2, 4)>>...<</if>>
→ won't run, since the array does not have the element 4
<<if _array.includesAny(_array2, "Apple")>>...<</if>>
<<if _array.includesAny(_array2, 4)>>...<</if>>
→ since the array has those elements, it will run the content
Using a non-variable array as the receiver:
<<if ["John", "Jane", "Sylvia"].includes($var)>>...<</if>>
→ if the value of the variable is included in this array, the code will run.
}}}
> Note: this last example can be useful to block certain names from being used by the player when setting their character
\
<h4>{{{<Array>.first()}}} and {{{<Array>.last()}}}</h4>\
{{{<Array>.first()}}} and {{{<Array>.last()}}} will return respectively the element in the first and last position in the array.
{{{
<Array>.first()
<Array>.last()
}}}
Among other, they can be used in conditional statements or setting another variable:
{{{
<<if _array.first() is "Apple">>...<</if>>
→ this will run, since the first element of the array is "Apple"
<<if _array.first() is 1>>...<</if>>
→ this won't run
<<set $var to _array.last()>>
→ the value of $var will be "3"
}}}
<h4>{{{<Array>.count()}}}</h4>\
{{{<Array>.count()}}} will check how many times an element is included in the array. You can indicate a {{{position}}} to start the search at said position in the array
{{{
<Array>.count(value, position)
}}}
{{{
_array.count("Apple") → 2
_array.count("Apple", 4) → 0
→ the elements 'Apple' are at position 0 and 1
}}}
> Note: the method cannot be left empty. If you are looking to check the length of an array, you should use {{{.length}}} instead.
\
<h3>Other Array Methods</h3>\
There are handful of other methods one can use with arrays.
<h4>{{{<Array>.random()}}}</h4>\
{{{<Array>.random()}}} will take a value from the array at random (but not modify the orignal array), and {{{<Array>.randomMany()}}} will do the same thing but take as many as indicated:
{{{
<Array>.random()
<Array>.randomMany(number)
}}}
> Note: it words similarly to the [[function|Function-Clone-Random]] {{{either()}}}.
You can use these methods in conditional statements, to set variable, or simply print on the screen:
{{{
<<set $var to _array.random()>>
<<= _array.randomMany(3)>>
<<if _array.random() is "Apple">>...<</if>>
}}}
<h4>{{{<Array>.shuffle()}}}</h4>\
{{{<Array>.shuffle()}}} wiill shuffle the order of the values in the array, at random.
{{{
_array.shuffle()
}}}
The method can be run on either the {{{<<set>>}}} or {{{<<run>>}}} macros
{{{
<<set _array to _array.shuffle()>>
<<set _array.shuffle()>>
<<run _array.shuffle()>>
}}}
<h4>{{{<Array>.flat()}}}</h4>\
{{{<Array>.flat()}}} will flatten an array containing sub-arrays.
{{{
<Array>.flat(depth)
}}}
> Note: the {{{depth}}} parameter is optional, if omitted, it will default to 1.
Assuming that {{{_array3 = [["Alfa", "Bravo"], [["Charlie", "Delta"], ["Echo"]], "Foxtrot"]}}}
{{{
_array.flat() → ["Alfa", "Bravo", ["Charlie", "Delta"], ["Echo"], "Foxtrot"]
_array.flat(2) → ["Alfa", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot"]
}}}
The method can be run on either the {{{<<set>>}}} or {{{<<run>>}}} macros
{{{
<<set _array to _array.flat()>>
<<set _array.flat(2)>>
<<run _array.flat(3)>>
}}}
<div id="link-menu">[[Back to the Methods Menu|Methods]] - [[Back to the Start Menu|Start]]</div><h1>Methods and Numbers</h1>
Mathematical methods can be quite useful in a project, especially when dealing with player statistics and stat bars, to ensure a value does not exceed or go below a certain range.
\
<h3>{{{Math.round()}}} </h3>\
This method will round the numerical value of a variable or equation to the nearest full number. It is most useful when wanting to keep the results of statistic calculations to a round value.
{{{
Math.round(value)
Math.round(5.5) → 6
Math.round(-5.5) → -5
}}}
> Note: this method is native to [[JavaScript|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round]].
While the use of this method can be as simple as rounding the value of a variable, you can use it for more complex equations:
{{{
<<set $stoic to Math.round($stoic)>>
→ will round the value of the value of $stoic to the nearest full number.
<<set $stoic to Math.round( $stoic + ( ( 100 - $stoic ) * ( _increase / 100 ) ) )>>
→ will increase the value of $stoic by a percentage set by _increase, then round it to the nearest number.
}}}
> Note: This calculation is a recreation of the ChoiceScript Fairmath system
\
<h3>{{{Math.trunc()}}}</h3>\
This method will remove any decimal from the value.
{{{
Math.trunc(value)
Math.trunc(5.5) → 5
Math.trunc(12.678) → 12
}}}
> Note: this method is native to [[JavaScript|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc]].
\
<h3>{{{Math.clamp()}}}</h3>\
This method will check whether the value is within a set range, and calculate a new value within the bounds. It is most useful when when wanting to ensure the value of a variable stays between bounds (ex: a stat not going above 100% or lower than 0%).
{{{
Math.clamp(value, min, max)
Math.clamp($var, 6, 300)
}}}
The method alone will not change the value of a variable, this needs to be done with a {{{<<set>>}}} macro:
{{{
<<set $stoic to Math.clamp($stoic, 0, 100)>>
<<set $stoic to Math.clamp(($stoic + 4) * 5, 0, 100)>>
}}}
> Note: for simple clamping without further calculation, this can also be done with {{{<Number>.clamp()}}}, {{{<<set $stoic to $stoic.clamp(0, 100)>>}}}.
<div id="link-menu">[[Back to the Methods Menu|Methods]] - [[Back to the Start Menu|Start]]</div><h1>Methods and String Variables</h1>
The methods below are mainly useful to change the formatting of string variables, or see if certain characters are included in the strings. With the methods below, the code will look at a string as if it was an array of character (including space and punctuation), with the first having the position 0.
\
<h3>Changing the Formatting of Strings.</h3>\
Whether to change the string to its upper or lowercase version, or just tranform the frist character, you would need to use one of the following methods: {{{.toLowerCase()}}}/{{{.toLocaleLowerCase()}}}, {{{.toUpperCase()}}}/{{{.toLocaleUpperCase()}}}, {{{.toUpperFirst()}}}/{{{.toLocaleUpperFirst()}}}
> Note: the {{{.toLocale-()}}} method transforms the string in accordance to the user's language and region in their device.
Assuming that {{{$jane = "jane"}}} and {{{$john = "John"}}}
{{{
<<print $jane.toUpperFirst()>> → Jane
<<print $jane.toUpperCase()>> → JANE
<<print $john.toLowerCase()>> → john
}}}
You can also save this information into a variable or use them in conditional statements:
{{{
<<set $name to $jane.toUpperFirst()>>
→ $name will have the value "Jane"
<<if $john.toLowerCase() is "john">>...<</if>>
}}}
\
<h3>Get the First or Last Character of a String</h3>\
To find the first or last character of a string variable, you would need to use respectively {{{.first()}}} and {{{.last()}}}. Assuming that {{{$var = "Hello, World :D"}}}:
{{{
<<print $var.first()>> → H
<<print $var.last()>> → D
}}}
\
<h3>Find if or how many times a Substring is included in a String Variable</h3>\
Similarly to [[arrays|Method-Array]], to find if a substring is included in a variable, you would need to use {{{.includes()}}}. With this method, you can do a wide search, or start it at a certain number. Assuming that {{{$var = "Hello, World :D"}}}:
{{{
<<if $var.includes('lo')>>.this will show.<</if>>
<<if $var.includes('lo', 2)>>.this won't show.<</if>>
<<if $var.includes('lo', 6)>>.this won't show.<</if>>
<<if $var.includes('love')>>.this won't show either.<</if>>
}}}
On the other hand, {{{.count()}}} will look at how many times a substring is included in a variable. Assuming that {{{$var = "Hello, World :D"}}}:
{{{
<<print $var.count('l')>> → 3
<<print $var.count('l', 5)>> → 1
}}}
> Note: the method cannot be left empty. If you are looking to check the length of a string, you should use {{{.length}}} instead.
<div id="link-menu">[[Back to the Methods Menu|Methods]] - [[Back to the Start Menu|Start]]</div><h1>More Special Passages and Tags</h1>
Aside from the [[Basic Special Passages|Special-Passage]], your project can be customised further with more Special Passage Names, as well as tags.
* [[Special Tags creating Special Passages and Functionalities|Tags-Built]]
* [[Process Code Before and After Rendering a Passage|SP-PassageReady-Done]]
* [[Changing the UI of the Project|SP-StoryInterface]]
* [[Customising Passages with Tags|Tags-CSS]]
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>Changing the UI of the Project</h1>
If you want to ditch the basic SugarCube UI and have something more customised, you will need to use the Special Passage {{{StoryInterface}}}. This passage only accepts HTML, and JavaScript inside a {{{<script>}}} markup at the bottom of the passage.
This passage only has one requirement to run properly: include the {{{#passages}}} element.
{{{
: : StoryInterface
<div id="passages"></div>
}}}
> Note: while knowledge of HTML and CSS is necessary to create your own UI, there are many templates available to use as is. See [[this page|https://manonamora-if.tumblr.com/post/700577877042888704/]]. Still, it is heavily recommended to understand the basics of both languages.
Inside other set elements in that passage you can add text or other HTML markup:
{{{
<div id="header"><h1>Title of the Game</h1></div>
}}}
For a full example:
{{{
<div id="parent">
<div id="passages"></div>
<div id="menu" data-passage="sidemenu"><!--Side menu, editable in the sidemenu passage--></div>
</div>
<script>
function myFunction() {
document.getElementById("myMenu").classList.toggle("show");
}
/*Close the dropdown menu if the user clicks outside of it*/
window.onclick = function(event) {
if (!event.target.matches('.dropbtn')) {
var dropdowns = document.getElementsByClassName("dropup-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
</script>
}}}
> Note: This is the code in my [[One Page Template|https://manonamora.itch.io/twine-sugarcube-templates]].
\
<h3>Formatting the elements</h3>\
When the required elements are set in the passage, you will need some CSS to place it on the page and format its content. A few elements will keep their built-in CSS rules, however:
* {{{#passages}}} and its child {{{.passage}}}
* {{{#ui-overlay}}}, {{{#ui-dialog}}} and its children (the elements in a the dialog box)
If other [[base IDs and classes|http://www.motoslave.net/sugarcube/2/docs/#html]] were used when setting elements in {{{StoryInterface}}}, those elements will also use the built-in CSS rules to start.
> Note: like with the base UI, those rules can be changed at will in the StyleSheet.
{{{
#parent {
width: 50vh;
margin: auto;
display: flex;
}
#passages {
width: 75%;
}
#menu {
width: 25%;
}
}}}
It is important when setting sizes or placement of elements to keep in mind that different screens will affect said placement or size differently. As such, testing the UI in different screen sizes (doable with the Inspect Tool of the browser), and using the {{{@media}}} CSS rule, will help with those issues.
> Note: testing on both Chromium and non-Chromium browsers should be done as well, as different CSS rules (ex: overflow) will render differently on screen.
\
<h3>Linking an Element to a passage</h3>\
To avoid filling the {{{StoryInterface}}} passage, or because certain elements would need some SugarCube code (which won't work in {{{StoryInterface}}}), you can create links between an element and a non-story passage. This can be done with either {{{data-passage}}} or {{{data-init-passage}}}.
{{{
<div class="menu" data-passage="sidemenu">
<!--Side menu, editable in the sidemenu passage-->
</div>
<div class="title" data-init-passage="title">
<!-- Title, editable in the "title" passage-->
</div>
}}}
> Note: any text left inside the elements will be overriden by the content of the linked passage.
While these two links seem interchangeable, there is a major difference between the two: {{{data-init-passage}}} will load at the start of the game and ''never'' change, while {{{data-passage}}} will update at every new passage (if an update is necessary).
<div id="link-menu">[[Back to the Special Passages and Tags Menu|Special-Tags]] - [[Back to the Start Menu|Start]]</div><h1>Process Code Before and After Rendering a Passage</h1>
{{{PassageReady}}} and {{{PassageDone}}} are two Special Passages that will trigger respectively before and after the story passage renders. Those passages will not render any output (i.e. text) on the page, but will run code for every new story passage visited. They are best used for code meant to be used for multiple passages during the game, such as checking the location of the player to trigger some code or change the display of the page.
{{{
: : PassageReady
<<if $var is 0>><<goto "END">><</if>>
<<if $points is 100>><<set $level++, $point to 0>><</if>>
<<if not tags().includes('noreturn')>><<set $return to passage()>><</if>>
: : PassageDone
<<if tags().includes('bar')>><<addclass ".bottle" "empty">><</if>>
}}}
> Note: for some functionality (like [[overriding navigations|Basic-API-Navig]] or [[Arbitrarily long returns|Long-Return-JS]]), it may be best to use JavaScript instead.
\
<h3>{{{PassageReady}}} or {{{PassageDone}}}</h3>\
While the passages will allow most code on the page (aside from DOM macros ([[text|Macro-ApPreRepCopy]]/[[class|Macro-DOM-Adv]]), which should only be added to {{{PassageDone}}}), whether a code is loaded before or after the passage is rendered will affect the development of the story.
{{{
Loading order:
PassageReady
PassageHeader
the content of the current Passage
PassageFooter
PassageDone
}}}
> The full ordered lists of events happening when a new passage is rendering can be found in the [[documentation|http://www.motoslave.net/sugarcube/2/docs/#events-navigation]].
As such, the code in the earlier passage will affect the code of the later one. Assuming that {{{$var is 2}}} before moving to a passage:
{{{
: : Next Passage
<<if $var is 2>>
The dog sleeps in the cottage.
<<elseif $var is 1>>
The dog yaps at the door.
<<else>>
The dog is not here.
<</if>>
}}}
If the value of {{{$var}}} is changed in {{{PassageReady}}}, the displayed sentence will be different than if it was changed in {{{PassageDone}}}.
<div id="link-menu">[[Back to the Special Passages and Tags Menu|Special-Tags]] - [[Back to the Start Menu|Start]]</div><h1>Special Tags creating Special Passages and Functionalities</h1>
Along with [[Special Passages|Special-Passage]], SugarCube uses special passage tags to either create new Special Passages or affect the passage itself.
> Note: only uses those tags when needed, as it can affect how Twine loads the project.
To add a tag to a passage on Twine, open the relevant passage, click {{{+ Tag}}} in the passage menu, and fill in the blanks. If a tag has been assigned to another passage, it will show in the {{{Add Tag}}} listbox. You can also assign a colour to the tag.
For Twee files, add the tag inside {{{[ ]}}} next to the passage name. For tags with multiple words, add a {{{-}}} between them ({{{[like-this]}}}) For multiple tags, add a space in between ({{{[nobr widget]}}}).
\
<h3>{{{nobr}}}</h3>\
Like the [[macro of the same name|Macro-Nobr-Silent]], the {{{nobr}}} tag removes every break to a new line in the passage. However, unlike the macro, it will affect the whole passage, rather than a part of it. This tag is most useful in passages with a lot of code, like a widget passage.
{{{
: : Passage [nobr]
This passage will not have line breaks.
Even if the code is formatted with line breaks.
}}}
> Note: to target the whole project rather than a passage, it is best to use the [[Config.nobr|Basic-API-Config]] API instead.
\
<h3>{{{widget}}}</h3>\
As the name suggest, this tag is meant to create a special passage to set up {{{<<widget>>}}} [[macros|Macro-Widget]].
{{{
: : Some Widgets [widget]
<<widget "Test">>this is a test widget<</widget>>
}}}
> Note: while you can have multiple passages with this tag, it is recommended to keep it to a minimum.
\
<h3>{{{bookmark}}}</h3>\
This widget is meant to populate the [[JumpTo Functionlity|Basic-API-UI]], to go back in the player history.
{{{
: : Passage [bookmark]
If the player read this passages, it will appear in the JumpTo dialog box.
}}}
> Note: if JumpTo is not used in a project, you can use this tag as if it were a "regular" tag.
\
<h3>{{{script}}}</h3>\
This tag is meant to tell Twine that this passage only contains JavaScript code. It is not necessary for Twine users, as JavaScript code should be placed in the {{{Edit JavaScript}}} passage, in the //Story// menu.
As for Twee files, it is only necessary if the file should be imported into the Twine app, and only one passage should be tagged as such. In the case of using a compiler, it is recommended to simply use a separate {{{.js}}} file (or multiple files) rather than create a {{{script}}} tagged passage.
{{{
: : The JavaScript Code [script]
}}}
\
<h3>{{{stylesheet}}}</h3>\
This tag is meant to tell Twine that this passage only contains CSS code. It is not necessary for Twine users, as CSS code should be placed in the {{{Edit Stylesheet}}} passage, in //Story// the menu.
As for Twee files, it is only necessary if the file should be imported into the Twine app, and only one passage should be tagged as such. In the case of using a compiler, it is recommended to simply use a separate {{{.css}}} file (or multiple files) rather than create a {{{stylesheet}}} tagged passage.
{{{
: : The CSS Code [stylesheet]
}}}
\
<h3>{{{init}}}</h3>\
This tag is meant to be used for add-ons/library, as it loads at the beginning initialization. It creates a passage that works like {{{StoryInit}}}. However, for 99% of projects created in Twine, this tag is unnecessary. Instead, the Special passage {{{StoryInit}}} should be used.
{{{
: : initialization [init]
}}}
<div id="link-menu">[[Back to the Special Passages and Tags Menu|Special-Tags]] - [[Back to the Start Menu|Start]]</div><h1>Customising Passages with Tags</h1>
Aside from [[creating Spcial Passages or Functionalities|Tags-Built]], tags can also be used to customise how a passage looks. For example, if multiple passages are set in a forest, one can add a tag called {{{forest}}} to those passages, and use this tag to set an image of a forest in the background of those passages.
To add a tag to a passage on Twine, open the relevant passage, click {{{+ Tag}}} in the passage menu, and fill in the blanks. If a tag has been assigned to another passage, it will show in the {{{Add Tag}}} listbox. You can also assign a colour to the tag.
For Twee files, add the tag inside {{{[ ]}}} next to the passage name. For tags with multiple words, add a {{{-}}} between them ({{{[like-this]}}}) For multiple tags, add a space in between ({{{[nobr widget]}}}).
Adding a tag to a passage creates:
* a data-tag on {{{html}}}, {{{body}}}, and {{{.passage}}}
* a CSS class on {{{body}}} and {{{.passage}}}
Both the data-tag and class can be used in the Stylesheet to edit aspects of the page, but are coded differently. The data-tag will keep the formatting of the inserted tag (case-sensitive and punctuation), while the class will transform it into a lowercase string and without punctuation (save for {{{-}}}).
{{{
For a tag called: The-Name-Of-The-Tag:
[data-tags~="the-name-of-the-tag"]
.the-name-of-the-tag
For a tag called: Super!
[data-tags~="Super!"]
.super
For a tag called: This-1
[data-tags~="This-1"]
.this-1
}}}
As for positioning the data-tag or class on an element, you need to take into account the order of CSS rules and where the tags are located. For example:
{{{
html[data-tags~="forest"] { background-image: url(forest-bg.jpg); }
→ will change the background to an image of a forest, because there is a data-tag on "html"
html.forest { background-image: url(forest-bg.jpg); }
→ will not do anything, because there is no class on "html"
html .forest { background-image: url(forest-bg.jpg); }
→ will add the image as a background to every element inside "html" with the class "forest"
}}}
> Note: it is recommended to be specific when targeting an element (so not like the last example), to avoid adding unnecessary rules to elements.
> Note 2: class can still be added to the {{{html}}} element, in the JavaScript passage, jQuery code or [[DOM Macros|Macro-DOM-Adv]].
Other examples:
{{{
Targeting a child element:
html[data-tags~="forest"] .passage { color: darkgreen; }
→ will change the font colour of ".passage" if the passage is tagged "forest"
body[data-tags~="forest"] a { color: green; }
→ will change the colour of every link inside "body"
Targeting an element without "body":
[data-tags~="forest"] #ui-bar {background: red;}
.forest #ui-bar {background: red;}
→ will change the background colour of the sidebar
}}}
> Note: Data-Tags are prefered over classes, because it is more stable (i.e. won't be messed up by custom macros or third party code).
<div id="link-menu">[[Back to the Special Passages and Tags Menu|Special-Tags]] - [[Back to the Start Menu|Start]]</div><h1>The Settings APIs</h1>
Settings can be a great way to customise your project, and make it more accessible for players. Whether it is to change the visual aspect (font, theme, etc), the audio (volume, track), or overall mechanics (difficulty, annimation), there are many ways to reach your goal.
While including settings in a project can feel a bit overwhelming, as they //will// require some knowledge of JavaScript, the Setting APIs are there to make things easier. There are also many UI templates out there including some settings. You can find also find a [[Setting-Only Template here|https://manonamora.itch.io/twine-sugarcube-templates]].
The basic Settings API is built in this format:
{{{
Settings.function(parameters)
}}}
> Note: The order you add the settings in the JavaScript passage will be the order you will see in the Setting dialog box.
* [[Adding Headers|SettingsHeader]]
* [[Creating a Toggle Setting|SettingsToggle]]
* [[Creating a List Setting|SettingsList]]
* [[Creating a Slider|SettingsRange]]
* [[Going Further with Settings|Settings-More]]
> Note: you can find a Setting Template with the most useful settings for Interactive Fiction on my [[itch page|https://manonamora.itch.io/twine-sugarcube-templates]]
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>Adding Headers</h1>
If you want to customise the Setting Dialog Box or organise your settings, you can group those under a Header. This will indicate to users what kind of setting they can expect below.
This API has 2 parameters :
* {{{name}}}: the name of the header (string)
* {{{desc}}}: description of the group of settings (string, optional)
{{{
Setting.addHeader(name [, description])
}}}
Examples:
{{{
Only a header
Setting.addHeader("Font Settings");
A header and a description
Setting.addHeader("Font Settings", "Settings controlling how the text is formatted.");
}}}
<div id="link-menu">[[Back to the Settings API Menu|Settings]] - [[Back to the Start Menu|Start]]</div><h1>Creating a Toggle Setting</h1>
Like the name suggests, this type of settings create a toggle. This type is best used for settings with a True/False options. For example: toggling a widescreen or autosave.
To add a Toggle setting, you need the followin API:
{{{
Setting.addToggle(name, definition)
}}}
This API has 2 main parameters:
* {{{name}}}: the name of the settings variable (string)
* {{{definition}}}: definition of the setting (object)
The //definition// object has multiple options:
* {{{label}}}: visible description of the setting (string)
* {{{desc}}}: further description of the setting (string, optional)
* {{{default}}}: default value for the setting (boolean, optional, undefined = false)
* {{{onInit}}}: the function to call when the game starts (optional, function)
* {{{onChange}}}: the function to call when the setting is changed (optional, function)
> Note: You can use a setting as a variable in a passage. You would write the variable as such:
{{{settings.name}}}
Examples:
{{{
Basic Toggle Setting to create a boolean setting
Setting.addToggle("notifications", {
label : "Show notifications?"
});
→ the default value not defined, so false is used
You can then use this in a passage as such:
<<if settings.notifications is true>> your code/text <</if>>
}}}
{{{
Toggle Setting to add/remove a CSS class
var settingNotifications = function () {
if (settings.notifications) { // is true
$("html").addClass("notifications");
}
else { // is false
$("html").removeClass("notifications");
}
};
Setting.addToggle("notifications", {
label : "Display Notifications?",
desc : "If enabled, you will be shown notifications throughout the game",
default : false,
onInit : settingNotifications,
onChange : settingNotifications
});
In your CSS, you'll need to include the needed code
html.notifications .macro-notif {
display: none;
}
}}}
<div id="link-menu">[[Back to the Settings API Menu|Settings]] - [[Back to the Start Menu|Start]]</div><h1>Creating a List Setting</h1>
Like the name suggests, this type of settings create a list. This type is best used for settings with more than 2 options or options with names. For example: a theme change setting or font settings.
To add a Toggle setting, you need the followin API:
{{{
Setting.addList(name, definition)
}}}
This API has 2 main parameters:
* {{{name}}}: the name of the settings variable (string)
* {{{definition}}}: definition of the setting (object)
The //definition// object has multiple options:
* {{{label}}}: visible description of the setting (string)
* {{{list}}}: the list of options (array of string)
* {{{desc}}}: further description of the setting (string, optional)
* {{{default}}}: default value for the setting (string from array, optional, undefined = 1st of array)
* {{{onInit}}}: the function to call when the game starts (optional, function)
* {{{onChange}}}: the function to call when the setting is changed (optional, function)
> Note: You can use a setting as a variable in a passage. You would write the variable as such:
{{{settings.name}}}
Examples:
{{{
Basic List Setting, creating a string setting variable
Setting.addList("difficulty", {
label : "Choose a difficulty level.",
list : ["Easy", "Normal", "Hard", "INSANE"],
default : "Normal"
});
In a passage:
<<if settings.difficulty is "Normal">> your code/text <</if>>
}}}
{{{
List Setting to add/remove a CSS class
var settingThemeNames = ["Base", "Reverse", "Night", "Light"];
var settingThemeHandler = function () {
var $html = $("html");
// remove any existing theme class
$html.removeClass("theme-reverse theme-night theme-light");
// switch on the theme name to add the requested theme class
switch (settings.theme) {
case "Reverse":
$html.addClass("theme-reverse");
break;
case "Night":
$html.addClass("theme-night");
break;
case "Light":
$html.addClass("theme-light");
break;
}
};
Setting.addList("theme", {
label : "Choose a theme.",
desc : "This will change the colour palette"
list : settingThemeNames,
default : "Base"
onInit : settingThemeHandler,
onChange : settingThemeHandler
});
In your CSS:
body {color: black;}
html.theme-reverse body {color: white;}
html.theme-night body {color: lightgrey;}
html.theme-light body {color: darkgrey;}
}}}
<div id="link-menu">[[Back to the Settings API Menu|Settings]] - [[Back to the Start Menu|Start]]</div><h1>Creating a Slider</h1>
Like the name suggests, this type of settings create a slider. This type is best used for settings with a range of value. For example: a a volume.
To add a Toggle setting, you need the followin API:
{{{
Setting.addRange(name, definition)
}}}
This API has 2 main parameters:
* {{{name}}}: the name of the settings variable (string)
* {{{definition}}}: definition of the setting (object)
The //definition// object has multiple options:
* {{{label}}}: visible description of the setting (string)
* {{{min}}}: the minimum value (number)
* {{{max}}}: the maximum value (number)
* {{{step}}}: the increment between each step (number, divisible by min & max)
* {{{desc}}}: further description of the setting (string, optional)
* {{{default}}}: default value for the setting (boolean, optional, undefined = false)
* {{{onInit}}}: the function to call when the game starts (optional, function)
* {{{onChange}}}: the function to call when the setting is changed (optional, function)
Examples:
{{{
Basic Range Setting
Setting.addRange("masterVolume", {
label : "Volume Level",
min : 0,
max : 10,
step : 1,
default : 10,
onChange : function () {
SimpleAudio.volume(settings.masterVolume / 10);
}
});
}}}
<div id="link-menu">[[Back to the Settings API Menu|Settings]] - [[Back to the Start Menu|Start]]</div><h1>Going Further with Settings</h1>
The settings are not just stuck to the JavaScript passage, they can also be used in regular passages.
\
<h3>The {{{settings}}} variable</h3>\
When a Setting is set, it creates a special variable that can be used in other passages, for example to trigger code.
{{{
settings.nameOfTheSetting
}}}
Assuming that a setting has been set up with the name {{{notification}}}:
{{{
For a Toggle Setting:
<<if settings.notification>>
<<notify 5s>>This is a notification only seen if the notification setting is toggled on<</notify>>
<</if>>
For a Range Setting:
<<if settings.notification gt 9>>
<<notify 5s>>This is very loud!<</notify>>
<</if>>
For a List Setting:
<<if settings.notification is "Easy">>
<<notify 5s>>You are playing on BabyMode<</notify>>
<</if>>
}}}
> Note: the {{{<<notify>>}}} macro is a [[Custom Macro by Chapel|https://github.com/ChapelR/custom-macros-for-sugarcube-2/blob/master/docs/notify-macro.md]].
\
<h3>Changing the Settings in the Passage</h3>\
It is also possible to change settings outside of the Settings Dialog Box, and can be done with {{{Setting.reset()}}} to reset a/all setting(s) to their default value, or {{{Setting.save()}}} to save the change of a setting.
> Note: the targetted setting needs to be set in the JavaScript beforehand.
> Note 2: you need to use the macros {{{<<script>>}}} or {{{<<run>>}}} with those APIs.
To reset:
{{{
Setting.reset() → will reset all settings to the default
Setting.reset('difficulty') → will reset only the 'difficulty' setting
<<run Setting.reset()>>
}}}
To save:
{{{
<<set settings.difficulty to "Normal">>
<<run Setting.save()>>
}}}
> Note: this can be quite useful when setting some functionality before the game starts, like the game's Language.
> Note: a {{{Setting.load()}}} API exists within SugarCube. However, it is called automatically everytime the game is loaded. As such, it should never be called manually.
<div id="link-menu">[[Back to the Settings API Menu|Settings]] - [[Back to the Start Menu|Start]]</div><h1>Basic Special Passages</h1>
To customise your project further, you can make use of SugarCube's special passages. To do so, create a new passage, and indicate the Special Passages Name in the passage's name, as it is indicated in the [[Documentation|http://www.motoslave.net/sugarcube/2/docs/#special-passages]]. The name for those Special Passages is case-sensitive!
* [[Headers and Footers|SP-HeaderFooter]]
* [[Special Passages for the UI Bar|SP-UIBar]]
* [[Setting Important Variables before Start|SP-Init]]
You can click here for the [[demo|SP-Demo]] to see most of these Special Passages in action!
<div id="link-menu">[[Back to the Start Menu|Start]]</div><h1>Headers and Footers</h1>
Whether to display Chapter titles or links to certain passages, the Headers and Footers are attached respectively on top of and under the passage. You can include simple text, or more complex code to load with the passage.
For example:
{{{
: : PassageHeader
<<if def $chapter>>Chapter $chapter<</if>>
: : PassageFooter
<<if $name is "Jane">>[[Jane's Curiosities|Inventory]]<<else>>[[$name + "'s closet"|Inventory]]<</if>>
}}}
> Note: if you are looking to add plain code without output (visible text), {{{PassageReady}}} and {{{PassageDone}}} is preferred. See [[this page|SP-PassageReady-Done]].
<div id="link-menu">[[Back to the Special Passages Menu|Special-Passage]] - [[Back to the Start Menu|Start]]</div><h1>Special Passages for the UI Bar</h1>
The left-side bar can be pretty bare without some customisation, which is what the Special Passages below can offer. From adding images, changing the title, adding extra text or links, there are many options. The passages listed below are organised in the order they would appear in the UI Bar.
> Note: the UI Bar will update when the player moves to another passage.
\
<h3>{{{StoryBanner}}}</h3>\
As its name implies, you can add a banner or icon in this passage, located above the title of the game. But you are not limited to an image, you can include text or code!
{{{
: : StoryBanner
<img src="extra/logo.png">
}}}
> Note: if you want to edit how this passage looks directly from the StyleSheet, you can target the element {{{#story-banner}}}
\
<h3>{{{StoryDisplayTitle}}}</h3>\
When this Special Passage is not in use, Twine takes the name of the project as the title to display. If you would rather have something different, you can use this Special Passage name to change it.
The Passage also allows for whatever text, image, or code you'd want.
{{{
: : StoryDisplayTitle
The Road Not Taken
}}}
> Note: This element has some special formatting, which you change in the StyleSheet by targetting the element {{{#story-title}}}
\
<h3>{{{StorySubtitle}}}</h3>\
This Special Passage will appear under the title, and is meant to show a tagline for the game, but you can include any text or image or code you'd want.
{{{
: : StorySubtitle
It's time to make a choice!
}}}
> Note: if you want to edit how this passage looks directly from the StyleSheet, you can target the element {{{#story-subtitle}}}
\
<h3>{{{StoryAuthor}}}</h3>\
This Special Passage is meant to display the author of the grame, but you can also include any text or image or code you'd want.
{{{
: : StoryAuthor
by [[manonamora|https://manonamora.itch.io/]]
}}}
> Note: This element has some special formatting, which you change in the StyleSheet by targetting the element {{{#story-author}}}
\
<h3>{{{StoryCaption}}}</h3>\
This Special Passage provides an extra space to include text or other elements. It is often used to show extra links towards side passage, like a Codex, or the state of certain variables, like a health bar.
{{{
: : StoryCaption
Coins: $coins
[[Codex]]
}}}
> Note: This element has some special formatting, which you change in the StyleSheet by targetting the element {{{#story-caption}}}
\
<h3>{{{StoryMenu}}}</h3>\
This passage adds a block for extra links, formatted in the same way as the Save and Restart buttons. Unlike the Special Passages listed above, this one ''only'' accepts links!
{{{
: : StoryMenu
[[Inventory]]
[[$name|MC Page]]
}}}
> Note: This element has some special formatting, which you change in the StyleSheet by targetting the element {{{#menu-story}}}
\
<h3>{{{StoryShare}}}</h3>\
This Special Passage creates a //Share// button below the //Restart// button and is meant to display social media links in a dialog box. However it can only be filled with links. If you want to display text with your links, I would recommend creating a regular passage and add that to the StoryMenu instead.
{{{
: : StoryShare
[[itch|https://manonamora.itch.io/]]
}}}
<div id="link-menu">[[Back to the Special Passages Menu|Special-Passage]] - [[Back to the Start Menu|Start]]</div><h1>Setting Important Variables before Start</h1>
Some projects may require to have some variables set in advance, for the game to progress as it should, or to include macro or custom code to load ahead of its use, like for the [[audio|Macro-Audio]] or stats bars.
{{{
: : StoryInit
<<set $var to "Jane">>
<<set $object to {
property1: 1,
property2: "Home",
property3: true
}>>
<<cacheaudio "rain" "extra/rain.mp3">>
}}}
<div id="link-menu">[[Back to the Special Passages Menu|Special-Passage]] - [[Back to the Start Menu|Start]]</div>There is not much to say about the demo. I think the Special Passages speak for themselves.
<<back "Click Here to Go back">><h1>About JavaScript and the StyleSheet</h1>
To customise your project futher, Twine gives you the possibility to use JavaScript and CSS, which you can edit in the //JavaScript// and //StyleSheet// passages under the Story Menu in the Twine app.
\
<h3>JS - JavaScript</h3>\
''JavaScript'' (or JS) is a coding language used in HTML files that will dictate the behaviour of elements on the page. When you click on a link to change the passage to a new one, it is because the JavaScript code is telling the page to do so. The macros in SugarCube are built on JavaScript.
The most common use for JavaScript in a project is:
* to add custom macro for effect not available in the base SugarCube
* to add settings to change how the project looks/acts for the player
* to change how the page looks/behaves (ex: removing the history arrows)
You could potentially build a whole SugarCube project by only using JavaScript, though it is not recommended...
> Note: SugarCube also uses jQuery, which is a sub-language of JavaScript, used for navigation, selecting elements or control animation.
> Note 2: Java and JavaScript are two different coding languages, with no link between each other aside from its name.
\
<h3>CSS - Cascading Style Sheet</h3>\
''Cascading Style Sheet'' (or CSS) is a coding language used in HTML files to dictate the layout and formatting of the page. From the choice of backgrond to the placement of an element, this is usually done in with CSS (note: some aspects can be changed in JavaScript). The language allows for alternate rules for different settings or screen size, as well as animation.
The most common use for CSS in a project is:
* to change the basic formatting of a page (ex: colour scheme)
* to have alternate rules for coded settings in the JavaScript (ex: font family)
* to have a different formatting of the page on mobile
> Note: in SugarCube, you can edit some styling with the [[Markup formatting]]. For futher use of CSS, see [[this page|Int-JS-CSS]].
\
<h3>Learn more about JavaScript, jQuery, and CSS</h3>\
* the [[W3 School|https://www.w3schools.com/]] has the most beginner explanations, and lets you test and edit their examples.
* [[MDN Web Docs|https://developer.mozilla.org/en-US/]] is more technical but provides a more extensive documentation.
* [[jQuery|https://jquery.com/]] has also a special documentation website.
<div id="link-menu">[[Back to the Start Menu|Start]]</div>