Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Line Groups

Players notice when an NPC says the same thing every time. Line groups let you write a handful of variants and let Bubbles pick which one plays - so your dock worker doesn’t shout “Oi, watch yer step!” on every single visit.

=> Barkeep: The fire crackles nearby.
=> Barkeep: A minstrel plucks softly in the corner.
=> Barkeep: The smell of roasting meat fills the air.

Three lines, all starting with =>. When the runner reaches this block, the active saliency strategy picks one. That one line emits a DialogueEvent::Line. The others stay silent.

With BestLeastRecentlyViewed (BLRV), the player hears a different line each visit, cycling through all three before any repeats. Set it once on the runner:

use bubbles::saliency::BestLeastRecentlyViewed;

runner.set_saliency(BestLeastRecentlyViewed::new());

Your game receives a normal DialogueEvent::Line - it doesn’t know there were three variants. It just gets the chosen one.

Saliency strategies

StrategyBehaviour
FirstAvailableAlways the first eligible line (default; deterministic)
RandomAvailableUniformly random (needs the rand feature)
BestLeastRecentlyViewedPrefers the one seen least recently

FirstAvailable is the default. It’s great for node groups where you’ve sorted variants by priority (see Node Groups and Saliency). For ambient barks, BLRV is almost always the right pick.

Conditions on variants

Each => line can have its own guard:

=> <<if $weather == "rain">> Barkeep: Dreary out, isn't it?
=> <<if $weather == "snow">> Barkeep: Mind the ice on the steps.
=> Barkeep: Another fine evening.

The strategy only picks among variants whose guard is true. The last line has no guard, so it’s always eligible - a nice “default” to keep the group from going silent.

Mixing with speaker, tags, and commands

=> lines behave like any other line: they can have a speaker, tags, even a #line:id for localisation.

=> Barkeep: Welcome back. #line:tavern_greet_01
=> Barkeep: Evening, stranger. #line:tavern_greet_02 #warm
=> Barkeep: Mind the step. #line:tavern_greet_03

You can also put commands inside a variant’s indented body:

=> Barkeep: The fire snaps louder than usual.
    <<shake_camera 0.05>>
=> Barkeep: The fire settles to embers.

A talkative guard

Line groups shine for NPCs who hang around:

title: Guard
---
Guard: Halt! ... Oh, it's you.

=> Guard: Quiet day, thankfully.
=> Guard: Thought I saw a shadow on the wall. Probably nothing.
=> Guard: My feet are killing me.
=> Guard: Heard anything from the capital?

-> Ask about the road.
    <<jump GuardRoad>>
-> Be on your way.
===

Every time you pass the guard, you hear one of four lines - and (with BLRV) probably a different one. No scripting, no counters, no bespoke code.

Not the same as options

Easy to confuse at first. Quick table:

Options (->)Line groups (=>)
Who picksThe playerThe saliency strategy
Event emittedOptionsLine
IntentBranching storyVariant / flavour

-> means “give the player a choice.” => means “you choose one for me.”


Try it: examples/snippets/saliency.bub: five ambient dock worker barks cycling with BLRV so the same line never plays twice in a row.

cargo run -p bubbles-tui -- examples/snippets/saliency.bub

Next: Node Groups and Saliency