Stonescript
Stonescript
v3.44.1 - 2023/09/20
intro | manual | beta ·:· release notes | faq
_ ______________________ _ ,:´ \____ __.---,. `. :.! __________\
_______\__`--`´__ \ :' \ \--------------------------.\ \ ':' · \
·:. :'· :.:· \\ \ ':' \ \ :·' :·:. \\ \ ':' · \ .: ·:: '.:. ':'··:.
\\ \ ':' \ \ · :.. \\ \ ':' · \ :·: ..': :·:. ·:: '. \\ \ ':' \ \
__________________________\\ \ ':' ` . \ . ) ':' . . . \ . . . .
' . . . . \ . .; `·.;,;,;,;,;,;,;,;,;,;,;,;,;,;,:'
Used in the Mind Stone to automate equipment choices. Stonescript is a
minimalistic, yet powerful language inside of Stone Story RPG. Need
help? Want to collaborate on scripts? Visit our Discord. This manual is
the comprehensive reference of all available Stonescript features. Most
of the examples can be copy/pasted directly into the Mind Stone, which
is a great way to learn how they work. ·:·:· Index ·:·:· 1. Example 2.
Basics 3. Game State 4. Commands 5. Search Filters 6. Comparisons 7.
Variables 8. Math Operations 9. Functions 10. Native Functions 11.
Importing External Scripts 12. ASCII-art 13. Loops 14. Arrays 15.
Custom Input 16. User Interface 17. Tips 18. Default script 19. Roadmap
Appendix A - Sound Effects Appendix B - Music Appendix C - Ambient
Loops
·:·:· Example ·:·:· // Equips the Shovel for Rocky Plateau. // In Caves
of Fear it equips loadout 1, // except against the boss, where the //
Grappling Hook and a 7 star War Hammer // are used instead. // For
Haunted Halls it uses two Wands, // specifying Poison for left hand and
// Vigor for the right hand. However, // if the difficulty is over 5
stars it // uses an enchanted +13 Vigor Staff. // Potion activates if
hitpoints fall // below 10 ?loc=rocky equip shovel ?loc=cave loadout
1 ?foe=bolesh equip grap equip hammer *7 D ?loc=halls equipL poison
wand equipR vigor wand ?loc.stars > 5 equip vigor staff +13 ?hp < 10
activate potion ^Back to top
·:·:· Basics ·:·:·
? Evaluates a logical condition. If true, executes indented lines (if).
E.g.
?loc = caves
loadout 1
// A comment. All text to the right of '//' has no logical effect when the script executes.
E.g.
?loc = caves
loadout 1
//The above equips loadout 1 for Caves of Fear
/* */ Block comment. All text between the symbols has no logical effect when the script executes.
E.g.
/*
?loc = caves
loadout 1
*/
This script does nothing, as all of it is inside the block comments.
?loc.begin Is true only on the first frame of a location, when time = 0, before any gam
Is not true after an Ouroboros loop. Useful for resetting variables.
E.g.
var i
?loc.begin
i=0
?loc = caves
i = -100
?loc.isQuest True if the current location is a special location from a Legend or custom q
E.g.
?loc.isQuest
>`0,1,We're in a special quest location
loc.averageTime The current location's average completion time. A location's average time
weighted manner, where the latest completion time is worth more and olde
progressively less the older they are.
E.g.
>`0,2,Average time =
^ @loc.averageTime@ frames
loc.bestTime The current location's best completion time (your record, high-score).
E.g.
>`0,1,Best time =
^ @loc.bestTime@ frames
?foe.id The unique ID (or type) of the foe being targeted by the player.
?foe.name The localized name of the foe being targeted by the player.
?foe.damage The damage per attack of the foe being targeted by the player.
E.g.
>`0,1,foe damage = @foe.damage@
?foe.distance The distance between the player and the foe being targeted.
?foe.hp The current hitpoints of the foe being targeted by the player.
?foe.maxhp The maximum hitpoints of the foe being targeted by the player.
?foe.armor The current armor of the foe being targeted by the player.
?foe.maxarmor The maximum armor of the foe being targeted by the player.
?foe.buffs.count The number of buffs (positive effects) on the foe being targeted.
?foe.buffs.string A composite of information about all the buffs on the target foe.
E.g.
?foe.buffs.count > 0
>`0,3,Foe buffs = @foe.buffs.string@
?foe.debuffs.count The number of debuffs (negative effects) on the foe being targeted.
?foe.debuffs.string A composite of information about all the debuffs on the target foe.
E.g.
?foe.debuffs.count > 0
>`0,4,Foe debuffs = @foe.debuffs.string@
?harvest.distance The distance between the player and the nearest harvestable object.
E.g.
?loc=Rocky & harvest.distance < 7
equip shovel
?input.x The X position, on the ASCII grid, of the input device (mouse/touch).
?input.y The Y position, on the ASCII grid, of the input device (mouse/touch).
E.g.
> (@input.x@, @input.y@)
?item.left.state The numeric representation for an equipped weapon's current state and ela
?item.left.time that state.
?item.right.state E.g.
?item.right.time >`0,1,@item.left.state@:@item.left.time@
>`0,2,@item.right.state@:@item.right.time@
?pickup.distance The distance between the player and the pickup being targeted.
E.g.
?pickup.distance < 5
equipL star stone
?armor The player's current armor, rounded down.
E.g. if the armor says [2.4] ?armor evaluates to 2.
?ai.enabled True if the AI is on, False if the AI is off (e.g. during a cinematic moment)
?ai.paused True if the AI is temporarily suspended, such as when waiting for a treasur
?ai.idle True if the player is idle, waiting for something such as an attack to compl
?player.direction Indicates the direction in which the player is facing. Returns a value of 1 f
E.g.
?player.direction = 1
>`0,0,Walking right
:
>`0,0,Walking left
?screen.i The screen's position in-game, as an index that increses when the player re
and it slides over.
E.g.
>`0,0,Screen index = @screen.i@
summon.GetId(index = 0) Returns the ID of the summon at a given index. The index parameter is op
zero (first summon). Returns null if no summons are at that index.
E.g.
?summon.GetId() ! "cinderwisp"
equipR fire talisman
activate R
summon.GetName(index = 0) Returns the localized name of the summon at a given index. The index par
defaults to zero (first summon). Returns null if no summons are at that ind
E.g.
>`0,1,Summon:@summon.GetName()@
summon.GetVar(varName, Returns the value for a custom variable on a summon. Different types of su
index = 0) different variables, based on their unique abilities. The index parameter is
to zero (first summon). Returns null if no summons are at that index. Show
does not correspond to a valid variable.
E.g.
?summon.GetId() = cinderwisp &
^summon.GetVar("ignition") > 2
activate cinderwisp
summon.GetState(index = 0) Returns a number representing the current state of a summon. The index p
and defaults to zero (first summon). Returns -1 if no summons are at that i
E.g.
>`0,1,Summon state:@summon.GetState()@
summon.GetTime(index = 0) Returns the elapsed number of frames in the current state of a summon. Th
optional and defaults to zero (first summon). Returns -1 if no summons are
E.g.
>`0,1,Summon time:@summon.GetTime()@
?totalgp The total "Gear Points" of your inventory, calculated from item star levels
bonuses.
E.g.
>My gear points = @totalgp@
?totaltime The current frame number of the location, accumulated in case of boss sub
E.g.
>`0,0,Current time = @totaltime@ frames
time.ms Unix time represents the number of milliseconds that have elapsed since
1970-01-01T00:00:00Z (January 1, 1970, at 12:00 AM UTC). It does not t
account.
E.g.
>@time.ms@
time.year, time.month, time.day, The local system time on the player's computer.
time.hour, time.minute, E.g.
time.second >`0,0,@time.year@/@time.month@/@time.day@
^ @time.hour@:@time.minute@:@time.second@
brew (ingredients) Refills the potion bottle to the specified combination of ingredients. Executes only at th
at time 0. Ingredients can be stone, wood, tar or bronze and should be separated by +. I
be written in English or in the language selected in the settings.
E.g.
?loc.begin
brew bronze + tar
equip (str) Equips an item. (str) has a limit of 7 criteria. Two-handed items must use this form of t
E.g.
equip vigor crossbow *8 +5
equipL (str) Equips an item to the left hand that best fits the given criteria.
E.g.
equipL poison d_sword
equipR (str) Equips an item to the right hand that best fits the given criteria.
E.g.
equipR vigor shield
equip @var@ Equips an item based on criteria from a string variable. Equip and other item search co
subtractive criteria.
E.g.
var weaponName = "poison sword *10 -big"
equipR @weaponName@
> @varName@ Prints a string with the value of a variable inserted. Multiple variables can be inserted i
insert, surround the variable's name with @.
The following example prints information about the currently targeted foe:
var foeInfo
foeInfo = foe
>FOE = @foeInfo@
>(abcd Shows a custom facial expression on the player. Requires Big Head.
E.g.
>( OwO
>oX,Y,[#rrggbb,](str) Advanced print relative to the player's position. X and Y are the coordinate offsets. #rrg
text in hexadecimal notation. Color can also be set with these constants: #white, #cyan
#blue and #red. To print in rainbow use #rainFF where the last 2 characters define the b
The following example writes "Let's go!" in red font, relative to the player's position, 6
>o-6,3,#red,Let's go!
>hX,Y,[#rrggbb,](str) Similar to ">o", however, draws on the same layer as the Big Head. Ideal for accessori
The following draws a yellow hat on the player. Works best if Big Head is enabled:
>h-2,-3,#yellow,ascii
##_
#| |
_|_|_
asciiend
>cX,Y,[#rrggbb,](str) Advanced print relative to the center of the screen. Similar to ">`". Note that in all thes
This example demonstrates how the color is optional and defaults to white:
>c0,0,Hello World!
var (variable) Declares a variable that can be used in math, logical and string operations. See the vari
details about their lifecycle and behavior, that may differ from other languages.
E.g.
var message = Hello World!
>@message@
Print(Hello World!)
for v = a..b Creates a loop that iterates a variable 'v' from value 'a' to value 'b'. Code that appears in
will run multiple times.
E.g.
var a
a=0
for i = 1..5
a=a+i
>a = @a@
import Fishing
new (script) Loads and executes an external script similar to 'import'. However, objects loaded with
individual copy and their script body will only execute one time.
This example creates and prints a vector object:
var v = new Components/Vector
v.Init(10, 5)
>Vector = @v@
disable abilities Prevents activation of potion and weapon abilities. Also greys out the HUD buttons.
enable abilities Restores activation of abilities that were disabled by a previous call to "disable abilities
disable banner Prevents rendering of the horizontal banner that appears with the location name at the b
location.
enable banner Restores rendering of the horizontal banner with location name.
disable hud (opts) Hides and disables the gameplay user interface elements. Accepts optional parameters,
elements to disable: p = player health and debuffs, f = foe health and debuffs, a = abilit
resources, b = banner, u = utility belt.
E.g.
disable hud // Disables all hud elements
E.g.2
disable hud ru // Disables only resources (r) and utility belt (u)
enable hud (opts) Brings back the user interface elements hidden by previous "disable hud" commands. A
optional parameters as the disable command.
disable loadout input Prevents weapon loadouts from being saved or recalled with input keys.
enable loadout input Restores the saving or recalling of weapon loadouts by means of input keys.
disable loadout print Hides the messages that appear when a loadout is recalled.
disable pause Hides the pause button user interface. Pause is still available with the [P] shortcut.
enable pause Brings back the pause button hidden by a previous "disable pause" command.
disable player Hides the player. Has no effect on combat, this is only cosmetic.
enable player Brings back the player rendering if it was hidden by a previous "disable player" comma
play (sound) (pitch) Plays a sound effect with an optional pitch value. The pitch default value is 100 with h
increasing the pitch and smaller numbers lowering it.
E.g.
?key = primary
play buy
?key = up
play buy 200
E.g.2:
var pitch
?time%30 = 0
pitch = rng/100 + 50
>@pitch@
play buy @pitch@
^Back to top
·:·:· Search Filters ·:·:· These are used when evaluating foes,
locations and items. E.g.: ?foe = insect | foe = poison loadout 3
poison vigor aether fire air ice arachnid serpent insect machine
humanoid elemental boss phase1 phase2 phase3 spawner flying slow ranged
explode swarm unpushable undamageable magic_resist magic_vulnerability
immune_to_stun immune_to_ranged immune_to_debuff_damage
immune_to_physical *[number] star level (location or item) +[number]
enchantment bonus (item only) ^Back to top
·:·:· Comparisons ·:·:· Used in conjunction with game state to make
decisions
= Compares values equal or string contains.
E.g.
?hp = maxhp
loadout 2
| Logical OR operator. If '&' and '|' are mixed in a single complex expression, all '&' operate first.
E.g.
?foe=slow | foe.count>3
activate potion
> Greater-than compare. Can be used with a location's difficulty, number of foes, health, etc.
E.g.
?foe.count > 10
equip shiny bardiche
>= Greater-than or equal compare. The combination of '>' and '=' into a single comparison.
The following two examples are equivalent:
?loc.stars >= 6
equipR vigor shield
<= Less-than or equal compare. The combination of '<' and '=' into a single comparison.
E.g.
?hp <= 6
activate potion
^Back to top
·:·:· Variables ·:·:· Variables are a way of storing value to use
later. Declare a new variable with the keyword 'var'. E.g.: var myVar =
10 (myVar is the name of the variable, and it's initialized with value
10) myVar = myVar + 5 (myVar now equals 15) var secondVar = 3 myVar =
myVar - secondVar (Many variables can be combined in math operations.
myVar now equals 12) When a variable is declared it is initialized only
once, the first time 'var' executes. E.g.: var i = 0 i++ >i = @i@ In
this example, variable 'i' is declared and starts with value 0. During
each frame of the run, the value of 'i' increases by 1 and then is
printed to the screen. Variables only reset to their initial value if
you leave a location and begin a new run manually. They do not reset
when the Ouroboros loops or when the Mind Stone is opened then closed
again. String variables can optionally be declared with quotes. This
allows special symbols and trailing spaces. E.g.: var a = 10 var b = 5
var myVar = a + " x " + b + " = " + (a * b) >@myVar@ (This example also
demonstrates how to join strings with the '+' operator) Variables in
imported scripts are contained within those scripts and their names
won't collide with variables or functions in other scripts. ^Back to
top
·:·:· Math Operations ·:·:· Operators modify numbers. Can be used in
conjunction with variables or directly in game state expressions.
+ Adds two numbers or variables together.
E.g.:
var a = 2 + 3
(a equals 5)
E.g.2:
var a = 2 * 0.4
// a equals 0.8
/ Divides one number or variable by another. In the case of integers, the result is rounded down.
E.g.:
var a = 8
a=a/4
// a equals 2
E.g.2:
var a = 5.0
a=a/2
// a equals 2.5
++ Increments a variable.
E.g.:
var a = 3
a++
// a equals 4
-- Decrements a variable.
E.g.:
var a = 3
a--
// a equals 2
E.g.2:
?time % 8 < 4
> \O)
?time % 8 > 3
> (O/
// this draws an animated emoji
ambient.Add(str) Adds a layer of ambient audio, with the given sound ID. Up to 4 layers. If a 5t
No return value oldest layer is removed.
E.g.
?loc.begin
ambient.Add(ambient_crypt)
color.FromRGB(r,g,b) Converts a color from three integer numbers (0 to 255) into a string.
Returns string E.g.
var c = color.FromRGB(255, 0, 128)
>`0,0,@c@, @c@
draw
‾‾‾‾
draw.Box(x, y, w, h, color, Draws a rectangular shape at the specified position and size. The rectangle's bo
style) and a style number. Negative style numbers cause the center of the rectangle to
No return value CAVEAT - At this time, advanced prints always draw on top of boxes.
Use this example to explore the different styles by pressing Left/Right
var style = 1
?key = leftBegin
style--
?key = rightBegin
style++
draw.Box(10, 5, 30, 15, #333333, style)
>`12,6,#ffffff,Style = @style@
>`12,8,#888888,Press Left/Right\nto change style
draw.Player() Draws the player character, with all equipment and addons, at a specific point
No return value
int
‾‾‾
int.Parse(str) Converts a string of a number into an integer value. If the given string is not a
Returns integer thrown.
E.g.
var s = "999"
var i = int.Parse(s)
i++
item
‾‾‾‾
item.CanActivate() Returns true if it's possible to activate item abilities. False otherwise. In some g
Returns boolean ability activations are disabled, even if they are not on cooldown, such as mom
or during a cinematic.
E.g.
?item.CanActivate()
equip Bardiche
activate R
item.CanActivate(str) Returns true if it's possible to activate a specific item. Will only ever be true if
Returns boolean Some items can have mechanics that don't allow them to be activated unless sp
This is a sub-set of item.GetCooldown(), as an item's cooldown may be zero an
activated, but it will never be possible to activate an item that is on cooldown.
E.g.
equip bardiche
?item.GetCooldown("skeleton_arm") <= 0
equip skeleton arm
?item.CanActivate("skeleton_arm")
activate R
item.GetCooldown(str) Returns the remaining cooldown time (in frames) for a given ability.
Returns integer E.g.
?foe = boss & item.GetCooldown("bardiche") <= 0
equip bardiche
activate R See the following table for all available ability strings. NOTE: Inval
return -1. Some abilities from weapons that have not been used yet will return
Item Cooldown ID
---- -----------
Bardiche "bardiche"
Hatchet "hatchet"
Quarterstaff "quarterstaff"
key
‾‾‾ The key namespace allows for the customization of standard game inputs and s
based on actions (abbreviated "act") and keys, where each action corresponds t
input/shortcut and each key corresponds to a physical key press. The list of all
be assigned to actions can be found here. Changes to action bindings persist be
currently do not save to storage). For optimization purposes, it is recommende
bindings every frame.
Action Default Key Default Key 2
------ ----------- -------------
Pause P Space
Leave L
Inventory I
Mindstone M
Potion Q
ItemLeft E
ItemRight R
Up W UpArrow
Down S DownArrow
Left A LeftArrow
Right D RightArrow
Back X
BumpL Z
BumpR C
Dynamic1 F
Dynamic2 T
Dynamic3 G
Dynamic4 V
Dynamic5 B
key.Bind(act, key1) Assigns a new set of keys to a specific action. If another action already has one
key.Bind(act, key1, key2) key already in use is abandoned for the original action. Up to two keys may be
No return value E.g.
?loc.begin
key.Bind("Potion", "P")
// In this example, the "P" key that originally is assigned to Pause, no longer pa
activates the potion instead. Also, the Potion's original "Q" key no longer work
action.
key.GetKeyAct(key) Returns the action bound to a given key. Returns "None" if the given key is no
Returns string
key.GetActKey(act) Returns the first key bound to a given action. Returns "None" if the given actio
Returns string it.
key.GetActKey2(act) Returns the second key bound to a given action. Returns "None" if the given a
Returns string secondary key bound to it.
key.GetActLabel(act) Returns a user-facing label that represents the first key bound to a given action
Returns string implementation returns the first letter of the bound key, which can be confusin
"LeftShift".
loc
‾‾‾
loc.Leave() Causes the run to be abandoned as if the player had pressed to leave manually.
No return value
loc.Pause() Causes the run to be paused as if the player had pressed the pause button manu
No return value
math The math API works with both integers and floating-point (float) numbers. Wh
‾‾‾‾ delcared with a decimal period, it's implied to be a float (e.g. var a = 0.5). If th
number, then it's treated as an integer (e.g. var a = 2).
math.Abs(num) Returns the absolute value of a given number.
Returns number E.g.
var number = -2
number = math.Abs(number)
// number now equals 2
math.Clamp(num, min, max) Constrains a number to within the range 'min' and 'max'. If the number is alrea
Returns number it will be returned without change.
E.g.
var number = 50
number = math.Clamp(number, 0, 10)
// number has been clamped down and will equal 10
math.Floor(num) Rounds a number down, to the first whole number smaller than it.
Returns number E.g.
var number = math.Floor(2.7)
// number equals 2.0
math.FloorToInt(num) Rounds a number down, to the first integer smaller than it.
Returns integer E.g.
var number = math.FloorToInt(2.7)
// number equals 2
math.Ceil(num) Rounds a number up, to the first whole number greater than it.
Returns number E.g.
var number = math.Ceil(4.2)
// number equals 5.0
math.CeilToInt(num) Rounds a number up, to the first integer greater than it.
Returns integer E.g.
var number = math.CeilToInt(4.2)
// number equals 5
E.g.2:
var n = 0.0
?key = Begin
n = 0.0
n = math.Lerp(n, 100, 0.02)
>n = @n@
// Variable n eases towards 100, at 2% per frame. When a key is pressed it rese
math.Acos(num) Returns the arc-cosine of a number, in radians. The input bounds are -1 to 1. If
Returns number of bounds then "NaN" is returned.
E.g.
var number = math.Acos(-1)
// number equals π
math.Asin(num) Returns the arc-sine of a number, in radians. The input bounds are -1 to 1. If th
Returns number bounds then "NaN" is returned.
E.g.
var number = math.Asin(1)
// number equals π/2
music
‾‾‾‾‾
music.Play(str) Plays a music, with the given sound ID. There can only be one music playing a
No return value E.g.
?loc.begin | loc.loop
music.Play(temple_0)
player.ShowScaredFace(num) If the player has big-head enabled, their facial expression will change to scared
No return value time.
E.g.
?key = primaryBegin
player.ShowScaredFace(1)
screen
‾‾‾‾‾‾
x = screen.ToWorldX(input.x)
z = screen.ToWorldZ(input.y)
>`0,2,World position of cursor: @x@,@z@
screen.Next() For locations that are multi-screen, moves the camera one screen forward in re
No return value E.g.
?key = rightBegin
screen.Next()
screen.Previous() For locations that are multi-screen, moves the camera one screen back in relati
No return value E.g.
?key = leftBegin
screen.Previous()
screen.ResetOffset() Resets the camera to follow the player, undoing changes made by screen.Next(
No return value E.g.
var lastScreenI = -1
?lastScreenI ! screen.i
screen.ResetOffset()
lastScreenI = screen.i
storage Values saved into permanent storage persist when you leave a location, as wel
‾‾‾‾‾‾‾ shut down. They are not part of your primary_save, existing instead in a series
the Stonescript folder. Imported scripts access storage in isolation from each o
modules to use the same keys without modifying each other's data.
storage.Delete(string) Deletes any value that may exist at the specified key.
No return value E.g.
storage.Delete("highscore")
storage.Get(string, value) Retrieves a permanent value stored at the specified key. If it's not found, return
Returns value as a default value.
E.g.
var value = storage.Get("highscore", 0)
>High Score = @value@
storage.Has(string) Returns true if the specified key exists in permanent storage; false otherwise.
Returns boolean E.g.
?storage.Has("highscore")
var value = storage.Get("highscore")
>High Score = @value@
:
>No High Score found.
storage.Incr(string) Increases by 1 the value stored at the specified key, then returns the new value
Returns integer E.g.
?gameOver
storage.Incr("stat_TimesPlayed")
storage.Keys() Retrieves an array of strings containing all the storage keys available in the cur
Returns array E.g.
var a
?time % 30 = 0
a = storage.Keys()
for i = 0 .. a.Count()-1
>Key @i@ = @a[i]@
storage.Incr(string, integer) Increases the value stored at the specified key by a given amount, then returns
Returns integer E.g.
var amount
?foundCoins
amount = rng%5 + 5
storage.Incr("coins", amount)
string
‾‾‾‾‾‾
string.Break(string, integer) Breaks a string into multiple strings, given a max width.
Returns array E.g.
var s = "The brown fox jumps over the lazy dog"
var a = string.Break(s, 14)
for i = 0 .. a.Count()-1
>`0,@i@,@a[i]@
string.Equals(str1, str2) Takes two string parameters and returns true if they are exactly the same. Retu
Returns boolean Case sensitive.
E.g.
var a = "foo"
?string.Equals(a, "foo")
>The strings are equal
:
>They are NOT equal
// The strings are equal in this case. string.Equals() evaluates to true
string.Format(str1, ...) Modifies a string by replacing format-templates with the values of the other pa
Returns string the final composed string. This is a powerful function that supports lots of form
E.g.
var str = "My name is {0} and I have {1} power!"
var result = string.Format(
^ str,
^ player.name,
^ totalgp
^)
>@result@
string.IndexOf(str, criteria) Takes a string variable and a string criteria as parameters and finds the position
Returns integer the string. Returns -1 if not found.
E.g.
var a = Hello World!
var index = string.IndexOf(a, llo)
// index equals 2
string.IndexOf(str, criteria, Takes a string variable, a string criteria and a starting index as parameters. Fin
startAt) criteria inside the string, but begins the search at 'startAt'. Returns -1 if not fou
Returns integer E.g.
var a = Hello World!
var index = string.IndexOf(a, llo, 4)
// index equals -1 because the search began at position 4
// therefore 'llo' was not found
string.Join(s, []) Takes an array of strings [] and combines it into a single string with the separa
string.Join(s, [], int) parameters can be passed that specify the starting index and number of elemen
string.Join(s, [], int,int) index parameters are provided, the entire array is combined.
Returns string E.g.
var a = ["Hello", "World", "!"]
var b = string.Join(";", a)
>`0,0,@b@
// Prints "Hello;World;!"
E.g.2
var a = ["Hello", "World", "!"]
var b = string.Join(";", a, 1)
>`0,0,@b@
// Prints "World;!"
E.g.3
var a = ["Hello", "World", "!"]
var b = string.Join(";", a, 0, 2)
>`0,0,@b@
// Prints "Hello;World"
string.Size(str) Takes a string variable as parameter and calculates how long it is, in number o
Returns integer E.g.
var a = Hello World!
var size = string.Size(a)
>size = @size@
string.Split(str) Takes a string and breaks it down into an array of strings, given a set of string
string.Split(str, s…) separators are provided, then the string is broken wherever there is a space. An
string.Split(str, s…, bool) parameter specifies if empty entries should be discarded.
string.Split(str, bool) E.g.
Returns array var a = string.Split("Hello World !")
for i = 0 .. a.Count()-1
>`0,@i@,[@i@] = @a[i]@
// Breaks up the string into: "Hello", "World", "!"
E.g.2
var a = string.Split("Hello World !", " ", "l")
for i = 0 .. a.Count()-1
>`0,@i@,[@i@] = @a[i]@
// Breaks up the string into: "He", " ", "o", "Wor", "d", "!"
E.g.3
var a
a = string.Split("Hello World !","l","r",true)
for i = 0 .. a.Count()-1
>`0,@i@,[@i@] = @a[i]@
// Breaks up the string into: "He", "o Wo", "d !"
string.Sub(str, startAt) Takes a string variable and a starting index as parameters and splits the string f
Returns string E.g.
var a = Hello World!
var subString = string.Sub(a, 6)
>substring = @subString@
// subString equals "World!"
string.Sub(str, startAt, length) Takes a string variable, a starting index and a length as parameters and splits th
Returns string starting point, stopping at the given length.
E.g.
var a = Hello World!
var subString = string.Sub(a, 6, 3)
>substring = @subString@
// subString equals "Wor"
sys.cacheRemoteFiles Indicates if files imported remotely should be cached between runs. Default is
boolean remote scripts will re-download when you begin play from the Locations scree
change this during development and iteration of new scripts that are deployed
property persists between runs.
E.g.
// We use the "up" key as an input to toggle
// remote caching on/off during rapid iteration
?key = upBegin
sys.cacheRemoteFiles = !sys.cacheRemoteFiles
?sys.cacheRemoteFiles
>Remote caching ENABLED
:
>Remote caching DISABLED
sys.fileUrl Getter for the current file path to be used when importing scripts. The default v
string (get only) device. On PC the default value is local. On mobile the default is
https://StonestoryRPG.com/stonescript/
E.g.
>`0,1,fileUrl = @sys.fileUrl@
sys.SetFileUrl(str) Changes the origin of imported scripts when using the commands import or ne
No return value on the Mind Stone and will error if written on an imported script. Accepts any
location, but also accepts the values "local" and "remote" as shortcuts to easily
drive or to the official Stone Story RPG repository, respectively. If null is pass
the file URL resets to the default value for your device. This global property p
E.g.
sys.SetFileUrl(
^"https://MyCoolDomain.com/scripts/")
import MyCombatScript
Text Localization Stonescript supports 12 languages as of this writing. A few operations allow cu
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ the player's chosen language.
te.language The code for the language selected by the player in settings. Possible values: E
string ZH-TW, FR, DE, RU, ES-LA, ES-EU, JP, KR and TK.
E.g.
var lang = te.language
>Language = @lang@
te.xt(str) Translates a given English text into the player's selected language. If a translat
Returns string then the input text is returned instead. Alternatively, a text identifier (TID) can
the exhausting list of TIDs is beyond the scope of this manual.
E.g.
var button = ui.AddButton()
button.text = te.xt(Play)
// Change your language in settings to see this example at work
te.GetTID(str) Returns the text identifier (TID) for a given text. The input text is expected in t
Returns string the player.
E.g.
var tid = te.GetTID("Play")
>`0,1,@tid@
// Prints tid_button_play to the screen
te.ToEnglish(str) Translates a given text from the player's selected language into the original En
Returns string version is not found, then the input text is returned instead.
E.g.
>`0,1,@te.ToEnglish("Jogar")@
// If Portuguese is chosen in settings it will print "Play"
// otherwise it will print "Jogar"
time
‾‾‾‾
UI
‾‾ See the User Interface section for details about Stonescript's advanced UI syste
functions of the ui namespace:
ui.ShowBanner(str) Displays the animated banner with up to two messages. The banner animation
ui.ShowBanner(str,str) ui.ShowBanner() is called.
No return value E.g.
?time = 120
ui.ShowBanner("Hello World!")
Other
‾‾‾‾‾
Type(var) Evaluates the type of a variable and returns a string representation. Possible ty
Returns string 'bool', 'function', 'object' and 'null'.
E.g.
var a = 0
?Type(a) = int
>Variable 'a' is an integer.
^Back to top
·:·:· Importing External Scripts ·:·:· Your script doesn't have to be
all in the Mind Stone. Stonescript supports the loading of external
files through the 'import' and 'new' keywords. For external scripts to
work they must be located in your save-file folder, inside a
/Stonescript folder and end in '.txt'. In the most basic example an
external script is imported and runs as if it were directly in your
Mind Stone, making this a convenient way to organize farming scripts:
import Rocky import Deadwood import Caves import Forest When a script
is imported it's copied into its own container and returns as a
reference. Variables declared in the external script are isolated and
don't interact with variables in other scripts. In this example, a
printing utility script offers simplified services: // PrintUtil.txt
func LowerLeft(x, y, color, message) y = y + screen.h
>`@x@,@y@,@color@,@message@ func LowerRight(x, y, color, message) x = x
+ screen.w y = y + screen.h >`@x@,@y@,@color@,@message@ // Main script
in Mind Stone var print = import PrintUtil disable hud
print.LowerLeft(0,-1,#ffffff,"Health: " + hp) Advanced solutions can
import the same script multiple times using the 'new' command, for
example, to implement componentization or an Object Oriented
paradigm: // Vector.txt var x = 0 var y = 0 func init(_x, _y) x = _x y
= _y func subtract(otherVect) x = x - otherVect.x y = y -
otherVect.y // Main script in Mind Stone var vectFrom = new
Components/Vector var vectTo = new Components/Vector vectFrom.init(5,
4) vectTo.init(8, 2) vectTo.subtract(vectFrom) >x = @vectTo.x@, y =
@vectTo.y@ External scripts can implement a 'ToString()' function,
allowing their direct use in advanced print commands: // Vector.txt var
x = 0 var y = 0 func init(_x, _y) x = _x y = _y func ToString() return
"(" + x + ", " + y + ")" // Main script in Mind Stone var v = import
Components/Vector v.init(3,5) >Vector = @v@ External scripts can be
imported from subfolders: import Games/Blackjack import
Cosmetics/PetFrog import Cosmetics/Hats While similar, there are two
important differences between 'import' and 'new'. With 'import' the
same object is returned each time. If you import the same script from
multiple places they will all be using the same object. Scripts
imported with 'new' are unique copies, but their script body will only
run 1 time as opposed to every frame. ^Back to top
·:·:· ASCII-art ·:·:· In Stonescript, custom ASCII-art can be embedded
within the scripts and drawn on screen with the advanced print
commands. There are a few methods to do this and some glyphs have
special behavior: # - Blank space. Transparency. Does not draw. \n -
Line break. Causes the draw to continue on the next line. WARNING: This
is an expensive operator and should not be used for breaking lines in
large drawings. Use the ascii/asciiend block instead. Method 1 -
Advanced print This example draws a green circle to the top-left of the
screen. >`1,0,#green,ascii #.-. ( ) #`-´ asciiend Method 2 - Variables
This example saves the art for a spooky fish into a variable, then
draws it to the top-left of the screen in red color. var fishSprite
fishSprite = ascii ###(°_## #_/_ o\# #´ `'"# asciiend
>`0,3,#red,@fishSprite@ ^Back to top
·:·:· Loops ·:·:· Loops allow a section of code to run multiple times.
To create a loop use the 'for' keyword in the form: for v = a..b The
variable 'v' begins the loop with value 'a' and increases in value
until it reaches 'b', then the loop ends: for i = 1..5 >`0,@i@,i = @i@
The iteration variable 'v' should not be declared prior to the 'for'
and is contained to the scope of the loop. However, the begin and end
values 'a' and 'b' can be declared prior to the loop: var min = 1 var
max = 4 var sum sum = 0 for j = min..max sum = sum + j >sum = @sum@
Loops can also go in the opposite direction, as well as use negative
numbers: var g g = "" for k = 5..-2 g = g + k >g = @g@ Loops can be
nested inside each other, as well as inlined with math expressions to
form complex algorithms: for x = 1..9 for y = x/2 .. x/2 + 6
>`@x@,@y@,* To break out of the loop early, modify the iteration
variable so that it's out of range: var n n = "" for i = 1..5 ?i = 3 i
= -1 n = n + i >n = @n@ Similarly, break out of the loop with the break
command: for i = 1..5 ?i = 3 break Loops also support the continue
command. When called, instructions below the continue are skipped and
the loop continues looping: var n n = "" for i = 1..5 ?i = 3 continue n
= n + i >n = @n@ It's possible to loop through elements of an array
using this form: var a = [1, 2, 3] var n n = "" for value : a n = n +
value >n = @n@ ^Back to top
·:·:· Arrays ·:·:· Arrays are a special type of variable. They provide
a way to sequentially organize values and objects into a collection
that is assigned to a single variable.
Operation Description
--------- -----------
a.Clear() Removes all elements from the array, making it empty. This is more efficient than re-
with [].
E.g.:
var myArray = [10, 3]
myArray.Clear()
a.Contains(value) Determines if a given value is inside the array. Returns true if found; false otherwise.
E.g.:
var myArray = [10, 3]
?myArray.Contains(3)
>Yes
a.IndexOf(value) Searches for a given value inside the array. Returns an integer indicating the position
of the value. If the value is not found returns -1.
E.g.:
var myArray = [10, 3]
var index = myArray.IndexOf(3)
>Found at position @index@
a.Insert(integer, value) Adds a new value/object to a specific position of the array. Elements to the right are s
position.
E.g.:
var myArray = [10, 3]
myArray.Insert(1, "apple")
// The array is now [10, "apple", 3]
a.RemoveAt(integer) Removes an element in the array from a specific position. Returns the value removed
Zero-based: myArray.RemoveAt(0) removes the first element.
Elements to the right are shifted to the previous position.
E.g.:
var myArray = [1, 2, 3]
myArray.RemoveAt(1)
// The array is now [1, 3]
a.Sort() Organizes the array's elements into ascending order. If the array contains objects of di
still be sorted, but no expected results are defined and elements are not guaranteed to
E.g.:
var myArray = ["Cherry", 2, "Apple", 1, true, false, "Banana", 3]
var value
myArray.Sort()
for i = 0 .. myArray.Count() - 1
value = myArray[i]
>`0,@i@,@value@
Here are some of the different ways to initialize and use arrays: var
emptyCollection = [] var magicNumbers = [10, 3, 0, 15, -7] var
someStrings = ["apple", "banana", "cherry"] var sameButMultiLine =
[ "apple", "banana", "cherry", ] var redeclaredEachFrame
redeclaredEachFrame = [] // Not good for the PC var clearedEachFrame =
[] clearedEachFrame.Clear() // Better for CPU & memory var
clearedEachLoop = [] ?loc.begin | loc.loop clearedEachLoop.Clear() var
multiDimensional = [[], [], []] var objectCollection = [ new
Components/Float, new Components/Float, new Components/Vector, ] var
animationFrames = [ascii ───┼ O/ /| / \ asciiend ^,ascii ---. O \ /|\
┼─── / \ asciiend ^] Looping through arrays: var myArray = ["Apple",
"Banana", "Cherry"] var count var value count = myArray.Count() ?count
> 0 for i = 0 .. count - 1 value = myArray[i] >`0,@i@,@value@ // This
example prints fruit names to the left of the screen Multi-dimensional
access: var a = [[1,2], [3,4]] var value value = a[1][0] >Found value
@value@ at (1, 0) ^Back to top
·:·:· Custom Input ·:·:· Stonescript can read player inputs by use of
the ?key game state. This can be used to drive advanced behaviors, such
as different modes for the AI, but custom inputs allow the creation of
entirely new experiences layered on top of Stone Story. In this
example, the @ symbol can be moved across the screen like the main
character in a classic Rogue-like game. The key codes (leftBegin, etc)
refer to the initial downpress of the button. var x = 0 var y = 0 ?key
= leftBegin x-- ?x < 0 x = 0 ?key = rightBegin x++ ?key = upBegin y-- ?
y < 0 y = 0 ?key = downBegin y++ >`@x@,@y@,#ffffff,@ Table with all the
available key codes:
Held Pressed Released Default PC
---- ------- -------- ----------
up upBegin upEnd W or ↑
ui.root The base UI object on top of which the entire tree is built.
Panel E.g.
disable hud
ui.root.visible = true
ui.AddAnim(string) Adds an Anim object to the root Panel. Accepts an animation sprite sheet as para
Returns Anim E.g.
?loc.begin
ui.AddAnim(ascii
\o)
%%
(o/
asciiend)
?loc.begin
var button = ui.AddButton()
button.y = 1
button.text = Press me
button.SetPressed(OnPressed)
ui.AddPanel() Adds a Panel object to the root Panel. Panels are an important object type, servin
Returns Panel other elements.
E.g.
?loc.begin
var p = ui.AddPanel()
p.color = #red
ui.AddStyle() Adds a new style that can be used for drawing rectangular Components such as P
Returns int Returns an ID number of the new style. Is protected against the same style being
in which case nothing changes and the same ID is returned. Because different scr
ui.AddStyle(), it's recommended to save the ID as a variable instead of hard-codi
the script.
E.g.
var customStyle = ui.AddStyle("
^123
^456
^789")
?loc.begin
var p = ui.AddPanel()
p.style = customStyle
Component Component is a base type for all other UI types. This means that other elements (
‾‾‾‾‾‾‾‾‾ and Anim) all have the following properties:
component.anchor Auto-layout property representing the internal pivot of the component. This guid
string how to position the component relative to itself. Default value is "center_center".
top_left, top_center, top_right, center_left, center_center, center_right, bottom_le
bottom_right.
component.dock Auto-layout property similar to anchor. However, dock represents the external pi
string the parent where to position the component. If in doubt, use the same value for bo
which is the most common situation.
E.g.
?loc.begin
var p = ui.AddPanel()
p.anchor = top_right
p.dock = top_right
p.w = 20
p.h = 9
var t = ui.AddText("HelloWorld!")
t.anchor = left_bottom
t.dock = bottom_left
t.x = 2
t.h = t.lines.Count() + 1
p.Add(t)
component.ax The X part of the anchor. Possible values: left, center and right.
string
component.ay The Y part of the anchor. Possible values: top, center and bottom.
string
component.dx The X part of the dock. Possible values: left, center and right.
string
component.dy The Y part of the dock. Possible values: top, center and bottom.
string E.g.
var p
?loc.begin
p = ui.AddPanel()
p.ax = right
p.ay = top
p.dx = right
p.dy = top
component.parent Reference to the component's parent Panel. May refer to the root Panel if the com
Panel but never added to another Panel. When panel.Add(component) is called the com
read-only changes.
component.visible Visibility of the component. Default value is "inherit". Possible values: true, false
multi type 'true', the component will always be visible, ignoring the status of its parent. If se
bool/string component will be invisible, regardless of its parent. However, if set to 'inherit', t
follow the visibility of its parent.
component.Recycle() Removes the component from its parent Panel. It will be repurposed in future ui.A
No return value variable references to the recycled element should be nulled or reassigned to avo
Panel > Component Panels are rectangular Components that serve as containers for other Component
‾‾‾‾‾ added to each other form a tree structure.
panel.children Array with all the child components that have been added to the Panel with panel
Component[]
panel.clip Indicates if the bounds of Panel should be used to contrain the drawing of child c
bool parts of child components that fall outside of the Panel's bounds will not draw.
E.g.
var p
?loc.begin
p = ui.AddPanel()
p.w = 4
p.h = 3
var t = ui.AddText("The quick brown fox jumps
^ over the lazy dog.")
p.Add(t)
?time%30 < 15
p.clip = true
:
p.clip = false
panel.color The panels color, in RGB hexadecimal format.
string
panel.style ID number of the Panel's current style. Default value is 1. Possible values from -8
int styles can be added with ui.AddStyle()
panel.Add(Component) Adds a Component to a Panel. The Component becomes a child of the Panel and
panel.Add(Component, int) parent of the Component. The order in which elements are added to a Panel affec
No return value Components may be inserted to a specific sorting position by use of the optional
integer parameter means the Component is added as the last child of the Panel. T
be used for changing the draw order of Components that are already children of t
panel.Clear() Removes all UI elements from the Panel. Components removed this way are recy
No return value system and will be repurposed in future ui.Add_() calls. Any variable references
should be nulled or reassigned to avoid bugs.
panel.Remove(Component) Removes a specific Component from a Panel or removes the Component at a spe
panel.Remove(int) Components removed this way are recycled into the UI system and will be repurp
No return value ui.Add_() calls. Any variable references to those elements should be nulled or rea
text.align The alignment/justification of the text inside the box. Default value is "left". Poss
string and right.
text.lines Array of strings that are the broken-down lines of text after the Text box has form
string[] Excludes color metadata.
text.text The full contents of the Text box. A subsection of the text may be colored with th
string [color=#rrggbb][/color].
E.g.
?loc.begin
var t = ui.AddText()
t.text = "Hello [color=#red]World[/color]!"
button.tcolor The color of the text inside the button, in RGB hexadecimal format.
string E.g.
button.tcolor = #ff0000
// Sets the button text color to red
button.hcolor The color of the button's highlight when it's pressed, in RGB hexadecimal format
string E.g.
?loc.begin
var b = ui.AddButton()
b.hcolor = #yellow
button.sound The sound effect that plays when the button is pressed. Default is "confirm".
string E.g.
button.sound = buy
// Changes the button so it plays the buying sound when pressed
button.style ID number of the Buttons's current style. Default value is 1. Possible values from
int styles can be added with ui.AddStyle()
button.SetPressed(f) Assigns a function to be called when the button is pressed. The function can have
function callaback parameters (even no parameters). When the function is called, the first parameter
the button itself.
E.g.
var button1
var button2
func OnPressed(btn)
?btn = button1
>Button1 was pressed
:
>Button2 was pressed
?loc.begin
button1 = ui.AddButton()
button1.y = 1
button1.SetPressed(OnPressed)
button2 = ui.AddButton()
button2.y = 6
button2.SetPressed(OnPressed)
button.SetDown(f) Similar to .SetPressed(), .SetDown() assigns a function to be called when the but
function callaback user contact).
func OnUp()
> Up!
?loc.begin
var button = ui.AddButton()
button.y = 1
button.text = Press me
button.SetDown(OnDown)
button.SetUp(OnUp)
Anim > Component ASCII sprite-sheet animations that can be added to UI.
‾‾‾‾
anim.frame Current animation frame being drawn. Can be changed to set an animation to a sp
int
anim.gamePause If true, the animation automatically pauses playback if the player pauses the gam
bool playback if the player exits the pause screen.
anim.loop If true, the animation will restart from the begining as soon as it reaches the end o
bool
anim.paused True if the animatino is playing, but has been paused with a call to anim.Pause().
bool
read-only
anim.pivotX Additional pivot offset that can be used for fine-tuning where the ASCII-art draw
anim.pivotY position.
int
anim.playOnStart If true, the animation will begin playing as soon as possible.
bool
anim.AddLayer(string) Adds a new ASCII sprite on top of this one. As the animation plays (or its frame
Returns Anim anim.frame) all layers stay in sync. Each layer has their own set of properties for
Advantages of using animation layers for complex ASCII-art include improved p
code quality. If the animation is recycled all layers clean up simultaneously.
E.g.
var a = ui.AddAnim(asciiArtA)
var layer2 = a.AddLayer(asciiArtB)
layer2.color = #bbbbbb
anim.Pause() Suspends playback of the animation at its current frame. A subsequent call to ani
No return value playback.
anim.Play() Begins playing the animation, or resumes playback in case it had been paused.
No return value E.g.
var dance
?loc.begin
dance = ui.AddAnim(ascii
(O/
%%
\O)
asciiend)
dance.duration = 20
dance.loop = true
dance.Play()
anim.Stop() Suspends playback and sets the animation back to its first frame.
No return value
Canvas > Component Container optimized for drawing arbitrary glyphs and colors.
‾‾‾‾‾‾
canvas.blend The blend mode of the canvas, when composed with elements behind it. Possible
string Multiply, Divide, Add, Subtract. Default value is "opaque".
E.g.
var filter1 = ui.AddCanvas()
var filter2 = ui.AddCanvas()
filter1.w = screen.w
filter1.h = screen.h
filter2.w = screen.w
filter2.h = screen.h
filter1.blend = multiply
filter1.SetFG(#aa5555)
filter1.SetBG(#dddddd)
filter2.blend = add
filter2.SetFG(#aa6600)
filter2.SetBG(#662200)
canvas.Set(int,int, fg,str) Overloads for changing a canvas at a specific position, while simultaneously sett
canvas.Set(int,int, fg,bg,str) background colors.
No return value E.g.
?loc.begin
var canvas = ui.AddCanvas()
for x = 0..canvas.w
for y = 0..canvas.h
var fg = color.Random()
var bg = color.Random()
canvas.Set(x, y, fg, bg, ▄)