Razorbill
Scripting API

Events

The event system lets scripts communicate without direct references. Scripts can emit named events with optional payloads, and other scripts can subscribe to receive them.

Functions

subscribe_event

Register a callback for a named event.

uint64_t subscribe_event(ScriptContext* ctx,
                         const char* event_name,
                         void (*callback)(void* user_data,
                                          uint64_t entity_high,
                                          uint64_t entity_low,
                                          const char* payload),
                         void* user_data);
ParameterTypeDescription
event_nameconst char*Event name to listen for (e.g., "player_death", "item_collected")
callbackfunction pointerFunction invoked when event fires
user_datavoid*Opaque pointer passed to callback (can be nullptr)

Returns a subscription handle (0 = failed). Use this handle to unsubscribe later.

emit_event

Broadcast an event to all subscribers.

void emit_event(ScriptContext* ctx,
                const char* event_name,
                uint64_t entity_high,
                uint64_t entity_low,
                const char* json_payload);
ParameterTypeDescription
event_nameconst char*Event name
entity_highuint64_tHigh 64 bits of source EntityHandle (or 0 for broadcast)
entity_lowuint64_tLow 64 bits of source EntityHandle (or 0 for broadcast)
json_payloadconst char*JSON-encoded payload string (can be nullptr, treated as "{}")

unsubscribe_event

Remove a subscription.

bool unsubscribe_event(ScriptContext* ctx,
                       const char* event_name,
                       uint64_t handle);

Returns true if the subscription was found and removed.


Example: Damage System

DamageDealer.cpp — emits damage events:

void OnUpdate(ScriptContext* ctx) {
    if (ctx->is_key_pressed(ctx, 70)) { // F key
        ctx->emit_event(ctx, "deal_damage", 0, 0,
            "{\"amount\": 25, \"type\": \"fire\"}");
    }
}

HealthSystem.cpp — subscribes and reacts:

static float health = 100.0f;
static uint64_t sub_handle = 0;

void on_damage(void* user_data, uint64_t eh, uint64_t el,
               const char* payload) {
    // payload = "{\"amount\": 25, \"type\": \"fire\"}"
    health -= 25.0f; // In production, parse the JSON payload
    if (health <= 0) {
        // Handle death
    }
}

void OnStart(ScriptContext* ctx) {
    sub_handle = ctx->subscribe_event(ctx, "deal_damage",
        on_damage, nullptr);
}

void OnDestroy(ScriptContext* ctx) {
    if (sub_handle) {
        ctx->unsubscribe_event(ctx, "deal_damage", sub_handle);
    }
}

Example: Game State Events

// Emit when player collects a coin
ctx->emit_event(ctx, "coin_collected", 0, 0,
    "{\"value\": 10}");

// Emit when level completes
ctx->emit_event(ctx, "level_complete", 0, 0,
    "{\"level\": 3, \"time\": 45.2}");

// Emit entity-specific event
// Pass entity handle split into high/low 64-bit parts
ctx->emit_event(ctx, "entity_hit", entity_high, entity_low,
    "{\"damage\": 50}");

On this page