Scripts in Book 2 are found in one of three places: embedded in map tiles, inside items (whenever you can "Use" an item in your inventory), and a script that an entity runs when it dies. In general, most of the script commands that I've found can be run in any of those places, though some commands only make sense in one context.

Commands can be separated with a semicolon, most often with whitespace around them, so to show a message to the player and play a sound effect, you'd do something like "msg (You hear a noise!) ; sound (sfx_portal)". Note that if you want to get pedantic about this, the semicolon itself isn't even necessary; the parser seems to just ignore them. The semicolons make things much more readable for humans, though, so I recommend you continue to use them.

An example command definition here will be given like so:

asfx (<soundname>) <coords>

The parentheses there are part of the actual command; they should be included if you're using the command. Anything in italics and angle brackets is data that you, as a map editor, should replace with the correct values. Whenever you see <coords> in a command, you'll be using a simple number of the form "YYYXX", though you don't need to zero-pad the number. For instance, the coordinate (34, 125) becomes 12534. The coordinate (5, 28) becomes 2805. Note that the coordinate 0 is considered special, and will cause the effect to happen on the same tile where the script was executed from.

The Book 2 script parser appears to have a fifty-token limit. A "token" in this case is simply one component of the command. The above asfx example would be three tokens: one for "asfx," one for the sound name, and one for the coordinates. When parentheses are used, it appears that everything inside the parens counts as a single token. So if you're using the msg command to do something like "msg (The gate opens behind you, letting forth a torrent of rats!)", that would only count as two tokens. There is probably a limit to how long a single token can be, and there's also probably a limit to how long a whole script can be, characterwise, but I don't know what those are. Regardless, if you go over fifty tokens in a single script, the game will crash once it tries to execute that script.

Commands which seem to be only present in Book 2 will be highlighted in blue. Commands which exist in Book 1 but with a different name will be highlighted in yellow. Commands from Book 1 which are still present in the engine but don't seem to be used by any of the Book 2 scripts will be highlighted in gray. It's probably safe to use those scripts, but it's possible that they're considered deprecated or something.

Note that even though many of these commands are valid in both Book 1 and Book 2, they might behave slightly differently, or have different arguments.

General-Purpose Commands

These are commands which should theoretically be valid anywhere.

Quest-Related

Each quest has a number in Book 2 - the main quests are numbered 1 through 32, and there are other internal flags the game uses which are technically numbered as quests 100 through 122. Each quest has a "state" number associated with it. To put a quest into the player's Quest book, you'd set the state to 1. It looks like a successfully-completed quest will have a state of 9. Also, quests that haven't started yet might have a state of -1.

I've been told that it is possible to use quests higher than 122 (up to at least 20,000, actually) as state variables of your own (for more complex custom mapping, for instance). Use caution when doing so, though, since it's unknown what's happening in the program's memory area when that's being done.

quest <questnum> <state>
Set the specified quest to the specified state. State can be given as a negative number with parens, like "(-2)", which is often used when the player abandons quests. (I have also seen where the -2 is not in parens.)
kill_quest <questnum>
Mark the quest as uncompletable (quest must be currently active). Used in a few entity death scripts.
quest_step <questnum>
Increments the quest status by one. Used in the Boreheads quest, and for the spiders infesting the Port Kuudad storehouse. Note that you can't use this on "real" quests, only on the "counter" type quests. You can't complete a quest using quest_step.
all_quests
Adds all quests to the player's Quest Journal. Note that in Book II, this will cause Eschalon to crash when the player opens his journal; presumably this ends up adding an "invalid" quest to the journal in addition to the good ones.

Conditional Statements

These are used to conditionally execute scripts. All of these will abort the execution of the script unless the condition is met. There doesn't appear to be any "else" clause or the like - if the condition isn't met, the script execution will simply stop.

condition (<text>) (<yes text>) (<no text>)
Displays a message (on parchment) to the player, with the two given options, and the script will only continue if the user hits "Yes." The last two arguments are usually "Yes" and "No," but it seems they can be just about anything.
cond_item (<itemname>)
Script will terminate unless you have the named item
cond_not_item (<itemname>)
Script will terminate if you DO have the named item
cond_quest <questnum> <state>
Script will only continue if the specified quest is at the specified state
cond_not_quest <questnum> <state>
Script will only continue if the given quest is NOT at the specified state
cond_special <num>
Special condition, will only continue if some internal criteria is met. Probably not very useful to custom map makers. The special conditions seen in the game:
  1. Bronze puzzle (in Ruel's House)
  2. Chest puzzle in Port Kuudad Sewers is solved correctly
  3. Has all four bells in inventory
  4. Switch puzzle in Talushorn Level 3 (releases Dragonels if failed)
cond_spot
Script will only continue if the player passes a Spot Hidden check (typically this is triggered by a type 13 object, triggered by proximity).
cond_touch
Script will continue if the script was triggered through a player click.
cond_health
Script will only continue if the user isn't at full health (used in healing elixirs).
cond_mana
Script will only continue if the user isn't at full mana (used in mana potions).
cond_gold <goldamount>
Script will only continue if the user has at least the specified gold.
cond_detected
Unknown - has always returned "true" for me.
cond_state <coords> <state>
Script will only continue if the object at the given coordinates is in the state given. This is typically used to check toggle states. Valid states in the game, used by doors, chests, other containers, and toggle switches:
  1. Closed
  2. Open
  3. Broken
  4. Toggle 1 (upright)
  5. Toggle 2 (toggled)

Interactions with the Player

give_item (<itemname>)
Place the named item in the player's inventory
remove_item (<itemname>)
Remove the named item from the player's inventory. You may want to call a cond_item first, to be safe.
strip_items
Removes all items from the player's inventory, including torches but excluding gold.
move_player <coords>
Send the player to the given coordinates, within this map.
portfx
Generate some portal effects, centered on the player square. This is sort of an analogue of "sound (sfx_portal) ; gfx (Port) 0 0" except that it's centered on the player, so you don't need to specify the actual coordinates.
port_to <coords>
Send the player to the given coordinates, within this map, with some portal effects. Analagous to "move_player <coords> ; portfx"
map_port (<mapname>) <coords>
Send the player to the given coordantes inside 'mapname' Sometimes the parens around mapname are omitted; though it's probably best to use them. When they're omitted, it seems to always be a 'numbered' (outside) map. Note that this doesn't do an implicit portfx, so if you want the portal effects, you should do so explicitly.
add_gold <n>
Adds the specified amount of gold directly to the player's inventory
remove_gold <n>
Removes the specified amount of gold from the player's inventory
learn_recipe <recipenum>
Player learns the given alchemy recipe. Occasionally the recipenum will have parens. recipenum of "99" will give the user all recipes
gain_xp <xp>
Give the specified XP. Can include parens around the XP
visit_well
Quenches your thirst and fills your waterskins. Note that if you have an object of type 16 (well), you don't need this script.
eat <foodval> <drinkval>
Used on edible food items, but works via other scripts, too. Could implement a cafeteria or something with this.
heal <hp> <hidden>
Heal the given amount of HP; if "hidden" is greater than zero, no message will be shown in the message pane, and the graphical flourishes will be supressed
restore <mp>
Restores the given amount of MP
cure_ailment
Cures ailments. Usually this is associated with a potion, but it doesn't have to be.
cure_poison <val>
Cures poison. The value I've always seen is 4, I'm not sure what exactly it means. Usually this is associated with a potion, but it doesn't have to be.
poison <num>
Poisons the character for a total of num times, spread out over a number of turns. This actually isn't effective in Book II, as the damage taken each time will always be zero.
trauma <hp>
Injures the player by the given HP.
disease <diseasenum>
Give the player the given disease (they have a chance to save versus disease resistance, though). Diseases in the game:
  1. Tapeworms
  2. Troll Fever
  3. Eye Rot
  4. Fleshblight
player_effect <effectnum> <levelnum> <duraitionnum>
Used in potions to grant various effects, though it doesn't have to be tied to an item. The levelnum probably refers to an equivalent spell-casting level, though I don't know that for sure. The effect numbers are as follows, though it seems that not all of these actually work with player_effect:
  1. Chameleon
  2. Protection from Curses
  3. Entangled
  4. Paralyzed
  5. Poisoned
  6. Scared
  7. Stunned
  8. Off-Balance
  9. Dense Nimbus
  10. Enchanted Weapon
  11. Cat's Eyes
  12. Gravedigger's Flame
  13. Blessed
  14. Haste
  15. Ogre Strength
  16. Invisible
  17. Leatherskin
  18. Nimbleness
  19. Reveal Map
  20. Stoneskin
  21. Keensight
  22. Enkindled Weapon
  23. Elemental Armor
  24. Predator Sight
  25. Mana Fortified
  26. Greater Protection

Some potions that I've noted down:

  • Cat's Eyes Brew: 11 3 120
  • Haste I: 14 3 10
  • Haste II: 14 3 20
  • Haste III: 14 3 20
  • Ogre Strength: 14 3 120
  • Invisibility I: 16 1 10
  • Invisibility II: 16 3 20
  • Invisibility III: 16 6 30
  • Keensight: 21 3 120
  • Predator Sight: 24 3 40
  • Greater Protection: 26 3 40
  • Leatherskin: 17 3 60
  • Nimbleness: 18 3 120
  • Stoneskin: 20 3 60
  • Fortify Mana: 25 3 20
cleric_heal
Opens a dialog to allow the player to pay for divine healing. This will deduct gold if they player agrees.
cleric_dehex
Opens a dialog to allow the player to pay for divine de-hexing. This will deduct gold if they player agrees.
curse
This appears to do nothing in Book II.
full_restore
Cures all poison, and will attempt to cure diseases. In my limited testing, though, it's possible this isn't actually able to cure disease. Will leave curses untouched.
rename_item <old name> <new name>
Renames the given item in the player's inventory.
rent_room <cost> <coords>
Used for Inn scripting. Will launch a dialog offering a room for the specified cost. If accepted, the player will wake up at coords.
teach_skill (<name>) <skillnum>
Offer to train the player in the specified skill. The player will have to pay the usual fee, and be restricted to the usual Book I training limits. The name argument will just be used to display the name in the initial dialog, and does not have to match any existing NPC.

Interactions with the Map

close_door <coords>
Closes the given door. Note that there doesn't appear to be an open_door.
open_port <coords>
Open the portcullis at the given coordinates
close_port <coords>
Closes the given portcullis
toggle_port <coords>
Toggle the given portcullis
toggle_obj <coords>
Toggle the existance of a given wall - This will work for basically any graphic. Used, for instance, on the entrance to Lorewitch.
toggle_zapper <coords>
Toggles a zapper (electric field) at the given coords
destroy_obj <coords>
Completely destroys the given wall - This will work for basically any graphic.
drop_ent <entnum> <coords>
Drops the given entity at the given coordinates. (Entity Number Lookup)
remove_npc <entnum>
Removes all entities with the given ID from the current map. (Entity Number Lookup)
npc_die <entnum>
Kills the given entity. (Entity Number Lookup)
npc_disp_change <entnum> <disposition>
This appears to have no effect in Book II.
trigger_talk <entnum>
Triggers a conversation with the given entity ID. The entity must be present somewhere on the map for this to work.
convert_tile <coords> <typenum>
Converts the given tile to the given object type. Typically this is "0 1", to make hidden cave treasure clickable, after a cond_spot. Note that you can technically change to any type, but make sure that a valid object is in place already for the type you're switching to. The only thing that this changes is the Object Type itself.
areacheck
Unknown; is often called immediately after a map_port, but not always. I assume it has something to do with checking for something on the map around where the player just ported to.
det_keg <coords>
Detonates the powder keg at the given coordinates. If there's no powder keg there, this has no effect.
init_trade <entnum>
Initiates a trade window with the specified NPC. Note that Book II expects the entity ID here. The NPC must be present on the map, and be an actual merchant, otherwise Eschalon will freeze.
remove_barrier <coords>
Allow the player to walk through the given coordinates.
trap <param>
Plays a sound effect and displays some graphical effects, as if a trap had been sprung, but has no actual effect on the player or environment.
spell (<spell name>) <level>
Casts the named spell, at the given level. Unknown spell names will crash Eschalon. I haven't found a way to provide target information for this, so it looks like this command can probably only cast spells which don't require targeting, such as defensive spells. This will deduct the appropriate amount of mana from the player's pool, and can cause the player's MP to go below zero.

Other Commands

special_event <num>
Triggers the given special event. These probably aren't really useful to custom map editors, but this is what they are regardless:
  1. Darus gets killed
  2. Darus' death script (replace with container'd body)
  3. Activates Viewing Glass effect
  4. Your bed (rest until 8:00am)
  5. ?
  6. Harpen turns into a dire wolf
  7. Open entrance to Thieves' Arcadia
  8. Denied access to Crius Vindica
  9. Granted access to Crius Vindica
  10. Drink Sparkling Divinity
  11. Take the Crux of Fire from its pedestal
  12. Player kicked out of the guild, main quest uncompletable
  13. ?
  14. Snow Wolves invade Durnore (This is fun to set off in Eastwillow; most of the wolves spawn inside buildings and slaughter the mostly-helpless inhabitants)
  15. Mortikus Death (disease trap)
  16. Four bells placed in Lockston Archives
  17. Westwillow quest done, all enemies on map disappear
  18. Something about "Harpy Cages" - probably unused in the actual game
  19. Trigger endgame cinematic
  20. Trap in Cape Sorrow (paralyzed plus Cursed Undead spawn)
  21. Killed Korren at endgame (Saboteur ending)
gfx (<gfx effect>) <coords> <colornum>
Launches a fancy graphical effect at the given coordinates. Coords are usually "0" when used in an entity death script, to denote the "current tile." Effects that I've noted in the game, and the associated colornum values for each:
  • Becon
    Becon Example
    0. Yellow (no discernable change on other numbers)
  • Colored Smoke
    Colored Smoke Example
    0. white
    1. green
    2. yellow/orange
    3. blue
    4. grey
    5. black
    6. white (again)
    7. pink
  • Divine Light
    Divine Light Example
    2. White (the default; other numbers don't seem to change the effect)
  • Flare
    Flare Example
    0. (invalid)
    1. red
    2. Green
    3. Purplish-White
    4. white
  • Flare Burst (very much like Flare but rotates more)
    Flare Burst Example
    0. (invalid)
    1. red
    2. Green
    3. Purplish-White
    4. white
  • Gibs
    Gibs Example
    0. white
    1. red
    2. green
    3. black
  • Port
    Port Example
    0. Multicolored (no discernable change on other numbers)
  • Sparkles
    Sparkles Example
    0. (invalid)
    1. Red
    2. Green
    3. Purple
    4. White
    5. Green and Purple
    6. White and Purple
    7. Multicolored
  • Sparks
    Sparks Example
    0. Yellow (no discernable change on other numbers)
msg (<message text>)
Displays the given text in the message pane
narrative <narrativenum>
Displays the given narrative. This is accompanied by a little graphical flourish in the message pane, and a sound effect.
kill_narrative <narrativenum>
Tells the game engine not to display the given narrative anymore. Used when a narrative text would no longer be accurate if triggered.
activate_qt <quicktravel num>
The player "discovers" the given quicktravel point (this doesn't actually send the player to the quicktravel point, it just makes that point clickable).
book <booknum>
Shows book text (just the text, I don't believe it'll actually teach you skills, etc)
destroy_script
Destroys this script (one-time use). Note that if you try to create a one-time use portal, you'll have to call destroy_script before the portal actually takes place, because otherwise the engine will try to destroy a script on the new map, not the old one, and will likely crash.
commit_crime
Area NPCs may notice you committing a crime
no_crime
Allows access to something which would otherwise be considered a crime.
drama
Unknown. This isn't used at all in Book 2, and only once in Book 1 (and I can't figure out what it does in Book 1 either). Probably best not to use it. The command does still exist in the engine, though.
alert_npcs
Unknown. This isn't used at all in Book 2, and only once in Book 1 (and I can't figure out what it does in Book 1 either). Probably best not to use it. The command does still exist in the engine, though.
sound (<soundname>)
Plays the specified sound. The soundfile name might be case-insensitive. I have seen, for instance, both "SFX_Quaff" and "SFX_quaff". Note that the engine will change the pitch somewhat, so consecutive executions may sound slightly different. Note that the soundfiles in question live inside the datapak, so you can't add your own sounds. The soundfiles that I've seen referenced by the game:
  • 2_swallow
  • eat
  • energy
  • f_laughter
  • ghorr
  • lava_step
  • mag_door
  • sfx_energize
  • sfx_port_up
  • sfx_positive
  • SFX_Quaff
  • SFX_Restore
  • sfx_weapon_eqp_swd
  • spirit_awaken
  • stairs
  • stone_slide
  • war_horn
asfx (<soundname>) <coords>
Trigger a sound effect at another location on the map, used to make sounds which appear to happen in the distance.
display (<graphicfile>)
Displays the given graphic file (used primarily for roadsigns). Note that the graphic file referenced lives inside the datapak, so you can't add your own graphics.
time
Display the in-game time (used in chronometers)
screen_fade_in
screen_fade_out
These do what you'd expect. Note that the screen will not fade back in unless you explicitly call screen_fade_in, so be careful.
updatezones
Unknown.
delay <turns>
Advances the game time by the specified number of turns. Timed effects will expire, etc.

Usually Only Used in Entity Scripts

These commands are typically found in Entity Death scripts, and often don't make much sense in other contexts. Note that you can call these elsewhere if you want, though.

drop_gold <n>
Drops a bag with the specified quantity of gold
drop_item (<Item Name>) <percent chance>
Drops the named item with the specified percent chance. Percentage *might* be optional? Set 100 to have it always happen.
drop_loot <lootlevel>
Drops loot at the given level. 0 is cheap, 10 is great. 11 seems to always be Ectoplasm and gold, which is what Dwarven Spirits drop

Only Used in Item Scripts

These commands are only found in Item scripts, for when you "Use" them, and will typically not work outside of that context.

learn_skill <skillnum>
Teaches the player the given skill, used in books. This doesn't seem to work properly when used outside of a book - a message will display saying that the player has learned the skill, but the skill value doesn't actually go up, and shows up in red in the character status screen. If anyone can find a way to make it work outside of books, let me know.
learn_spell
Teaches the player the appropriate spell, based on the name of the Item. The item needs to be named "Scroll of Spell Name", or else the game will crash.
remove
Removes the used item from inventory
to_flask
Used on potions to turn the potion into an empty flask
drink
Used on waterskins

Only Used in Tiles/Squares

These commands are found in square/tile scripts, and don't make much sense outside of that context.

unlocked_with (<key name>)
Used on locked doors and containers, specifying the key to use.
toggle_switch
Toggle this switch's position. (Should only be used when there's a toggle switch.)