Download the exact captured file
---
name: nqtr-ink
description: Use when writing .ink files in a Pixi'VN project that uses @drincs/nqtr — every NQTR hashtag command (# enter room, # set time, # set date, # wait, # add/remove activity, # add/remove routine, # start/continue quest) and the quest state variables (questId_started, _completed, _failed, _currentStageIndex), plus createNqtrHandler setup and options. Prefer this over TypeScript labels whenever ink is configured.
---
# NQTR in ink
Official docs: [pixi-vn.com/nqtr](https://pixi-vn.com/nqtr). Ink basics, Vite plugin and the generic hashtag-command mechanism: skill `pixi-vn-ink`. Entities referenced here (rooms, activities, commitments, quests) must already be defined and registered in TypeScript, see [nqtr](../getting-started/SKILL.md).
## When to use this skill
Use it for any `.ink` line that changes or reads NQTR state. If the project uses ink, write NQTR interactions here instead of in TypeScript labels.
## Setup
```ts
import { createNqtrHandler } from "@drincs/nqtr/ink";
createNqtrHandler(); // once, with the other ink initialization
```
`createNqtrHandler(options?)` registers all commands below plus the quest variable getter. Options: `timeConverter(time: string) => number` (default: `"01:30"` → `1.5`, i.e. replaces `:` with `.`), `dateConverter(date: string) => number` (default `Number`), `wait(delta)` (replace the default time/date increase), and `activityIds` / `commitmentIds` / `questIds` / `roomIds` (readonly id arrays, e.g. the `nqtr*Ids` generated by `vitePluginNqtr`, to validate ids). Without id arrays any string is accepted. `nqtrHandler()` is a deprecated alias.
## Commands
In the syntax below `<...>` is a placeholder, not ink interpolation.
| Command | Effect |
| --- | --- |
| `# enter room <roomId>` | `navigator.currentRoom = room`; location and map follow |
| `# set time <time>` | `timeTracker.currentTime`; accepts `18`, `18.30`, `18:30` |
| `# set date <date>` | `timeTracker.currentDate` |
| `# wait` | advance time by `timeTracker.defaultTimeSpent` |
| `# wait <time>` | advance time by that many hours (rolls over to the next date after `dayEndTime`) |
| `# wait days <n>` | advance `n` days, time reset to `dayStartTime` |
| `# wait days <n> hours <t>` | advance both |
| `# add activity <activityId> in <roomId>` | runtime link (saved with the game) |
| `# remove activity <activityId> from <roomId>` | unlink a runtime-linked activity |
| `# add routine <commitmentId> in <roomId>` | runtime-link a commitment (saved) |
| `# remove routine <commitmentId>` | remove a runtime-linked commitment |
| `# start quest <questId>` | `quest.start(props)` |
| `# continue quest <questId>` | `quest.continue(props)`, i.e. go to the next stage |
Unknown ids log a warning (`Room x not found`) and the command is skipped. Commands go on their own line or as a tag on a content line; follow the placement rules from `pixi-vn-ink-hashtag-commands`.
```ink
=== start ===
# enter room mc_room
# set time 08:00
# add activity order_product in mc_room
# start quest aliceQuest
mc: Let's begin.
# wait 2
# wait days 1 hours 8
-> DONE
```
## Quest variables
The handler also resolves read-only quest state in ink expressions, where `<id>` is the quest id:
| Variable | Type |
| --- | --- |
| `<id>_started` | boolean |
| `<id>_completed` | boolean |
| `<id>_failed` | boolean |
| `<id>_currentStageIndex` | number (0-based; `stages.length` once completed) |
```ink
=== talk_alice ===
{ aliceQuest_currentStageIndex:
- 0: -> talk_alice0
- 1: -> talk_alice1
- else: alice: Thanks for the book.
}
-> DONE
= talk_alice0
alice: Can you order me a book from the PC?
# continue quest aliceQuest
-> DONE
```
```ink
+ {aliceQuest_started && not aliceQuest_completed} Ask about the quest
```
Do not declare `VAR aliceQuest_started` in ink; the value comes from NQTR. Failing a quest has no hashtag command: set `quest.failed = true` in TypeScript (or from a custom hashtag command, see `pixi-vn-ink-hashtag-commands`).
## Not available from ink
Creating/registering entities, `timeTracker.initialize`, `navigator` queries beyond `enter room`, `quest.advanceIfCompleted`, hiding/disabling entities, `timeTracker.isWeekend`/`currentTimeSlot`. Do these in TypeScript, or expose them with a custom hashtag command / external function.
## Typical call from the UI into ink
Activities and commitments run `onRun(entity, props)` in TypeScript; to hand over to ink, jump to the knot: `await narration.jump("knot_name", props)` (ink knots are Pixi'VN labels). See [nqtr-activity](../activity/SKILL.md).