Skip to main content

Player Input

This page explains how player input works in Eldiron.

At a high level, player input is split into two concepts:

  • Actions: direct movement or turning commands such as forward, left, right, and backward
  • Intents: interaction modes such as use, attack, look, take, drop, or spell

Keyboard input is configured in character data via Input Mapping.
UI buttons on screens can also trigger the same actions and intents.

Actions

Actions are immediate movement-style commands.

Examples:

  • forward
  • left
  • right
  • backward
  • strafe_left
  • strafe_right

They are sent as runtime EntityAction values and are interpreted based on the current player camera mode:

  • 2D / Isometric: directional movement
  • 2D Grid: cardinal one-tile movement with smooth interpolation
  • First-Person: forward/backward movement plus left/right turning, with optional strafing via strafe_left / strafe_right
  • First-Person Grid: one-tile forward/backward/strafe movement with smooth interpolation, plus 90-degree left/right turning

If no intent is active, pressing an action key simply moves or turns the player.

The input mapping mode is controlled at runtime with set_player_camera. This affects how actions are interpreted, but it does not change the visual render camera by itself.

Intents

Intents describe what the player wants to do, not how they move.

Common intents:

  • use
  • attack
  • look
  • take
  • drop
  • spell

An intent can be selected by:

  • a keyboard mapping like intent(use)
  • a spell shortcut like spell(Fireball)
  • a screen button with an intent attribute

Once selected, the intent is stored on the player and used for the next interaction.

2D, Isometric, And First-Person Behavior

Intents behave differently in 2D and 3D.

2D

In 2D-style play, an intent is usually one-shot:

  1. select an intent like use or attack
  2. press a directional action like forward
  3. the engine looks in that direction and sends the matching intent event

If no valid target is found, the engine sends the localized fallback {system.cant_do_that}.

This applies to both:

  • 2d
  • 2d_grid

Isometric / First-Person

In isometric and first-person play, intents behave more like a persistent interaction mode:

  1. select an intent like use, attack, or spell
  2. move the cursor over an entity or item
  3. click the target to apply that intent

The active intent can also change the cursor if the corresponding button widget defines intent cursor tiles.

This applies to:

  • iso
  • firstp
  • firstp_grid

Camera Input Modes

The current player input mode can be:

  • 2d: freeform cardinal movement
  • 2d_grid: smooth grid-based cardinal movement, one tile / world unit per action
  • iso: same movement semantics as 2d, usually paired with an isometric render camera
  • iso_grid: alias of 2d_grid, usually paired with an isometric render camera
  • firstp: freeform first-person movement and turning
  • firstp_grid: smooth grid-based first-person movement, one tile / world unit per step and 90-degree turns

Intent Events

When an intent is triggered successfully, the engine sends an intent event.

That event is sent to:

  • the player character
  • the clicked target entity, if the target is a character
  • the clicked target item, if the target is an item

The event payload includes:

  • intent
  • entity_id
  • item_id
  • distance

This lets either side handle the interaction.

Examples:

  • the player handles attack and calls deal_damage(...)
  • an item handles use and toggles itself
  • a character handles talk and opens dialogue

Built-In Shortcuts

Some common intents have built-in convenience behavior before or alongside script handling.

Examples include:

  • look
  • use
  • take / pickup
  • drop
  • spell:<template>

Character and item attributes such as on_look, on_use, and on_drop can provide shortcuts for common cases.

Spells

Spell shortcuts are encoded as intent payloads of the form:

spell:Fireball

Keyboard mapping:

[input]
f = "spell(Fireball)"

Screen button mapping:

intent = "spell"
spell = "Fireball"

In both cases the runtime treats this as a spell intent and routes it through the normal intent system.

Where To Configure What