Javascript Macros
X-Change Life uses a customized version of the Twine Harlowe engine. The following custom macros are for modders – these are some macros we have added to Twine Harlowe in order to extend its functionality.
1. average
Function: Calculates the average of a series of numbers.
Usage:
(set: $avg to (average: 1, 2, 3, 4, 5)) <!-- $avg will be 3 -->
2. rnd
Function: Rounds a number to a specified precision.
Usage:
(set: $rounded to (rnd: 3.14159, 2)) <!-- $rounded will be 3.14 -->
3. indexof
Function: Finds the 1-based index of an item in an array. Returns -1 if the item is not found.
Usage:
(set: $index to (indexof: (a: "apple", "banana", "cherry"), "banana")) <!-- $index will be 2 -->
4. intersection
Function: Calculates the intersection of two arrays, returning their common elements.
Usage:
(set: $common to (intersection: (a: "apple", "banana"), (a: "banana", "cherry"))) <!-- $common will be (a: "banana") -->
5. savegameto
Function: Saves the game to the specified slot name.
Usage:
(savegameto: "slot1") <!-- Saves the game to slot "slot1" -->
6. win
Function: Checks if the variable $result
is “pass”.
Usage:
(set: $result to "pass")
(set: $didWin to (win:)) <!-- $didWin will be true -->
7. is_fem
Function: Checks if the character’s gender is female.
Usage:
(set: $character to (dm: "gender", "female"))
(set: $isFemale to (is_fem:)) <!-- $isFemale will be true -->
8. is_male
Function: Checks if the character’s gender is male.
Usage:
(set: $character to (dm: "gender", "male"))
(set: $isMale to (is_male:)) <!-- $isMale will be true -->
9. is_preg
Function: Checks if the character is pregnant.
Usage:
(set: $character to (dm: "pregnant", "true"))
(set: $isPregnant to (is_preg:)) <!-- $isPregnant will be true -->
10. knows_preg
Function: Checks if the character’s pregnancy is known.
Usage:
(set: $character to (dm: "pregnancy known", "true"))
(set: $knowsPregnancy to (knows_preg:)) <!-- $knowsPregnancy will be true -->
11. is_bim
Function: Checks if the character has the “bimbo” side effect.
Usage:
(set: $character to (dm: "side effects", (a: "bimbo")))
(set: $isBimbo to (is_bim:)) <!-- $isBimbo will be true -->
12. is_pp
Function: Checks if the character has the “people pleaser” side effect.
Usage:
(set: $character to (dm: "side effects", (a: "people pleaser")))
(set: $isPeoplePleaser to (is_pp:)) <!-- $isPeoplePleaser will be true -->
13. pill
Function: Checks if the value of $pill_taken
matches the provided pill name (case-insensitive).
Usage:
(set: $pill_taken to "Cum-Cure")
(set: $isCumCure to (pill: "cum-cure")) <!-- $isCumCure will be true -->
14. clamp
Function: Clamps a number within a specified range.
Usage:
(set: $clampedValue to (clamp: 15, 10, 20)) <!-- $clampedValue will be 15 -->
(set: $clampedValue to (clamp: 25, 10, 20)) <!-- $clampedValue will be 20 -->
15. currency
Function: Formats a number as currency (USD) without cents.
Usage:
(set: $formattedCurrency to (currency: 1234)) <!-- $formattedCurrency will be "$1,234" -->
16. del
Function: Deletes the specified variables.
Usage:
(del: "$variable1", "$variable2") <!-- Deletes $variable1 and $variable2 -->
17. outfitdb
Function: Retrieves a list of outfits for a specified character, optionally filtered by outfit IDs.
Usage:
(set: $outfits to (outfitdb: "characterName")) <!-- Retrieves all outfits for "characterName" -->
(set: $filteredOutfits to (outfitdb: "characterName", (a: "outfit1", "outfit2"))) <!-- Retrieves specific outfits for "characterName" -->
18. getoutfit
Function: Retrieves details of a specific outfit by its ID.
Usage:
(set: $outfitDetails to (getoutfit: "characterName category outfitName")) <!-- Retrieves details of the specified outfit -->
19. checkdm
Function: Checks if a datamap contains a specified value based on an operation.
Usage:
(set: $dm to (dm: "key1", "value1", "key2", (a: "value2", "value3")))
(set: $result1 to (checkdm: $dm, "key1", "is", "value1")) <!-- $result1 will be true -->
(set: $result2 to (checkdm: $dm, "key2", "contains", "value2")) <!-- $result2 will be true -->
20. newseed
Function: Generates a new seed based on the current time.
Usage:
(set: $seed to (newseed:)) <!-- Generates a seed string based on the current time -->
21. clearstandardvars
Function: Clears standard variables.
Usage:
(clearstandardvars:) <!-- Clears standard variables -->
22. twist
Function: Generates a random integer between a specified minimum and maximum value (inclusive) using the Mersenne Twister algorithm.
Usage:
(set: $randomNumber to (twist: 1, 10)) <!-- Generates a random number between 1 and 10 using Mersenne Twister algorithm -->
Note: This macro uses the Mersenne Twister algorithm, which provides a higher degree of randomness compared to Harlowe’s native randomness functions.
23. twirl
Function: Picks a random value from a list of arguments using the Mersenne Twister algorithm.
Usage:
(set: $randomValue to (twirl: "apple", "banana", "cherry")) <!-- Picks a random fruit from the list using Mersenne Twister algorithm -->
Note: This macro uses the Mersenne Twister algorithm, which provides a higher degree of randomness compared to Harlowe’s native randomness functions.
24. twisted
Function: Shuffles an array using the Fisher-Yates algorithm with the Mersenne Twister algorithm for randomness.
Usage:
(set: $shuffledArray to (twisted: (a: "apple", "banana", "cherry"))) <!-- Shuffles the array using Fisher-Yates algorithm with Mersenne Twister algorithm -->
Note: This macro uses the Mersenne Twister algorithm, which provides a higher degree of randomness compared to Harlowe’s native randomness functions.
25. remove
Function: Removes a specified number of occurrences of an item from an array.
Usage:
(set: $originalArray to (a: "apple", "banana", "cherry", "apple"))
(set: $modifiedArray to (remove: $originalArray, "apple", 1)) <!-- Removes one occurrence of "apple" -->
Harlowe Macros
There are custom harlowe macros that you can also use. These are slightly different than the ones above since they perform native harlowe functions, opposed to the ones above that do background things in javascript. These are usually utility macros that shorten other functions or allows you to cut out repeated tasks.
🎥 Media & Visuals
$pic
Parameters:(str) image_path
, (str) position = "left"
, (str) css_class = "small"
Function:
Displays an image from the img/
folder. Optional parameters adjust position and CSS class. "small"
sets width to 50%.
Usage Examples:
($pic:"places/gym/locker room.jpg")
($pic:"places/gym/locker room.jpg","left")
($pic:"places/gym/locker room.jpg","right","small")
$vid
Parameters:(str) video_path
, (str) position = "left"
Function:
Embeds an autoplaying, looping video with mute behavior determined by $audio_toggle
. Optional "left"
or "right"
positions it using top_left_pic
or top_right_pic
.
Usage Examples:
($vid:"scenes/characters/jade/sex/workout/02 get towel.mp4")
($vid:"scenes/characters/jade/sex/workout/02 get towel.mp4","left")
🖼 Display & Styling
$centered
Parameters:(codehook) _content
Function:
Wraps content in a centered <div class='options'>
block. Used to center text or UI blocks visually.
Usage Examples:
($centered: ["You feel warm and slutty inside."])
($centered: [(print:"<b>Warning:</b> You're being watched.")])
$highlight
Parameters:(codehook) _content
Function:
Displays the content inside a <span class='highlight'>
, useful for drawing attention to text.
Usage Examples:
($highlight: ["Objective Updated!"])
($highlight: [(print:$her_name + " seems impressed.")])
$shadow
Parameters:(codehook) _content
Function:
Displays the content inside a <span class='shadow'>
for stylized text with a drop-shadow effect.
Usage Examples:
($shadow: ["Your heart skips a beat."])
($shadow: [(print:"Round " + $round_number)])
$bimbo
Parameters:(codehook) _content
Function:
Wraps the content in a <span class='bimbo'>
and centers it in a <div class='options'>
. Used for bimbo-styled thoughts or narration.
Usage Examples:
($bimbo: ["Like, I dunno what that means... but it sounds sexy! 💋"])
($bimbo: [(print:"Ughhh... math is, like, soooo hard!")])
$bimbo_dialogue
Parameters:(codehook) _content
Function:
Displays the content as bimbo-styled dialogue wrapped in quotation marks so you don’t have to add them.
Usage Examples:
($bimbo_dialogue: [Omigod, did you, like, feel that too?])
($bimbo_dialogue: [(twirl:
"This is like, so totally embarrassing... *nervous giggle*",
"Omigosh, I'm like, so sorry! Was I using too much teeth? My jaw's just sooo tiny compared to your huge-")])
$heading
Parameters:(str) _text
Function:
Displays _text
in a large heading styled using the palette color, with a shadow effect.
Usage Examples:
($heading: "New Objective")
($heading: "Alexia’s Bedroom")
$notification
Parameters:(str) _message
Function:
Displays _message
inside a <mark>
block that fades in and out automatically.
Usage Examples:
($notification: "You gained 1 charm.")
($notification: "Your outfit is now dirty.")
$notification_still
Parameters:(str) _message
Function:
Displays _message
inside a non-animated <mark>
block. Remains visible until removed by logic.
Usage Examples:
($notification_still: "Your makeup has worn off.")
($notification_still: "You have unread messages.")
🔊 Audio & Sound Control
$play
Parameters:(any) type
, (str) track
, (str) delay = "none"
Function:
Plays a sound or music track. Supports custom routing based on type:
"sound"
,"sex loop"
,"ambience"
,"song"
- Directory-specific:
"scene"
,"story"
,"secretary"
,"workout"
Usage Examples:
($play:"sound","wet_squish") <!-- Plays a sound effect immediately -->
($play:"ambience","cafe") <!-- Plays ambience immediately -->
($play:"sex loop","slow_ride") <!-- Loops a sex sound -->
($play:"scene","thwack","2s") <!-- Delays playback 2 seconds -->
($play:"song no loop","main_theme") <!-- Plays a song once without looping -->
💬 Text & Language Tools
$caps
Parameters:(str) sentence
Function:
Capitalizes the first letter of each word in the string.
Usage Examples:
(set:_title to ($caps:"just another slutty day")) (print:_title) <!-- Output: Just Another Slutty Day -->
(print: $caps's "turn me into a girl") <!-- Output: Turn Me Into A Girl -->
💾 Storage Macros
$get_session_storage
/ $get_local_storage
Parameters:(str) name
, (any) default
Function:
Reads a value from browser session or local storage. Returns the default if nothing is found.
Usage Examples:
(set:_mood to ($get_session_storage:"last_mood","bored"))
(set:_flags to ($get_local_storage:"debug_flags",(a:)))
$set_session_storage
/ $set_local_storage
Parameters:(str) name
, (any) value
Function:
Saves a value into session or local storage.
Usage Examples:
($set_session_storage:"last_mood","humiliated")
($set_local_storage:"debug_flags",(a:"showIDs"))
$delete_global_variable
Parameters:(str) var_name
Function:
Resets a named variable by setting it to 0. Used to “delete” global state cleanly.
Usage Examples:
($delete_global_variable:"$her_name") <!-- Resets $her_name to 0 -->
$use_global
Parameters:(str) var_name
, (str) js_var_name
, (codehook) hook
Function:
Temporarily loads a JS value, runs a hook with it, then resets the Twine variable.
Usage Examples:
($use_global: "$scene_select", "window.GE.scene_select", [(set:$scene to $scene_select)])
🧪 Logic & Utility
$char_passage
Parameters:(str) base_passage
, (codehook) core
, (codehook) fallback
Function:
Tries to display a character-specific version of a passage for non-base girls (modded). Falls back to a default block if none exists.
Usage Examples:
($char_passage:"sex transactional kiss",[
(set:$kiss_variant to (cond:
$character's "race" is "white", "kiss " + (text:(twist:1,3)),
$character's "race" is "latin", "kiss " + (text:(twist:4,6)),
$character's "id" is "asian", "kiss " + (text:(twist:7,8)),
$character's "id" is "black", "kiss " + (text:(twist:9,10)),
"kiss"
)
)],[(set:$kiss_variant to "kiss")])
$passage_tags
Parameters:(str) tag
Function:
Inserts a “blank” section with the assigned tag, so modders can inject code into this location. Popular for options like adding a new button in a set list of options – mall locations, pills, etc.
Usage Examples:
($passage_tags:"bar_options")
<!--
Then you'd inject code into that spot like this:
:: new bar options [bar_options]
{(link:"yell at a patron")[etc]}
-->
$rnd
Parameters:(num) value
, (num) precision
Function:
Rounds a number to a given decimal precision.
Usage Examples:
(set:_chance to ($rnd:0.75488,2)) <!-- _chance = 0.75 -->
(print: $rnd:12.347,1) <!-- Output: 12.3 -->
$clamp
Parameters:(num) value
, (num) min
, (num) max
Function:
Limits a value between a minimum and maximum. If the value is lower than min, returns min; if higher than max, returns max.
Usage Examples:
(set:_speed to ($clamp:12,5,10)) <!-- _speed = 10 -->
(set:_volume to ($clamp:-3,0,100)) <!-- _volume = 0 -->
(set:_sanity to ($clamp:$sanity,0,100)) <!-- Ensures stat stays in bounds -->
🧠 Mood & Status
$set_mood
Parameters:(str) mood_name
, (str) reason
Function:
Sets the current mood, including icon, stat changes, and duration. Triggers mood refresh visuals. Mood must exist (current existing moods are “awesome”, “bored”, and “humiliated”.)
Usage Examples:
($set_mood:"humiliated","because ' + (text: $her_name) + ' rejected you due to your small cock.")
($set_mood:"bored","because you've been hanging around the house too much recently!")
$set_status
Parameters:(str) status_name
, (str) reason
Function:
Adds a temporary status effect that modifies charm, intellect, or fitness. Triggers status display and stat refresh. Status must exist (current existing statuses are “cum breath”, “nasty cum breath”, “cum shoes”, “walking funny”.)
Usage Examples:
($set_status:"cum breath","' + (text: $npc's "sex name") + ' came in your mouth, and your breath smells...")
($set_status:"walking funny","You're not walking straight... maybe because your ass was so ruthlessly physically dominated in that machine...")
🕹 Game Interaction
$register_orgasm
Parameters:
None
Function:
Logs an orgasm event, resets arousal, reduces action points, and updates stats.
Usage Examples:
($register_orgasm:) <!-- Call at the end of orgasm scenes -->
$simple_option
Parameters:(str) result
, (...str) labels
Function:
Creates simple clickable links to set $choice
and optionally go to next
, display
, or use nostop
logic.
Usage Examples:
($simple_option:"passage","transition type (optional)","choice 1","choice 2","choice 3") <!-- Any number of choices -->
($simple_option:"buy flowers","Daisies","Roses","Lilies")
<!-- ^ this is the same as
(link:"Daisies")[(set:$choice to "Daisies")($cs:"buy flowers")
(link:"Roses")[(set:$choice to "Roses")($cs:"buy flowers")
(link:"Lilies")[(set:$choice to "Lilies")($cs:"buy flowers")
-->
if you add "display" then it uses (display:) instead of ($cs)
($simple_option:"buy flowers","display","Daisies","Roses","Lilies")
if you use "next", then it uses ($nx) instead.
($simple_option:"buy flowers","next","Daisies","Roses","Lilies")
$cs
Parameters:(str) passage_name
Function:
Sets $next
and displays the "change screen"
passage.
*Special note: Calling this will clear the content on the “center screen” and replace it with the passage that you call, but it will leave the left and right sidebars alone. The exception to this rule is if the passage you call is a [fullscreen] passage.
Usage Examples:
($cs:"scene 04 page 2")
($cs:"scene 04 page 3")
$nx
Parameters:(str) passage_name
Function:
Sets $next
and displays the "next"
passage. This works similar to $cs except it replaces the ENTIRE screen. This means the passage you call needs to be [fullscreen] and rebuild both the left and right sidebars.
Usage Examples:
($nx:"Go to the bar")
($nx:"Do chores")
($nx:"Workout")
💰 Economy & Currency
$gain_money
Parameters:(num) amount
Function:
Adds money to the player’s total and updates the money display with a visual fade-up transition. Also plays a “kaching” sound if the amount is greater than zero.
Usage Examples:
($gain_money:50) <!-- Adds $50 and shows animated currency update -->
($gain_money:200) <!-- Plays sound and fades in the new amount -->
$pay_money
Parameters:(num) amount
Function:
Subtracts money from the player. Ensures balance never drops below zero. Updates display and plays a cash sound.
Usage Examples:
($pay_money:25) <!-- Deducts $25 and updates the money display -->
($pay_money:100) <!-- Deducts and plays sound if amount > 0 -->
🔥 Arousal & Emotion
$gain_arousal
Parameters:(num) gain
Function:
Sets $gain
to the given value and displays the "gain arousal"
passage. Used to increment arousal in a stylized way.
Usage Examples:
($gain_arousal:10) <!-- Increases arousal by 10 and shows UI feedback -->
($gain_arousal:5) <!-- Triggers gain arousal logic for smaller amounts -->
🎲 Skill Checks
$willpower_check
Parameters:(str) next_passage
, (num) difficulty
Function:
Performs a willpower check based on a fixed chance (101 - difficulty
). If successful, jumps to the next_passage
.
Usage Examples:
($willpower_check:"resist temptation",40) <!-- 61% chance to resist -->
($willpower_check:"walk away",70) <!-- 31% chance to succeed -->
$charm_check
Parameters:(str) next_passage
, (num) difficulty
Function:
Performs a charm-based skill check. Chance is calculated from charm * 10, averaged with 101 - difficulty
.
Usage Examples:
($charm_check:"flirt with him",60) <!-- Based on player’s charm stat -->
($charm_check:"convince guard",75) <!-- Harder charm check -->
$intellect_check
Parameters:(str) next_passage
, (num) difficulty
Function:
Performs an intellect-based skill check. Chance is based on intellect * 10, blended with 101 - difficulty
.
Usage Examples:
($intellect_check:"solve puzzle",50) <!-- Average difficulty logic check -->
($intellect_check:"hack the console",80) <!-- Requires high intellect -->
$fitness_check
Parameters:(str) next_passage
, (num) difficulty
Function:
Performs a fitness-based skill check. Chance uses fitness * 10 with a difficulty modifier.
Usage Examples:
($fitness_check:"climb out window",65) <!-- Physical escape or action -->
($fitness_check:"lift heavy object",40) <!-- Easier physical task -->