Download the exact captured file
---
name: nqtr-activity
description: Use when creating NQTR activities (actions the player can take, linked to rooms/locations/maps) — ActivityBaseModel, RegisteredActivities, linking at init (activities in the room constructor) vs at runtime (room.addActivity / "# add activity X in room"), unlinking, timeSlot/dateScheduling, disabled/hidden, and custom Activity classes.
---
# NQTR activities
Official docs: [pixi-vn.com/nqtr/activity](https://pixi-vn.com/nqtr/activity). Index: [nqtr](../getting-started/SKILL.md). Ink commands: [nqtr-ink](../ink/SKILL.md).
An activity is an action the player can take (sleep in the bed, order a product, ...) linked to a navigation element ([rooms/locations/maps](../navigation/SKILL.md)). How it is shown and triggered (button, icon, sprite) is up to your UI.
## Initialize
`new ActivityBaseModel(id, onRun, props)`; register with `RegisteredActivities.add(...)` (**required**). `onRun(activity, props)` receives the `OnRunProps`; typically navigate to the narration screen, then jump to the story label/knot. When the story is written in ink, jump to the ink knot with the same name.
```ts title="content/activities.ts"
import { ActivityBaseModel, RegisteredActivities, timeTracker } from "@drincs/nqtr";
import { narration } from "@drincs/pixi-vn";
export const bed = new ActivityBaseModel(
"bed",
async (_, props) => {
await props.navigate({ to: "/game/narration" });
await narration.jump(timeTracker.nowIsBetween(5, 22) ? "nap" : "sleep", props);
},
{ name: "bed" },
);
RegisteredActivities.add(bed);
```
```ink
=== nap ===
mc: A short nap.
# wait 2
-> DONE
```
`ActivityProps`: `name`, `timeSlot` (`{ from, to? }`, active only in that time range), `dateScheduling` (`{ from, to? }`, active only in that date range), `disabled` / `hidden` (boolean or a Pixi'VN flag name), `renderIcon`.
## Link (many-to-many)
An activity is only available when linked to a navigation element.
1. **At initialization** — `activities: ["bed"]` in the room/location/map constructor. Not saved with the game, so you can change it between versions without migrations.
2. **During the game** — saved with the game; for temporary activities.
```ink
# add activity order_product in mc_room
```
```ts
mcRoom.addActivity("order_product"); // or the activity instance
```
## Unlink
Only activities linked at runtime can be removed:
```ink
# remove activity order_product from mc_room
```
```ts
mcRoom.removeActivity("order_product");
```
Init-time links cannot be removed; use `disabled`/`hidden` or `timeSlot`/`dateScheduling` to control them.
## Get
`RegisteredActivities.get(id)` and `RegisteredActivities.values()`. `activity.isActive(options?)` tells whether it is available for the current time/date; `activity.expired` whether its date range has passed.
## Custom class
Extend `ActivityStoredClass` and implement `ActivityInterface`; augment the interface in `nqtr.d.ts` with `name`, `disabled`, `hidden`, `sprite?`, `icon?`. Constructor: `super(id, onRun, props)` with `ActivityStoredClassProps` (`timeSlot`, `dateScheduling`). Persist `disabled`/`hidden` via `getStorageProperty`/`setStorageProperty`. Override `isActive` to return `false` when `hidden`, and `run` to refresh the UI after running (`await runProps.invalidateInterfaceData()`), as the templates do.
## Pitfalls
- Forgetting `RegisteredActivities.add`.
- Linking by id before the activity is registered: register activities before use, or rely on the id lists/Vite plugin for validation.
- Prefer a stable id: ink commands use it.