Script dump

Jump to navigation Jump to search

This page is a place to put scripts or links to scripts that may be useful or good examples when you don't want to bother creating a dedicated wiki article. It would be nice to clean some of these up a bit and convert them into wiki pages (see Category:Example Scripts).

Scripts elsewhere[edit]

Unsorted collections of scripts

  • The 3rd Party HSI, on this wiki
  • Scripts hosted at The Moglery. This is an ancient site, and many of the scripts are obsolete or can now be written in a simpler way, but there are still lots of useful examples.
  • Some Useful Functions on SlimeSald

Some of the following scripts might be quite specific to a certain game, but might still be educational or a good starting point.



Hero/NPC/object graphics/animations:

Sound effects:

Party manipulation:

NPC triggers:


Map effects:

Show region names


Collision detection:

Line of sight:

Titlescreen/load menu/save menu/new games:

Utility scripts[edit]


# Cap n within the range min to max
script, bound, n, min, max, begin
  if (n < min) then (exit returning (min))
  if (n > max) then (exit returning (max))
  return (n)

script, min, n1, n2, begin
  if (n1 < n2) then (return (n1)) else (return (n2))

script, max, n1, n2, begin
  if (n1 > n2) then (return (n1)) else (return (n2))

# Reduce a number towards zero. For example, reduce(10,2)==8, return(-10,2)==-8
script, reduce, n, amount, begin
	if (n < 0) then (
		n += amount
		if (n > 0) then (n := 0)
	) else (
		n -= amount
		if (n < 0) then (n := 0)
	return (n)

(Note: dir X and dir Y have been added as standard commands in ichorescent)

# Return the distance of a point in the specified direction from the origin
script, directional distance, x, y, dir, begin
  switch (dir) do (
    case (up)    return (0 -- y)
    case (right) return (x)
    case (down)  return (y)
    case (left)  return (0 -- x)

script, dir X, dir, begin
  switch (dir) do (
    case (up, down) return (0)
    case (right) return (1)
    case (left)  return (-1)

script, dir Y, dir, begin
  switch (dir) do (
    case (left, right) return (0)
    case (down) return (-1)
    case (up)   return (1)


The following script shows how you can sort a list of numbers by using slices and the sort children command.

plotscript, number sorter, begin
  variable (parent)

  # Add a `number` to the list of numbers to be sorted. 
  # `id` can be anything you want sorted, for example it could be an NPC reference or item ID.
  subscript, add number, number, id = 0, begin
    variable (sl)
    sl := create container
    set parent (sl, parent)
    set sort order (sl, number)
    set slice extra (sl, 0, id)

  # getid(0) returns the id of the smallest number, getid(1) is 2nd smallest, etc
  subscript, get id, index, begin
    return (get slice extra (slice child (parent, index)))

  # getnumber(0) returns the smallest number, getnumber(1) is the 2nd smallest, etc
  subscript, get number, index, begin
    return (get sort order (slice child (parent, index)))

  parent := create container
  # You can rearrange these "add number" lines and it makes no difference
  add number (42, 0)
  add number (100, 1)
  add number (0, 2)
  add number (-2, 3)
  sort children (parent, false)
  trace value (get id(0), get id(1), get id(2), get id(3))   # prints 3 2 0 1 to g_debug.txt
  trace value (get number(0), get number(1), get number(2), get number(3))   # prints -2 0 42 100 to g_debug.txt
  free slice (parent)


# Returns true 'percent' % of the time
script, d100, percent, begin
  return (random(0, 99) < percent)
global variable(16300, last diverse random offset)  # Used by diverse random function

# Like random, but when called with the same range multiple times in a row,
# avoids returning a value close to the last one (within 1/5 of the range).
script, diverse random, low, high, begin
	variable (ret, offset, range)
	range := high -- low + 1
	offset := last diverse random offset + range/5 + random(0, range * 3 / 5)
	ret := low + (offset, mod, range)
	last diverse random offset := offset
	return (ret)

# Approximation of a normally distributed variable
script, normal var, mu, sigma, begin
	variable (i, sum)
	for (i, 0, 5) do (sum += random(0, sigma))
	return (mu + sum -- 3 * sigma)
script, random choice, n1=-1, n2=-1, n3=-1, n4=-1, n5=-1, n6=-1, n7=-1, n8=-1, n9=-1, begin
  if(n1 > -1) then(last:=1)
  if(n2 > -1) then(last:=2)
  if(n3 > -1) then(last:=3)
  if(n4 > -1) then(last:=4)
  if(n5 > -1) then(last:=5)
  if(n6 > -1) then(last:=6)
  if(n7 > -1) then(last:=7)
  if(n8 > -1) then(last:=8)
  if(n9 > -1) then(last:=9)
  if(n10 > -1) then(last:=10)
  r := random(1, last)
  switch(r) do(
    case(1) do(exit returning(n1))
    case(2) do(exit returning(n2))
    case(3) do(exit returning(n3))
    case(4) do(exit returning(n4))
    case(5) do(exit returning(n5))
    case(6) do(exit returning(n6))
    case(7) do(exit returning(n7))
    case(8) do(exit returning(n8))
    case(9) do(exit returning(n9))
    case(10) do(exit returning(n10))

plotscript, example, begin
  show text box(random choice(15, 27, 4, 250, 252))
  wait for text box


# Shuffles the order of the extra data values of a slice/NPC/etc.
script, shuffle extra data, obj, begin
  for (idx, 0, extra length(obj) -- 1) do (
    swap extra data(obj, idx, random(0, idx))

script, swap extra data, obj, idx1, idx2, begin
  variable(x1, x2)
  x1 := get extra(obj, idx1)
  x2 := get extra(obj, idx2)
  set extra(obj, idx1, x2)
  set extra(obj, idx2, x1)

Same but for global variables:

script, swap globals, id1, id2, begin
  variable(x1, x2)
  x1 := readglobal(id1)
  x2 := readglobal(id2)
  writeglobal(id1, x2)
  writeglobal(id2, x1)

# Randomise the order of a range of global variables with consecutive global IDs
# eg.  shuffle globals(@scene1, @scene10)
script, shuffle globals, first id, last id, begin
  for (id, first id, last id) do (
    swap globals(id, random(id, last id))


script, count slices, start slice, begin
  # First count self
  count += 1
  # Then recursively count children
  child := first child(start slice)
  while(child) do(
    count += count slices(child)
    child := next sibling(child)
  exit returning(count)

set parent keep pos[edit]

Using setparent does not behave the same as setting a slice's parent in the slice editor (with the shift key). A slice's x/y position is relative to (some edge or corner of) its parent. When you setparent usually it will also move on the screen because the thing its position is relative to changes. On the other hand in the slice editor when you reparent the offset is recalculated to keep the slice in the same position relative to the screen.

Here is a handy little helper script if you want to reparent a slice without changing its current position.

script, set parent keep pos, sl, new parent, begin
  variable(oldx, oldy)
  oldx := slice screen x(sl)
  oldy := slice screen y(sl)
  set parent(sl, new parent)
  set slice screen x(sl, oldx)
  set slice screen y(sl, oldy)


Copies from one string to another, while removing characters that are icons in the font (adjust for the range of icons you have in your font).

script, remove icons from string, in str, out str, begin
  variable(i, ascii)
  clear string(out str)
  for (i, 1, string length(in str)) do (
    ascii := ascii from string(in str, i)
    #if (ascii < 127) then (   # ASCII font
    if (ascii < 127 || ascii > 160) then (  # Latin-1 font
      append ascii(out str, ascii)


Replace all instances of an item in the inventory with a new one (e.g. to work around the lack of script commands for editing item), without changing which slots it's stored in (which inventory plus delete item get item does).

script, replace item, original id, new id, begin
  variable (slot)
  for (slot, 0, get inventory size -- 1) do (
    if (item in slot(slot) == original id) then (
      set item in slot(slot, new id)


To remove KOed heroes from the active party after a battle, use an after-battle script (you can set a global script in the Special Plotscripts menu) that loops through heroes and swaps them out (and maybe locks them if you want to prevent the player from swapping them back in):

plotscript, swap out KOed heroes, begin
  variable (slot, who)
  for (slot, 0, 3) do (
    who := hero by slot (slot)
    if (who > -1 && get hero stat (slot, stat: hp, current stat) <= 0) then (swap out hero (who))
# Attach this script to an NPC, and set the 'Script Argument'
# to a formation number to trigger.
# The NPC will be deleted after the battle.
# The NPC can optionally show a textbox as well as triggering
# this script.
# Note: the NPC reappears if you load a saved game, or
# leave the map and don't have
# "NPC Data: Remember state when leaving" turned on.
plotscript, npc battle, formation, npcref, begin
  # Prevent the NPC from immediately re-triggering and showing another textbox
  set npc usable(npcref, false)
  wait for textbox
  destroy npc(npcref)
# Attach this script to an NPC, and set the 'Script Argument'
# to a formation number to trigger.
# The NPC will be deleted after the battle if you won, and
# is made un-activatable for 1 second if you run.
# The NPC can optionally show a textbox as well as triggering
# this script.
# Note: the NPC reappears if you load a saved game, or
# leave the map and don't have
# "NPC Data: Remember state when leaving" turned on.
plotscript, npc battle, formation, npcref, begin
  # Prevent the NPC from immediately re-triggering
  set npc usable(npcref, false)
  wait for textbox
  if (fightformation(formation)) then (
    # Won the battle
    destroy npc(npcref)
  ) else (
    # Wait one second, then make the NPC deadly again
    setnpcusable(npcref, true)
plotscript, fun with tile changing, begin
  if(keyval(key:comma) > 1) then(decrement current tile)
  if(keyval(key:period) > 1) then(increment current tile)
  if(keyval(key:O) > 1) then(change tileset(layer tileset(0) -- 1, 0))
  if(keyval(key:P) > 1) then(change tileset(layer tileset(0) + 1, 0))
  if(keyval(key:backspace) > 1) then(reset map state)
  if(keyval(key:S) > 1) then(save map state)
  if(keyval(key:L) > 1) then(load map state)

script, increment current tile, begin
  change current tile by(1)

script, decrement current tile, begin
  change current tile by(-1)

script, change current tile by, amount, begin
  variable(tile, x, y)
  x := hero x(me)
  y := hero y(me)
  tile := read map block(x, y, 0)
  tile := tile + amount, mod, 256
  write map block(x, y, tile, 0)
plotscript, each step example, x, y, begin
  pass := read pass block(x, y)
  if(pass ,and, harm tile) then(
    play sound(5, false, true)
plotscript, on keypress handler, begin
  if(hero is walking(me) == false) then(
    set hero speed(me, 4)
    if(key is pressed(key:Z)) then(
      set hero speed(me, 10)
global variable(1, space being held)

plotscript, on key example, begin
  if(key is pressed(key:space)) then(
    if(not(space being held)) then(
      space being held := true
      space key down
    space being held := false

script, space key down, begin
  # This stuff only happens when you press spacebar
  # and will not repeat if you hold it down

Examples involving animations or visualisations[edit]

global variable(1, face)

plotscript, new game, begin
  init face

plotscript, load game, begin
  init face

script, init face, begin
  face := load medium enemy sprite(5)
  realign slice (face, edge:center, edge:bottom, edge:center, edge:bottom)
  normal face expression

script, normal face expression, begin
  replace medium enemy sprite(face, 5)
  set timer(1, 0, 20, @blink eyes)

script, blink eyes, begin
  replace medium enemy sprite(face, 6)
  set timer(1, 0, 1, @normal face expression)
plotscript, somebody talking, begin
  show text box(5)
  wait for text box while animating(14, 15)

script, wait for text box while animating, backdrop 1, backdrop2, begin
  while(true) do(
    show backdrop(backdrop 1)
    if(current text box == -1) then(exit script)
    show backdrop(backdrop 2)
    if(current text box == -1) then(exit script)
script, pokemon evolve example, begin
  large pokemon evolve(5, 6)

script, large pokemon evolve, sprite 1, sprite 2, begin
  # This script assumes that palette 0 is all black
  sl := load large enemy sprite(sprite 1)
  center slice(sl)
  set sprite palette(sl, 0)
  for(i, 0, 10) do(
    replace large enemy sprite(sl, sprite 1, 0)
    replace large enemy sprite(sl, sprite 2, 0)
  set sprite palette(sprite 2)
  free slice(sl)
plotscript, single cloud example, begin
   sl := load large enemy sprite(10)
   # Attach the slice to the topmost map layer
   set parent(sl, lookup slice(sl:map layer7))
   # center the slice on tile x=125 y=47
   set slice x(125 * 20)
   set slice y(47 * 20)
   set horiz anchor(sl, edge:center)
   set vert anchor(sl, edge:middle)

The following script can be attached to an NPC (either onetime-use or normal) to make it melt and disappear (instead of disappearing instantly). Note: unfortunately the NPC will disappear for one tick and then reappear when it's used, before melting, unless you also attach a textbox to the NPC, which prevents the NPC from immediately disappearing.

plotscript, melt away npc, unused arg, npcref, begin
   # First, turn the NPC's onetime tag back on to make it reappear
   variable (onetime)
   onetime := read npc(npcref, NPCstat:onetimeusetag)
   if (onetime) then (set onetime(onetime, off))
   # Then melt the NPC, and remove it.
   dissolve sprite(lookup slice(sl:walkabout sprite component, get npc slice(npcref), dissolve:melt, 20, 0, false, true)
   if (onetime) then (set onetime(onetime, on)) else (delete npc(npcref))

Remappable key controls[edit]

# This returns either false for no keypress, or a scancode of the pressed keyboard key
script, find pressed key, begin
  variable (key)
  for (key, 1, 127) do (
    if (key == key:Num Lock || key == key:Scroll Lock || key == key:Num Lock) then (continue)
    switch (key) do (
      case (key:Num Lock, key:Scroll Lock, key:Num Lock) do()  # Ignore these keys
      case (key:Ctrl, key:Alt, key:Shift) do ()  # Skip these so we will return e.g. key:Right Ctrl instead of key:Ctrl
      case (else)
        if (keypress(key)) then (exit returning(key))

Or to check to gamepad/joystick buttons too, change the 127 in the 'for' loop to 163 (the last joy: constant).

Using these scripts, you can let the player remap scripted controls for your game.

global variable (1, attack key)

plotscript, remap controls, begin
  show textbox (2)  # E.g. "Press the ATTACK key"
  variable (key)
  while (true) do (
    if (keypress (cancel key)) then (exit script)  # Cancel!
    key := find pressed key
    switch (key) do (
      # Disallow a bunch of keys that have other purposes (we don't need to check the cancel keys again)
      case (key:left, key:right, key:up, key:down, key:enter, key:space) do()
      case (else)
        if (key) then (break (2))  # Break out of both the 'switch' and the 'while'
  attack key := key

  get scancode name (1, attack key)
  show textbox (3)  # E.g. "Attack key: ${S1}" which expands to e.g. "Attack key: Right Ctrl"

And later on you could write

if (keypress (attack key)) then (...)

See Also[edit]