Writing Scripts in PawScript
PawScript comes in two forms: expressions — small <<…>> snippets that can be used to return a value or to insert a value into your text — and scripts, which can be more than one line and are used to change aspects of the game, such as the values of your Tracked Items. You already know expressions from your writing — <<health>>, <<$party.count()>>, and so on. This guide is about the other form: a script is a few lines of PawScript that change your tracked items when a trigger fires. Heal everyone in the party, spend some gold, tick a quest forward, tidy up a list — that sort of thing.
You write a script in the “Run a script” trigger effect. The only thing a script can do is change the values of your tracked items — it can't show messages, talk to the AI, or touch anything else. That makes scripts safe to experiment with.
New to PawScript? Read the Beginner's Guide to PawScript Expressions first — it covers values,
$variables, and the dot‑paths ($party.item(1).hp) that scripts build on. Try as you read: open the PawScript Playground to run scripts against sample data.
A first script
Here's a complete script. Imagine a tracked item called party that holds a list of characters, each with a hp, a luck and a healing value. This rolls a chance for each member and heals the lucky ones:
for each $member in $party
if random()*100 < $member.luck
$member.hp += $member.healing
That's the whole shape of a script: go through some things (for each), check a condition (if), and change a value (+=). Everything below is just those three ideas in more detail.
Two things to notice. Indentation matters — the lines under a for each or if are indented to show they belong to it, exactly like a bulleted list with sub‑points. And $member is the actual party member, so changing $member.hp really does change that member inside $party.
Changing values
The simplest line sets a value:
$gold = 100
To adjust a value relative to what it already is, use the shorthands. += means “add to”, -= means “subtract from”:
$gold += 50 # earn 50 gold
$health -= 10 # take 10 damage
$score *= 2 # double it
The full set is +=, -=, *=, /= and %=. The right‑hand side can be any PawScript expression you already know — dice_roll(6), $base + $bonus, random()*100, and so on.
You can reach inside structured (YAML) items with a dot‑path, just like when you show them:
$player_state.flags.met_wizard = "true"
$inventory.potions.quantity -= 1
$party.item(1).hp = 30 # the first party member
List positions count from 1 (the first item is item(1)), the same as everywhere else in PawScript. Setting a path that doesn't exist yet creates it.
Going through a list or a group
for each repeats some lines once for every item:
for each $member in $party
$member.hp += 5
This works for a list (each entry in turn) and for a labelled group/map (each value in turn). The indented lines run once per item, with $member standing for the current one.
If you just want to repeat something a fixed number of times, loop over range(n) — it counts 1, 2, … n:
for each $i in range(3)
$quiver.append("arrow")
Making decisions
if runs its lines only when a condition is true. You can add else if for more cases and else for “otherwise”:
if $hp <= 0
$status = "defeated"
else if $hp < 10
$status = "wounded"
else
$status = "healthy"
Conditions are ordinary PawScript tests — $hp > 0, $gold >= $price, $name = "Frodo", and you can join them with and / or.
Working variables
Sometimes you need a scratch value to add things up. Make one with set. It exists only while the script runs and is thrown away afterwards — it never becomes a tracked item:
set $total = 0
for each $member in $party
set $total = $total + $member.hp
$party_hp = $total # store the total in a real tracked item
(Writing to a name that isn't a tracked item without set is treated as a mistake, so a typo can't quietly vanish.)
Adding to and removing from lists
$inventory.append("Excalibur") # add to the end of a list
$inventory.remove("rusty key") # remove every matching entry
$player_state.remove("curse") # remove a map key entirely
You can also select first and remove what matched — $party.where(hp <= 0).remove() drops every defeated member in one line.
Comments
Anything after a # is a note to yourself and is ignored when the script runs:
# Give everyone a small heal at dawn
for each $member in $party
$member.hp += 2 # gentle overnight recovery
Scripts can't run away
Scripts are deliberately limited so they're safe in a shared world:
- The only thing they change is your tracked items. System values like
$game.turn_numberand$player.namecan be read but never written — a script that tries gets a friendly error. - There's no “repeat forever” loop — every loop is over a list, a map, or a bounded
range(n)— so a script always finishes. - If a script hits a problem (or tries to do an absurd amount of work), it stops and nothing is changed — your items are never left half‑updated. The problem is noted in the World Debug log, and the game carries on.
Cookbook
Spend gold to buy something (only if you can afford it):
if $gold >= 50
$gold -= 50
$inventory.append("healing potion")
Clamp health into a sensible range after other effects:
$health = $health.constrain(0, 100)
Level everyone up and refill their health:
for each $member in $party
$member.level += 1
$member.hp = $member.max_hp
Advance a quest stage:
if $quest.stage = "find_key"
$quest.stage = "open_door"
Cheat sheet
$x = value— set a value (+= -= *= /= %=to adjust)for each $item in $list— repeat for every item (indent the lines below)for each $i in range(5)— count 1 to 5if …/else if …/else— make decisionsset $name = value— a temporary working value$list.append(x)/$list.remove(x)/$map.remove("key")log("message")— leave yourself a note in the PawScript Log# …— a comment
For the full list of functions you can use on the right‑hand side, see the PawScript Reference. And remember you can try any of this safely in the PawScript Playground.
Happy worldbuilding!