Interactive Characters

Turn any NPC into an interactive character, they talk, move, gives items, run commands, remember each player, and react.

Interactive Characters

Turn any NPC into an interactive character, they talk, move, gives items, run commands, remember each player, and react. You build all of it in game by clicking, with no coding.

Interactive Characters is a standalone admin toolkit. Set its identity, attach triggers, and build a graph of nodes that runs when a player interacts with it.

Highlights

  • Turn any NPC into an interactive character, entirely in game.
  • Conversations with branching, clickable choices.
  • Per-player memory through scoped variables.
  • Triggers for use, proximity, and a repeating loop.
  • Make NPCs walk to a spot, wander, patrol, or follow a player.
  • 17 built-in node types, from items and commands to math and animation.
  • A built-in guide (/ic guide) with live code samples.
  • Java API so other developers can add their own node types and triggers.

How it works

  1. Get the editor tool with /ic tool.
  2. Right-click any NPC. It is now an Interactive Character.
  3. On the Identity tab, set its name, model, scale, and movement mode.
  4. On the Interactions tab, add a trigger.
  5. Build the trigger's node graph: add nodes and wire each node's "continue to".
  6. Save, then test it in world.

Triggers

Every interaction starts with a trigger:

  • On Use (F): fires when a player presses F on the NPC.
  • On Proximity: fires when a player comes within range. You set the radius and cooldown.
  • Loop: fires every few seconds while a player is nearby. Entry rules (distance, line of sight, variables) decide what it does each tick: chase, patrol, react.

Nodes

A trigger runs a graph of nodes. Each node does one thing, then continues to the next. The built-in types:

  • Dialogue: show a dialogue box with a speaker, text, and clickable choices that branch the conversation.
  • Give item / Remove item: add or remove items from the player's inventory.
  • Command: run a command, as the player or as the server.
  • Branch (if): check a condition, then continue one of two ways.
  • Variable: set, add to, subtract from, or clear a scoped variable.
  • Math: compute A op B (add, subtract, multiply, divide, modulo, min, max, power, random) and store the result.
  • Animation: play or stop an animation on the NPC, for everyone or just the interacting player.
  • Sound: play a sound at the NPC, for everyone nearby or only the interactor.
  • Wait: pause the graph, then continue after a delay.
  • Held item: set which hotbar slot the NPC uses.
  • Combo: fire several nodes at once, then continue.
  • Run function: run a saved, named node tree inline.
  • Component: add, set, or remove an ECS component on the NPC.
  • Navigate: make the NPC walk to a target, whether forward or to a position, player, or trigger volume.
  • Stop: interrupt the NPC's movement or its running loops.
  • Set role: switch the NPC's role or movement mode at runtime.

Variables and memory

Variables let an NPC remember things. Each variable lives in a scope:

  • player: bound to the interacting player (per-player memory).
  • character: bound to this NPC.
  • global: shared across the whole world.
  • temp: scratch space for the current run only, never saved.

Most text fields expand placeholders: %player% is the player's name, and %player:gold%, %character:mood%, or %global:event% insert a scoped variable's value.

Example: a villager who greets each player once

On Use (F)
  -> Branch: is player:greeted set?
       if not set:
         -> Dialogue "Welcome, traveler! Here, take this."
         -> Give item: Coin x10
         -> Variable: set player:greeted = 1
         -> Dialogue "Spend it well."
       if set:
         -> Dialogue "Back again? Nothing more for you today."

Because player:greeted is a per-player variable, the NPC remembers everyone individually. First timers get the gift, returning players get the brush off. You build the whole thing by clicking nodes, no code.

Commands

Every command lives under /ic and is gated by a permission node. Grant interactivecharacters.* to staff for all of them, or grant the nodes individually.

  • /ic tool (interactivecharacters.tool): get the editor tool, then right-click an NPC to edit it.
  • /ic debugtool (interactivecharacters.debug): get the debug tool, then right-click an NPC to toggle interaction-radius overlays. Useful for finding npc-specific issues, or navigation problems.
  • /ic guide (interactivecharacters.guide): open the in-game guide.
  • /ic flag (interactivecharacters.flag): set or clear a variable on a scope.
  • /ic reload (interactivecharacters.reload): reload interaction profiles and dialogue trees from disk.
  • /ic uireload (interactivecharacters.reload): reload the editable dialogue UI and push it live.

In-game guide

Type /ic guide for a full walkthrough. It covers Overview, Commands, Triggers, Nodes, Assets, Variables, Movement, Appearance, and the Developer API, each with live code samples you can show or hide.

Customization

Tweak DialoguePage.ui in the plugin's data folder, then push your changes live to connected players with /ic uireload.

For developers

Interactive Characters exposes a Java API so other developers can add their own node types, fire triggers, and read or write variables. You write the same shapes the plugin uses internally. Depend on the plugin, then call these from your own setup().

Worked example: an arena NPC that rewards kills. Your plugin contributes a Pay node and an On Kill trigger; the admin composes them in game (On Kill -> Pay 10 -> Dialogue "Nice kill!") with no glue code.

A custom node is one class that implements NodeModule, the same interface the built-in nodes use:

public final class PayModule implements NodeModule {
    public String type()        { return "pay"; }
    public String label()       { return "Pay player"; }
    public String color()       { return "#F0C040"; }
    public String icon()        { return "Cloth_Block_Wool_Yellow"; }
    public String description() { return "Deposit coins into the player's balance."; }

    public List<ModuleField> fields() {
        return List.of(ModuleField.text("amount", "Amount", "10"));
    }
    public String run(NodeContext ctx, NodeView node) {
        MyEconomy.deposit(ctx.playerId(), node.i("amount", 10));  // your code
        return node.next();
    }
}

A custom trigger implements TriggerModule, and your plugin fires it from its own events:

public final class OnKillTrigger implements TriggerModule {
    public String type()        { return "on_kill"; }
    public String label()       { return "On Kill"; }
    public String color()       { return "#D9534F"; }
    public String icon()        { return "Cloth_Block_Wool_Red"; }
    public String description() { return "Runs when the player gets a kill near this NPC."; }
}

Register both in setup(), then fire the trigger from your own logic:

ModuleRegistry.register(new PayModule());
TriggerRegistry.register(new OnKillTrigger());

InteractiveCharactersPlugin.getInstance()
    .fireTriggers(store, npcRef, "on_kill", killer);

IcVariables reads and writes the persisted scopes (player, character, global) from your own commands, events, or schedulers, with no interaction running. It is the same storage the NPC graphs use:

IcVariables.setPlayer(playerUuid, "gold", "100");
IcVariables.setGlobal("event", "halloween");

Built-in node and trigger type ids are reserved, so pick a unique id for your own.

Notes

This is the first public release. Feedback and ideas are welcome.

The Interactive Characters Team

profile avatar
  • 7
    Followers
  • 2
    Projects
  • 3.8K
    Downloads

More from callmeehko

  • Hylograms project image

    Hylograms

    • 3.7K
    • Mods

    Create floating text for your servers with easy-to-use commands.

    • 3.7K
    • February 19, 2026
    • Mods
    • +3
  • Hylograms project image

    Hylograms

    • 3.7K
    • Mods

    Create floating text for your servers with easy-to-use commands.

    • 3.7K
    • February 19, 2026
    • Mods
    • +3