Repository navigation
EN Create Flags Variables Events
Français · Type: explanation · Audience: author · Context: engine repository, created project · Status: ready · Applies from: 4.3.0
A flag is a state: the door is open. An event is a moment: the bell just rang. quest'n'click has no separate "variable": a flag holds a value (a boolean, a number or a string), so a counter or a choice is a flag too. This page says what each one is, what the engine keeps of it, and how to choose.
A flag is a named value in the save (GameState.flags), set by commands and read by
conditions:
| Write | Read |
|---|---|
{ set: 'door_open' } (true) |
'door_open', '!door_open'
|
{ set: ['guess', 'grandpa'] } (a string), { set: ['tries', 3] } (a number) |
{ flag: 'guess', eq: 'grandpa' }, { flag: 'tries', gte: 3 }, { flag: 'tries', lt: 3 }
|
{ inc: 'tries' }, { inc: 'tries', by: -1 } (an absent or non-number flag counts from 0) |
the same |
{ unset: 'door_open' } (removed: false, absent) |
A flag stays until something changes it; a save keeps it, a load restores it. Flags are named however you like; the
validator warns about one read and never set, or set and never read. A minigame that says how it ended writes the
reserved flag minigame.<id> (4.1.16). A text can show a flag's value through a text switch,
{form?gull=e|*=} (translations).
An event is a name fired by { emit: 'bell_rang' }. Right there, in order, it moves on every script paused on
{ waitEvent: 'bell_rang' }, then runs the listeners of the current room, then the game's
(scripts and events):
// market.ts, in a rule: { gain: 'key' }, { emit: 'key_found' }
// game.ts:
events: [
{ id: 'grandpa.goes-home', on: 'key_found', once: true, do: [{ moveActor: ['grandpa', 'house'] }, { toast: 'Grandpa went home.' }] },
],if and once work as on a rule. An event is not remembered: once its listeners have run, nothing of it is left,
except what they changed (and a once listener's mark that it fired). A listener of a room the player is not in does
not hear it.
Other parts of the state answer "has it happened?" without a flag: a prop's state ({ prop: ['lamp', 'on'] }), the
inventory ({ has }), a room visited ({ visited }), where a moving character is ({ actorIn }), a topic heard
({ seen }), the count of a once, nth, cycle or random block.
| You want | Use |
|---|---|
| To remember that something happened, and test it later (next room, next session) | a flag: { set: 'x' }, then 'x'
|
| A counter (tries, coins, a price that goes down) | a numeric flag: { inc }, { flag, gte/lt }
|
| A choice among several (the player's guess, the hero picked) | a string flag: { set: ['guess', 'grandpa'] }, { flag, eq }
|
| Something that shows on screen (a lamp on, a drawer open) | a prop state, not a flag: the picture and the condition stay one thing |
| Several places to react now to one moment, without each rule knowing the others | an event: { emit } and listeners |
| A script that waits for a moment (the cook comes when the gong rings) | an event: { waitEvent }
|
| A script that waits for a state | a flag or any condition: { waitUntil: COND }
|
| Something said only the first time |
{ once: […], id }, no flag needed |
| A room that reacts later to an event that happened elsewhere | the listener sets a flag; the room's onEnter tests it |
The last row is the usual pattern: an event is not remembered, so to react the next time the player enters a room,
set a flag in the listener and test it in onEnter.
events: [{ id: 'bell.heard', on: 'bell_rang', do: [{ set: 'bell_rang_once' }] }],
// hall.ts
onEnter: [{ if: 'bell_rang_once', then: [{ say: ['butler', 'You rang?'] }] }],- Typed variables beside flags. A second store would be one more thing to save, migrate, show in the DEV panel and explain; a flag that holds a value covers counters and choices.
- Remembered events (a log of moments that conditions could query). Conditions would then depend on history, and the solver's states would grow with it. A flag set by a listener says exactly what is worth remembering.
- Code in listeners. Listeners are data, like rules, so the validator, the solver and the save understand them (principles).
- Every flag the solver can see is part of the state it explores: a flag nobody needs to read makes proofs slower.
npm run lintandvalidatepoint at flags never read. -
{ flag, lt }is true for an absent flag: testgtefirst, or set the flag at the start (start.flagsingame.ts), when absent must mean "zero tries". - Renaming a flag breaks old saves unless a migration renames it too (
migrations: [{ from, renameFlag }], state and saves).
Limit ·
event-not-rememberedAn event fired while a listener's condition is false, or in a room whose listeners are not in scope, is lost for that listener: nothing replays it later. Use a flag for anything that must survive.
- ADR 0002, content is data: listeners and flags are data the tools read.
- ADR 0003, the solver runs the real engine: every flag is part of the state it explores.
- References: commands, logic, conditions, scripts and events, the generated DSL reference.
Generated publication · publication générée — current documentation · documentation courante: quest'n'click 4.4.0 r1, documentation revision · révision de la documentation 8dc717c69acb62c4742b69c54a7e7dfb620f75d8.
Earlier versions and permalinks · versions précédentes et liens permanents: https://wanoo.github.io/quest-n-click/docs/
An edit made in this wiki is overwritten at the next publication · une modification faite dans ce wiki est écrasée à la publication suivante.
Edit the source · Modifier la source · Report an error · Signaler une erreur
Index (6)
Start (6)
Play (9)
Install (17)
- Requirements
- Install from the release archive
- Install from npm, once published
- Install from the repository to work on the engine
- doctor: checking your machine
- Image toolchain
- Audio toolchain: ffmpeg, fluidsynth, Furnace, uv
- Upgrade
- Upgrade notes: 4.4
- Upgrade notes: 4.3
- Upgrade notes: 4.2
- Upgrade notes: 4.1
- Upgrade notes: v3
- Upgrade notes: v2 to v3
- Coming from web-scumm
- Package reference
- Install troubleshooting
Create a game (55)
- Your first game
- Layout of a created project and of the engine repository
- The working loop
- Content principles and the identity contract
- Rooms
- Geometry: placement, walk zones, masks, layers, camera
- Something is visible but unreachable
- Reactions
- Game commands
- Conditions
- Flags, variables and events: which to use
- Custom code
- Characters
- Items and inventory
- World map
- Dialogues
- Scripts and events
- Moving characters: patrols and walks
- Exits
- Chapters and objectives
- State and saves: persistent or temporary, renaming an id, migrations
- Staging: wide rooms and animations
- The stage: lights, particles, floors
- Skin and fonts
- Title and credits
- Heroes: several characters and hero choice
- Built-in minigames
- A custom minigame
- Translations
- Music in stems
- Sound effects
- Voices: per language and per hero
- Images: prompts, cutting sheets, transparency, scale
- Asset provenance
- The storyboard, source of truth
- Puzzle design
- Classic mechanics
- Review pages
- DSL reference
- Checking your game
- What the solver proves
- Solver options
- Playtests
- Remix
- Speedrun for authors
- The sealed ending
- Production template
- Example games
- Working with an AI
- Build and release a game
- Publish on GitHub Pages
- The static game on Clever Cloud
- Other static hosts
- Sub-path, cache and service worker, incomplete deploys, going back
- Testing on a phone over the LAN
Local Studio (24)
- The local Studio: overview and launch
- Edit a room
- Placement and stage
- Preview, apply, undo
- Storyboard
- Assets and cutting
- Check: validator, solver, critical path, heat, health, coverage
- Before and after captures
- Semantic diff
- Play and replay a session
- Rule explainer
- Language and objectives
- Voices and the heroes × languages matrix
- Map
- Notes
- Remix in the Studio
- Music
- The Assistant: bring your own key
- Demo mode and studio-apply
- Local and LAN security
- Studio API
- Local MCP: setting up each client
- MCP tools
- Studio troubleshooting
Team Studio (21)
- What runs where
- Concepts: revision, transaction, span, lease, preview, build
- Starting as an invited dev
- Working together day to day
- Roles and actions: the full matrix
- Invitations
- Managing members
- Write refused on the hosted Studio: stale base revision (409)
- Write refused on the hosted Studio: span locked (423)
- Recovering after a lost lease, a disconnection or a stale preview
- Comments
- Map and semantic diff
- Publishing builds
- Remote MCP
- The game in Git
- Upgrading the engine of a hosted game
- Hosted assets
- The server's command line
- Health and metrics routes
- Trying it locally with compose.yml
- Known limits
Clever Cloud (23)
- Clever Cloud: overview, cost and prerequisites
- Apps and add-ons
- Domains and TLS
- Keycloak
- Generic OIDC and GitLab
- Configuration
- First deployment
- Backups
- RPO and RTO
- Restore the Studio on a fresh installation
- Redeploys
- Upgrading the server and checking state after a migration
- Limits of going back
- Monitoring
- Security
- Rotating keys
- Recovering admin access
- Changing domain or OIDC provider
- Worker, PostgreSQL or Cellar down
- Exporting the game and leaving the installation
- Retention
- Clever Cloud troubleshooting
- Costs and teardown
Reality Bridge and connectors (16)
- The Reality Bridge: what it is
- Quick start
- Guarantees
- Install and run the Bridge
- Backup and restore
- Several tenants
- Signals and the manifest
- The Bridge's command line
- Connectors overview
- Email connector
- Telnet connector
- SSH connector
- Open Badges connector
- The connector SDK
- Security: Biscuit and signatures
- Bridge and connector troubleshooting
Contribute (25)
- Welcome
- Developer setup
- The dev loop
- Before a pull request
- Conventions
- Writing documentation
- Architecture
- Code tour
- Import boundaries
- Which tests run when
- Mutation testing
- The coverage ratchet
- The quality baseline
- CI explained
- Field passes
- Benchmarks
- Releasing
- npm packages
- Decisions and ADRs
- Governance
- Bot pull requests
- Contributing with AI agents
- Security policy
- Code of conduct
- Licences and credits