Skip to content

DialogPlugin

Manages dialog display and pagination for game conversations.

Location

Configuration

The DialogPlugin uses the following settings from pedre.conf.settings:

Behavior Settings

  • DIALOG_AUTO_CLOSE_DEFAULT - Default auto-close behavior when not explicitly specified (default: False)
  • DIALOG_AUTO_CLOSE_DURATION - Seconds to wait after text reveal before auto-closing (default: 0.5)
  • DIALOG_CHAR_REVEAL_SPEED - Characters per second for text reveal animation (default: 20)
  • DIALOG_INSTANT_TEXT_DEFAULT - Whether text appears instantly by default (default: False)
  • DIALOG_SHOW_HELP - Whether to show instruction text (default: True)
  • DIALOG_SHOW_PAGINATION - Whether to show page indicators (default: True)

Input Settings

  • DIALOG_KEY_ADVANCE - Key for advancing dialog pages and closing dialogs (default: "SPACE")

Layout Settings

  • DIALOG_BOX_WIDTH_PERCENT - Dialog box width as fraction of window width (default: 0.75)
  • DIALOG_BOX_MAX_WIDTH - Maximum dialog box width in pixels (default: 800)
  • DIALOG_BOX_MIN_WIDTH - Minimum dialog box width in pixels (default: 400)
  • DIALOG_BOX_HEIGHT_PERCENT - Dialog box height as fraction of window height (default: 0.25)
  • DIALOG_BOX_MIN_HEIGHT - Minimum dialog box height in pixels (default: 150)
  • DIALOG_VERTICAL_POSITION - Vertical position from bottom as fraction of window height (default: 0.25)
  • DIALOG_OVERLAY_ALPHA - Transparency of background overlay (0-255, default: 128)
  • DIALOG_BORDER_WIDTH - Width of dialog box border in pixels (default: 3)
  • DIALOG_PADDING_HORIZONTAL - Horizontal padding inside dialog box in pixels (default: 20)
  • DIALOG_PADDING_VERTICAL - Vertical padding inside dialog box in pixels (default: 20)
  • DIALOG_NPC_NAME_OFFSET - Vertical offset of NPC name from top of dialog box (default: 30)
  • DIALOG_FOOTER_OFFSET - Vertical offset of footer elements from bottom of dialog box (default: 20)

Font Settings

  • DIALOG_NPC_NAME_FONT_SIZE - Font size for NPC name text (default: 20)
  • DIALOG_TEXT_FONT_SIZE - Font size for dialog message text (default: 16)
  • DIALOG_INSTRUCTION_FONT_SIZE - Font size for instruction text (default: 12)
  • DIALOG_PAGE_INDICATOR_FONT_SIZE - Font size for page indicator text (default: 10)

Text Labels

  • DIALOG_TEXT_NEXT_PAGE - Instruction for advancing to next page (default: "Press SPACE for next page")
  • DIALOG_TEXT_CLOSE - Instruction for closing dialog (default: "Press SPACE to close")
  • DIALOG_TEXT_PAGE - Label for page indicator (default: "Page")

These can be overridden in your project's settings.py:

# Custom dialog settings
DIALOG_AUTO_CLOSE_DEFAULT = True
DIALOG_AUTO_CLOSE_DURATION = 1.0
DIALOG_CHAR_REVEAL_SPEED = 30
DIALOG_KEY_ADVANCE = "RETURN"
DIALOG_BOX_WIDTH_PERCENT = 0.8
DIALOG_TEXT_FONT_SIZE = 18

Public API

Dialog Display

show_dialog

show_dialog(npc_name: str, text: list[str], *, instant: bool = settings.DIALOG_INSTANT_TEXT_DEFAULT, auto_close: bool = settings.DIALOG_AUTO_CLOSE_DEFAULT, dialog_level: int | None = None, npc_key: str | None = None) -> None

Display a dialog from an NPC.

Parameters:

  • npc_name - Display name of the character speaking (shown at top of dialog box)
  • text - List of dialog text strings, one per page. Each string can contain multiple lines and will be wrapped automatically
  • instant - If True, text appears immediately without letter-by-letter reveal. Defaults to settings.DIALOG_INSTANT_TEXT_DEFAULT. Useful for narration, system messages, or cutscenes
  • auto_close - If True, dialog automatically closes after configured duration. If False, player must manually close. Defaults to settings.DIALOG_AUTO_CLOSE_DEFAULT
  • dialog_level - Optional dialog level for event tracking. Used when emitting DialogClosedEvent
  • npc_key - Optional NPC key name for event tracking. If provided, this is used in DialogClosedEvent instead of npc_name. Use this when the display name differs from the NPC's key name

Example:

# Basic dialog with manual advancement
dialog_plugin.show_dialog("Martin", [
    "Hello! I'm Martin, the village elder.",
    "Welcome to our humble town.",
    "Feel free to explore and talk to the other villagers!"
])

# Instant narration dialog
dialog_plugin.show_dialog(
    "Narrator",
    ["The world fades to black..."],
    instant=True
)

# Auto-closing cutscene dialog
dialog_plugin.show_dialog(
    "Plugin",
    ["Achievement unlocked!"],
    instant=True,
    auto_close=True
)

# Dialog with level tracking
dialog_plugin.show_dialog(
    "Merchant",
    ["Thanks for your help!"],
    dialog_level=1,
    npc_key="merchant"
)

Notes:

  • Each string in the text list becomes one page of dialog
  • Players advance through pages by pressing the configured DIALOG_KEY_ADVANCE key (default: SPACE)
  • Text reveals letter-by-letter unless instant=True or settings.DIALOG_INSTANT_TEXT_DEFAULT=True
  • Auto-close timer starts after text is fully revealed
  • Publishes DialogOpenedEvent when dialog is shown

close_dialog() -> None

Close the currently showing dialog.

Example:

# Force close on ESC key
if key == arcade.key.ESCAPE and dialog_plugin.is_showing():
    dialog_plugin.close_dialog()

Notes:

  • Dismisses the dialog overlay and clears all dialog state
  • Called automatically when the player advances past the last page
  • Does not publish DialogClosedEvent (that only happens via player interaction)

advance_page

advance_page() -> bool

Advance to the next page or close dialog if on last page.

Returns:

  • True if dialog was closed (was on last page)
  • False if text was revealed or advanced to next page

Example:

# In your input handler
if symbol == arcade.key.SPACE and dialog_plugin.is_showing():
    was_closed = dialog_plugin.advance_page()
    if was_closed:
        # Dialog finished, can trigger follow-up actions
        pass

Notes:

  • If text is still being revealed, it instantly completes the reveal animation
  • Otherwise, advances to the next page if there are more pages
  • Closes the dialog and returns True if on the last page
  • Called automatically by the DialogPlugin's on_key_press method

State Queries

is_showing

is_showing() -> bool

Check if dialog is currently displayed.

Returns:

  • True if a dialog is currently showing, False otherwise

Example:

if dialog_plugin.is_showing():
    # Don't allow player movement during dialog
    return

get_current_page

get_current_page() -> DialogPage | None

Get the currently displayed page.

Returns:

  • DialogPage object with npc_name, text, page_num, total_pages
  • None if no dialog is showing

Example:

page = dialog_plugin.get_current_page()
if page:
    print(f"{page.npc_name}: {page.text}")
    print(f"Page {page.page_num + 1}/{page.total_pages}")

Dialog State Management

set_current_dialog_level

set_current_dialog_level(dialog_level: int) -> None

Set the current dialog level for event tracking.

Parameters:

  • dialog_level - Dialog level to set

Notes:

  • Used internally for event emission
  • Typically set automatically when showing dialog

set_current_npc_name

set_current_npc_name(npc_name: str) -> None

Set the current NPC name for event tracking.

Parameters:

  • npc_name - NPC name to set

Notes:

  • Used internally for event emission
  • Typically set automatically when showing dialog

Text Reveal Control

speed_up_text

speed_up_text() -> None

Instantly reveal all text on the current page.

Example:

# Skip text reveal animation
if user_pressed_skip:
    dialog_plugin.speed_up_text()

Notes:

  • Called automatically when player presses SPACE while text is revealing
  • Useful for implementing skip functionality

Plugin Lifecycle

setup

setup(context: GameContext) -> None

Initialize the dialog plugin with game settings.

Parameters:

  • context - Game context for accessing the event bus

Notes:

  • Called automatically by the PluginLoader
  • Stores the game context for event publishing

cleanup

cleanup() -> None

Clean up dialog resources when the scene unloads.

Notes:

  • Closes any open dialog and clears text objects
  • Called automatically by the PluginLoader

update

update(delta_time: float) -> None

Update the dialog text reveal animation and auto-close timer.

Parameters:

  • delta_time - Time elapsed since last update, in seconds

Notes:

  • Called automatically every frame
  • Handles text reveal animation at rate controlled by DIALOG_CHAR_REVEAL_SPEED
  • Manages auto-close countdown when enabled

on_key_press

on_key_press(symbol: int, modifiers: int) -> bool

Handle input for dialog advancement.

Parameters:

  • symbol - Arcade key constant
  • modifiers - Modifier key bitfield

Returns:

  • True if dialog is showing and event was consumed
  • False if dialog is not showing

Notes:

  • Called automatically by the PluginLoader
  • Handles the configured DIALOG_KEY_ADVANCE key to advance pages or close dialog
  • Publishes DialogClosedEvent when dialog closes

on_draw_ui

on_draw_ui() -> None

Draw the dialog overlay in screen coordinates.

Notes:

  • Called automatically by the PluginLoader during UI draw phase
  • Renders the complete dialog UI on top of the game world
  • Uses lazy initialization for text objects

Dialog Configuration Files

Dialogs are typically loaded from JSON files in the assets/dialogs/ directory. Each file follows the pattern <scene>_dialogs.json (e.g., casa_dialogs.json).

JSON Structure

{
    "npc_name": {
        "0": {
            "name": "Display Name",
            "text": [
                "First page of dialog",
                "Second page of dialog"
            ]
        },
        "1": {
            "name": "Display Name",
            "text": ["Next dialog level"],
            "conditions": [
                {
                    "check": "inventory_accessed",
                    "equals": true
                }
            ],
            "on_condition_fail": [
                {
                    "type": "dialog",
                    "speaker": "Display Name",
                    "text": ["Alternative text if condition fails"]
                }
            ]
        }
    }
}

Fields:

  • name - Optional display name shown in the dialog box instead of the NPC's key name
  • text - Array of strings, one per page
  • conditions - Optional array of conditions that must be met to show this dialog
  • on_condition_fail - Optional array of actions to run if conditions fail

Example Dialog File

{
    "martin": {
        "0": {
            "name": "Martin",
            "text": [
                "Buenos días mi amor! Feliz cumpleaños!",
                "Te hice un café, me acompañas a tomarlo?"
            ]
        },
        "1": {
            "name": "Martin",
            "text": ["Qué hermoso día, no?"],
            "conditions": [
                {
                    "check": "inventory_accessed",
                    "equals": true
                }
            ]
        }
    },
    "merchant": {
        "0": {
            "text": [
                "Welcome to my shop!",
                "I have the finest wares in town."
            ]
        }
    }
}

Events

DialogOpenedEvent

Published when a dialog is shown to the player.

Attributes:

  • npc_name: str - Name of the NPC whose dialog was opened
  • dialog_level: int - Conversation level at the time dialog was shown

Script Trigger Example:

{
    "trigger": {
        "event": "dialog_opened",
        "npc": "martin",
        "dialog_level": 1
    },
    "actions": [
        {"type": "play_sfx", "sound": "dialog_open.wav"}
    ]
}

DialogClosedEvent

Published when a dialog is dismissed by the player.

Attributes:

  • npc_name: str - Name of the NPC whose dialog was closed
  • dialog_level: int - Conversation level at the time dialog was shown

Script Trigger Example:

{
    "trigger": {
        "event": "dialog_closed",
        "npc": "martin",
        "dialog_level": 0
    },
    "actions": [
        {"type": "set_dialog_level", "npc": "martin", "level": 1}
    ]
}

Notes:

  • Trigger filters (npc, dialog_level) are optional
  • Omit npc to trigger for any NPC
  • Omit dialog_level to trigger at any level

Actions

DialogAction

Show a dialog to the player.

Type: dialog

Parameters:

  • speaker: str - Name of the character speaking
  • text: list[str] - List of dialog pages to show
  • instant: bool - If True, text appears immediately without letter-by-letter reveal. Defaults to settings.DIALOG_INSTANT_TEXT_DEFAULT (optional)
  • auto_close: bool - If True, dialog automatically closes after configured duration. If False, player must manually close. Defaults to settings.DIALOG_AUTO_CLOSE_DEFAULT (optional)

Example:

{
    "type": "dialog",
    "speaker": "Martin",
    "text": ["Hello there!", "Welcome to the game."]
}
{
    "type": "dialog",
    "speaker": "Narrator",
    "text": ["The world fades to black..."],
    "instant": true,
    "auto_close": true
}

Notes:

  • Action completes immediately after queuing the dialog
  • Use WaitForDialogCloseAction to wait for player to dismiss the dialog

WaitForDialogCloseAction

Wait for dialog to be closed.

Type: wait_for_dialog_close

Parameters: None

Example:

[
    {"type": "dialog", "speaker": "Martin", "text": ["Hello!"]},
    {"type": "wait_for_dialog_close"},
    {"type": "dialog", "speaker": "Yema", "text": ["Hi there!"]}
]

Notes:

  • Pauses script execution until the player dismisses the currently showing dialog
  • Essential for creating proper dialog sequences where each message should be read before continuing

Custom Dialog Implementation

If you need to replace the dialog plugin with a custom implementation, you can extend the DialogBasePlugin abstract base class.

DialogBasePlugin

Location: src/pedre/plugins/dialog/base.py

The DialogBasePlugin class defines the minimum interface that any dialog plugin must implement.

Required Methods

Your custom dialog plugin must implement these abstract methods:

from pedre.conf import settings
from pedre.plugins.dialog.base import DialogBasePlugin

class CustomDialogPlugin(DialogBasePlugin):
    """Custom dialog implementation."""

    name = "dialog"
    dependencies = ["npc", "interaction"]

    def show_dialog(
        self,
        npc_name: str,
        text: list[str],
        *,
        instant: bool = settings.DIALOG_INSTANT_TEXT_DEFAULT,
        auto_close: bool = settings.DIALOG_AUTO_CLOSE_DEFAULT,
        dialog_level: int | None = None,
        npc_key: str | None = None,
    ) -> None:
        """Show a dialog from an NPC."""
        ...

    def set_current_dialog_level(self, dialog_level: int) -> None:
        """Set current dialog level."""
        ...

    def set_current_npc_name(self, npc_name: str) -> None:
        """Set current NPC name."""
        ...

    def is_showing(self) -> bool:
        """Verify if dialog is showing."""
        ...

Registration

Register your custom dialog plugin using the @PluginRegistry.register decorator:

from pedre.plugins.registry import PluginRegistry
from pedre.plugins.dialog.base import DialogBasePlugin

@PluginRegistry.register
class CustomDialogPlugin(DialogBasePlugin):
    name = "dialog"
    dependencies = ["npc", "interaction"]

    # ... implement all abstract methods ...

Notes on Custom Implementation

  • Your custom plugin inherits from BasePlugin (via DialogBasePlugin), so you must implement the standard plugin lifecycle methods: setup(), cleanup(), and on_key_press()
  • The role attribute is set to "dialog_plugin" in the base class
  • Your implementation can use any rendering backend, not just Arcade's text system
  • Register your custom dialog plugin in your project's INSTALLED_PLUGINS setting before the default "pedre.plugins.dialog" to replace it

Example Custom Implementation:

# In myproject/plugins/custom_dialog.py
from pedre.plugins.registry import PluginRegistry
from pedre.plugins.dialog.base import DialogBasePlugin

@PluginRegistry.register
class RichTextDialogPlugin(DialogBasePlugin):
    """Custom dialog plugin with rich text support."""

    name = "dialog"
    dependencies = ["npc", "interaction"]

    def __init__(self):
        self.showing = False
        self.rich_text_renderer = RichTextRenderer()
        # ... rest of initialization ...

    def show_dialog(
        self,
        npc_name: str,
        text: list[str],
        *,
        instant: bool = settings.DIALOG_INSTANT_TEXT_DEFAULT,
        auto_close: bool = settings.DIALOG_AUTO_CLOSE_DEFAULT,
        dialog_level: int | None = None,
        npc_key: str | None = None,
    ) -> None:
        # Custom rich text dialog display logic
        self.rich_text_renderer.render(npc_name, text)
        self.showing = True

    # ... implement other abstract methods ...
# In myproject/settings.py
INSTALLED_PLUGINS = [
    "myproject.plugins.custom_dialog",  # Load custom dialog first
    "pedre.plugins.camera",
    "pedre.plugins.audio",
    # ... rest of plugins (omit "pedre.plugins.dialog") ...
]

Usage Examples

Basic Dialog Interaction

# Show a simple greeting
dialog_plugin.show_dialog("Guard", [
    "Halt! Who goes there?",
    "State your business in our town."
])

Cutscene with Auto-Close

# Narration that auto-advances
dialog_plugin.show_dialog(
    "Narrator",
    [
        "A long time ago...",
        "In a land far away...",
        "A hero was born."
    ],
    instant=True,
    auto_close=True
)

Scripted Dialog Sequence

{
    "trigger": {
        "event": "npc_interacted",
        "npc": "martin"
    },
    "actions": [
        {
            "type": "dialog",
            "speaker": "Martin",
            "text": ["Hello!", "How are you today?"]
        },
        {
            "type": "wait_for_dialog_close"
        },
        {
            "type": "set_dialog_level",
            "npc": "martin",
            "level": 1
        }
    ]
}

Dialog with Event Tracking

# Show dialog with level tracking for scripts
dialog_plugin.show_dialog(
    "Elder",
    ["You have completed the first trial."],
    dialog_level=1,
    npc_key="elder"
)
# This will publish DialogOpenedEvent(npc_name="elder", dialog_level=1)
# And DialogClosedEvent(npc_name="elder", dialog_level=1) when dismissed

See Also