# ST Bot Commands

Commands for Storytellers to manage characters via IRC. All ST commands are used in **#VC_Staff** only.

## Character References

ST commands take a `<ref>` argument that identifies a character. You can use any of three formats:

| Format | Example | How It Resolves |
|--------|---------|----------------|
| **Nick** | `StormRunner` | Looks up the nick in bindings, finds the slug |
| **Slug** | `storm-runner` | Matches the TOML filename directly |
| **Token** | `plane-compass-lily` | Looks up the download token, finds the slug |

Resolution order: nick, then slug, then token. Use whichever is most convenient.

## Nick Bindings

Link an IRC nick to a character so players can use spending commands and STs can reference characters by nick.

| Command | Description |
|---------|-------------|
| `!bind <nick> <slug-or-token>` | Link a nick to a character |
| `!unbind <nick>` | Remove a binding |
| `!bindings` | List all current bindings |

**Examples:**
```
!bind StormRunner storm-runner
  Bound StormRunner -> storm-runner

!bind StormRunner plane-compass-lily
  Bound StormRunner -> storm-runner    (resolved token to slug)

!unbind StormRunner
  Unbound StormRunner (was storm-runner)

!bindings
  StormRunner -> storm-runner
  Crescent -> moon-walker
```

**Note:** The bot strips `_Suffix` from nicks automatically, so `StormRunner_Lupus` resolves to the same binding as `StormRunner`.

## Querying Characters

| Command | Description |
|---------|-------------|
| `!get <ref> <field>` | Get a single field value |
| `!sheet <ref>` | Full character summary |
| `!stats <ref>` | Identity, pools, health, renown, XP |
| `!attrs <ref>` | All 9 attributes |
| `!abilities <ref>` | Non-zero talents/skills/knowledges |
| `!gifts <ref>` | Gifts by category |
| `!rites <ref>` | Rites |
| `!carried <ref>` | Carried items |
| `!owned <ref>` | Owned items |
| `!form <form> <ref>` | Character's stats in a Garou form |
| `!specs <ref>` | Specialties |
| `!notes <ref>` | ST notes |

These are the same commands players use in DMs, but with a `<ref>` argument to specify which character.

**Examples:**
```
!get storm-runner str
  storm-runner: attributes.physical.strength = 4

!get storm-runner rage
  storm-runner: rage.current = 5

!sheet storm-runner
  Storm Runner -- Ahroun, Get of Fenris, Rank 3
  Rage: 7/7, Gnosis: 4/4, Willpower: 5/5
  Health: OOOOOOO  (Healthy)
  Glory: 5/6, Honor: 2/3, Wisdom: 1/2
```

## Rest (ST Override)

Put a character to sleep from the staff channel. Bypasses the 18-hour cooldown.

| Command | Description |
|---------|-------------|
| `!sleep <ref>` | Trigger sleep for a character (no cooldown) |

**Example:**
```
!sleep storm-runner
  Storm Runner sleeps: +1 beat, WP 6/8 -> 7/8, Rage 3/7 -> 4/7, healed 2B 1L
```

## Modifying Characters

| Command | Description |
|---------|-------------|
| `!set <ref> <field> <value>` | Set a field to a specific value |
| `!give <ref> <field> <amount>` | Add to a numeric field |
| `!take <ref> <field> <amount>` | Subtract from a numeric field |

**Examples:**
```
!set storm-runner rank 4
  storm-runner.identity.rank = 4 (was 3)

!set storm-runner tribe "Shadow Lords"
  storm-runner.identity.tribe = "Shadow Lords" (was "Get of Fenris")

!give storm-runner xp 5
  storm-runner: XP +5 (total: 30, current: 25)

!take storm-runner xp 3
  storm-runner: XP -3 (spent: 8, current: 22)

!take storm-runner rage 2
  storm-runner.rage.current - 2 = 5
```

**Tip:** Use `!set ref field ""` (with quotes) to clear a string field.

## Health Commands

Track damage and healing with the WtA health system.

**Health track symbols:**
- `O` = Healthy (clear)
- `/` = Bashing
- `X` = Lethal
- `*` = Aggravated

The track is always sorted by severity: `*X/O` (worst first).

| Command | Description |
|---------|-------------|
| `!damage <ref> <type> <amount>` | Apply damage |
| `!heal <ref> <type> <amount or all>` | Heal damage |

**Damage types:** `bashing` (or `b`), `lethal` (or `l`), `aggravated` (or `a`, `agg`)

**Examples:**
```
!damage storm-runner bashing 2
  storm-runner: Health OOOOOOO -> //OOOOO (Hurt, -1)

!damage storm-runner l 1
  storm-runner: Health //OOOOO -> X//OOOO (Injured, -1)

!damage storm-runner agg 1
  storm-runner: Health X//OOOO -> *X//OOO (Wounded, -2)

!heal storm-runner bashing all
  storm-runner: Health *X//OOO -> *XOOOOO (Hurt, -1)

!heal storm-runner lethal 1
  storm-runner: Health *XOOOOO -> *OOOOOO (Bruised)

!heal storm-runner a 1
  storm-runner: Health *OOOOOO -> OOOOOOO (Healthy)
```

**Overflow rules:**
- When the track is full, bashing overflows to lethal
- Lethal overflows to aggravated
- Higher-severity damage pushes lower-severity damage down the track

**Wound penalties:**

| Level | Penalty |
|-------|---------|
| Bruised | 0 |
| Hurt | -1 |
| Injured | -1 |
| Wounded | -2 |
| Mauled | -2 |
| Crippled | -5 |
| Incapacitated | -- |

## List Management

Manage any list field on a character sheet: notes, deed names, gifts, rites, and possessions.

| Command | Description |
|---------|-------------|
| `!list <ref> <field>` | View entries (numbered) |
| `!list add <ref> <field> <value>` | Add an entry |
| `!list remove <ref> <field> <n>` | Remove entry by number |

**Available fields:**

| Field Name | What It Manages |
|------------|----------------|
| `notes` | ST notes |
| `deed_names` (or `deednames`, `deeds`) | Deed names |
| `rites` | Known rites |
| `gifts` | All gifts (view only, shows all categories) |
| `gifts.breed` | Breed gifts |
| `gifts.auspice` | Auspice gifts |
| `gifts.tribe` | Tribe gifts |
| `gifts.other` | Other gifts |
| `carried` | Carried possessions |
| `owned` | Owned possessions |

**Examples:**
```
!list storm-runner notes
  storm-runner notes:
    1. Owes favor to Iron Raven
    2. Suspected of Wyrm taint

!list add storm-runner notes Pack contact: Whispers-in-Dark
  storm-runner: notes #3 added

!list remove storm-runner notes 2
  storm-runner: notes #2 removed

!list storm-runner deed_names
  storm-runner deed_names:
    1. Storm Runner
    2. Wyrm's Bane

!list add storm-runner deed_names Fenris-Tooth
  storm-runner: deed_names #3 added

!list storm-runner gifts
  storm-runner gifts:
    Breed:
      1. Razor Claws
    Auspice:
      1. Inspiration
      2. Spirit of the Fray
    Tribe:
      1. Halt the Coward's Flight

!list add storm-runner gifts.tribe Halt the Coward's Flight
  storm-runner: gifts.tribe #2 added
```

**Note:** Players can view their own notes via `!notes` in a DM to the bot.

## Weather Management

Control the `!weather` command output. The bot normally fetches live weather data from Vail, CO and generates atmospheric prose via AI. These commands let you override or style that output.

| Command | Description |
|---------|-------------|
| `!weather set <text>` | Replace weather with a custom description (440 char limit) |
| `!weather tone <style>` | Set the AI prose style (e.g., "noir detective", "foreboding") |
| `!weather clear` | Clear the override and tone, return to default |

**Examples:**
```
!weather set A bitter wind howls through the valley. Snow drifts across I-70.
  Weather override set.

!weather tone noir detective narration
  Weather tone set to: noir detective narration

!weather clear
  Weather override and tone cleared.
```

Setting a tone or clearing both will refresh the weather on the next `!weather` query.

## News Management

Manage announcements and events that players see with `!news`. Categories are `a` (announcements) and `e` (events). Content is stored in wiki markdown files.

| Command | Description |
|---------|-------------|
| `!news add <a\|e> <title> \| <body>` | Add an entry (pipe separates title from body) |
| `!news rm <a\|e> <number>` | Remove an entry by number |
| `!news edit <a\|e> <number> <title> \| <body>` | Replace an entry |

**Examples:**
```
!news add a Server Maintenance | The server will be down for maintenance on Friday.
  announcements: #3 added

!news rm a 3
  announcements: #3 removed

!news edit a 1 Updated Title | Updated body text.
  announcements: #1 edited
```

## Chronicle Ticker

Post quick notes to the chronicle ticker after running scenes. Entries appear on the Storyline Dashboard feed and are visible to all STs.

| Command | Description |
|---------|-------------|
| `!log <message>` | Post a freeform entry to the chronicle ticker |

**Examples:**
```
!log Ran the mine scouting scene, players found corporate equipment at the entrance

!log Kalipeda debriefed with Luca at the monitoring station, samples handed off
```

The bot echoes back your entry: `Logged: "your message here"`

Ticker entries are also created automatically when STs complete storyline steps, change storyline statuses, or add log entries through the web interface. The `!log` command is for everything that doesn't belong to a specific storyline: freeform chronicle activity.

## Admin Commands

| Command | Description |
|---------|-------------|
| `!join #channel` | Join a channel (persisted) |
| `!part #channel` | Leave a channel (persisted) |
| `!reload` | Hot-reload channels and bindings from disk |
| `!ghost` | NickServ GHOST to reclaim the bot's nick |

## Logging

All commands that modify character data (`!set`, `!give`, `!take`, `!damage`, `!heal`) are logged to **#VC_Log**. Each log entry includes the ST's nick, the command, and a timestamp. Player spending commands (`!rage`, `!gnosis`, `!wp`) and description changes (`!desc`) are logged there as well.

This gives STs a running audit trail of every character change made through the bot.

## Field Reference

### Shorthand Aliases

These shortcuts work with `!get`, `!set`, `!give`, and `!take`:

**Attributes:**

| Shorthand | Full Path |
|-----------|-----------|
| `str` | attributes.physical.strength |
| `dex` | attributes.physical.dexterity |
| `sta` | attributes.physical.stamina |
| `cha` | attributes.social.charisma |
| `man` | attributes.social.manipulation |
| `app` | attributes.social.appearance |
| `per` | attributes.mental.perception |
| `int` | attributes.mental.intelligence |
| `wit` | attributes.mental.wits |

Full names also work: `strength`, `dexterity`, `stamina`, `charisma`, `manipulation`, `appearance`, `perception`, `intelligence`, `wits`.

**Pools** (default to current value):

| Shorthand | Full Path | For Max |
|-----------|-----------|---------|
| `rage` | rage.current | `rage.max` |
| `gnosis` | gnosis.current | `gnosis.max` |
| `willpower` or `wp` | willpower.current | `willpower.max` |

**Renown** (default to current value):

| Shorthand | Full Path | For Max |
|-----------|-----------|---------|
| `glory` | renown.glory.current | `renown.glory.max` |
| `honor` | renown.honor.current | `renown.honor.max` |
| `wisdom` | renown.wisdom.current | `renown.wisdom.max` |

**Identity:**

| Shorthand | Full Path |
|-----------|-----------|
| `name` | identity.name |
| `player` | identity.player |
| `tribe` | identity.tribe |
| `auspice` | identity.auspice |
| `breed` | identity.breed |
| `rank` | identity.rank |
| `concept` | identity.concept |
| `deed_names` | identity.deed_names (list, use `!list`) |

**Abilities** (use full names to avoid ambiguity):

{cyan}Talents:{/cyan} `alertness`, `athletics`, `brawl`, `empathy`, `expression`, `intimidation`, `leadership`, `primal_urge`, `streetwise`, `subterfuge`

{cyan}Skills:{/cyan} `animal_ken`, `crafts`, `drive`, `etiquette`, `firearms`, `larceny`, `melee`, `performance`, `stealth`, `survival`

{cyan}Knowledges:{/cyan} `academics`, `computer`, `enigmas`, `investigation`, `law`, `medicine`, `occult`, `rituals`, `science`, `technology`

**Experience:**

`!give ref xp` and `!take ref xp` have special handling (see **Awarding XP** below). For direct field access, use explicit paths:

| Shorthand | Full Path |
|-----------|-----------|
| `xp` | experience.current |
| `xp.total` | experience.total |
| `xp.spent` | experience.spent |

**Other:**

| Shorthand | Full Path |
|-----------|-----------|
| `health` | health_track |
| `history` | history.text |
| `irc_description` (or `ircdesc`) | description.irc_description |

### Using Full Paths

You can always use the full dotted path instead of a shorthand:
```
!get storm-runner attributes.physical.strength
!set storm-runner renown.glory.max 6
!get storm-runner abilities.talents.brawl
```

### List Fields

These fields are string arrays managed with the `!list` command. Players can query some of them in a DM:

| Field | Player Reads With | ST Manages With |
|-------|-------------------|-----------------|
| Notes | `!notes` | `!list <ref> notes` |
| Deed names | `!deednames` | `!list <ref> deed_names` |
| Gifts (breed, auspice, tribe, other) | `!gifts` | `!list <ref> gifts.breed` etc. |
| Rites | `!rites` | `!list <ref> rites` |
| Carried items | `!carried` | `!list <ref> carried` |
| Owned items | `!owned` | `!list <ref> owned` |
| Specialties (attributes, abilities) | `!specs` | edit via wiki |

Specialties are map-of-lists, not simple lists, so they're still edited by downloading the TOML and uploading through the wiki.

## Example Workflows

### Combat Scene: Dealing Damage

```
!damage storm-runner bashing 3     Apply 3 bashing
!damage storm-runner l 1           Then 1 lethal on top
!sheet storm-runner                Check current state
```

### Post-Combat Healing (Garou)

Garou heal all bashing after a scene:
```
!heal storm-runner bashing all     Clear all bashing
!sheet storm-runner                Verify
```

### Awarding XP After a Session

`!give ref xp` adds to both **total** and **current** in one command. `!take ref xp` moves points from current to spent (validates you have enough).

```
!give storm-runner xp 3
  storm-runner: XP +3 (total: 33, current: 28)

!take storm-runner xp 5           Player spends 5 XP
  storm-runner: XP -5 (spent: 10, current: 23)
```

### Rank Up

```
!set storm-runner rank 3
!set storm-runner renown.glory.max 6
!set storm-runner renown.honor.max 5
!give storm-runner willpower.max 1
!list add storm-runner deed_names Wyrm's Bane
```

### New Character Setup

```
!bind PlayerNick storm-runner      Link their nick
!sheet storm-runner                Verify the sheet loaded
```
