api.events
Events you can listen for
| Event | When it happens |
|---|---|
aura-added |
An aura is added to or refreshed on a player or monster. |
aura-removed |
An aura is removed from a player or monster. |
counter-attack-end |
A monster’s counter attack ends. |
counter-attack-start |
A monster’s counter attack starts. |
item-drop |
An item drops. |
join-map |
A map finishes loading. |
login |
A game session starts. |
logout |
A game session ends. |
monster-death |
A monster dies. |
monster-respawn |
A monster respawns. |
player-afk |
A player goes AFK or comes back. |
player-death |
A player dies. |
player-location |
A player’s location changes. |
players-changed |
A player joins or leaves the current map. |
quest-complete |
A quest turn-in succeeds. |
update-message |
A yellow combat message appears. |
zone |
The current map’s encounter zone changes. |
Event details
Each event includes the information shown below.
aura-added
An aura is added to or refreshed on a player or monster.
{
readonly type: "aura-added";
/** The aura duration in seconds, when available. */
readonly duration?: number;
readonly icon?: string;
readonly name: string;
/** The applying entity's map-scoped ID, when known. */
readonly sourceId?: number;
readonly sourceType?: "monster" | "player";
/** The affected entity's map-scoped ID. */
readonly targetId: number;
readonly targetType: "monster" | "player";
}
aura-removed
An aura is removed from a player or monster.
{
readonly type: "aura-removed";
/** The aura duration in seconds, when available. */
readonly duration?: number;
readonly icon?: string;
readonly name: string;
/** The applying entity's map-scoped ID, when known. */
readonly sourceId?: number;
readonly sourceType?: "monster" | "player";
/** The affected entity's map-scoped ID. */
readonly targetId: number;
readonly targetType: "monster" | "player";
}
counter-attack-end
A monster’s counter attack ends.
{
readonly type: "counter-attack-end";
/** The monster's map-scoped ID. */
readonly monsterMapId: number;
/** Where the trigger was detected. */
readonly source: "aura" | "message";
/** A stable identifier for the recognized trigger. */
readonly triggerId: string;
/** The aura name or combat message that matched the trigger. */
readonly triggerText: string;
}
counter-attack-start
A monster’s counter attack starts.
{
readonly type: "counter-attack-start";
/** The expected window duration in milliseconds, when known. */
readonly durationMs?: number;
/** The monster's map-scoped ID. */
readonly monsterMapId: number;
/** Where the trigger was detected. */
readonly source: "aura" | "message";
/** A stable identifier for the recognized trigger. */
readonly triggerId: string;
/** The aura name or combat message that matched the trigger. */
readonly triggerText: string;
}
item-drop
An item drops.
{
readonly type: "item-drop";
readonly item: ItemSnapshot;
}
join-map
A map finishes loading.
{
readonly type: "join-map";
readonly map: { readonly id: number; readonly name: string; readonly roomNumber: number; };
}
login
A game session starts.
{
readonly type: "login";
}
logout
A game session ends.
{
readonly type: "logout";
}
monster-death
A monster dies.
{
readonly type: "monster-death";
readonly monsterMapId: number;
}
monster-respawn
A monster respawns.
{
readonly type: "monster-respawn";
readonly monsterMapId: number;
}
player-afk
A player goes AFK or comes back.
{
readonly type: "player-afk";
readonly afk: boolean;
readonly entityId: number;
readonly username: string;
}
player-death
A player dies.
{
readonly type: "player-death";
readonly entityId: number;
readonly username: string;
}
player-location
A player’s location changes.
{
readonly type: "player-location";
readonly cell: string;
readonly entityId: number;
readonly pad: string;
/** The latest known coordinates for the player. */
readonly position: { readonly x: number; readonly y: number; };
readonly username: string;
/** The destination reported by a complete walk update. */
readonly destination: { readonly x: number; readonly y: number; };
readonly kind: "walk";
} | {
readonly type: "player-location";
readonly cell: string;
readonly entityId: number;
readonly pad: string;
/** The latest known coordinates for the player. */
readonly position: { readonly x: number; readonly y: number; };
readonly username: string;
/** `position` reports coordinates; `cell` reports only cell/pad. */
readonly kind: "cell" | "position";
}
players-changed
A player joins or leaves the current map.
{
readonly type: "players-changed";
}
quest-complete
A quest turn-in succeeds.
{
readonly type: "quest-complete";
readonly questId: number;
}
update-message
A yellow combat message appears.
{
readonly type: "update-message";
/** The animation's `animStr`, when present. */
readonly animation?: string;
readonly message: string;
/** The related monster's map-scoped ID, when the message names one. */
readonly monsterMapId?: number;
readonly source: "animation" | "aura";
}
zone
The current map’s encounter zone changes.
{
readonly type: "zone";
readonly map: string;
readonly zone: string;
}
Members
api.events.on()
Runs a handler for every matching event. The handler must return an Effect or generator; plain values and Promises are not supported.
Call the returned function to stop listening early. The subscription is also removed automatically when the script stops.
api.events.on<const T extends ScriptEventType>(query: ScriptEventSelectorForType<T>, handler: (event: ScriptEventForType<T>) => ScriptCallbackResult): Effect.Effect<() => void, never, never>
api.events.on(query: undefined, handler: (event: ScriptEvent) => ScriptCallbackResult): Effect.Effect<() => void, never, never>
api.events.on(query: ProjectionEventSelector | undefined, handler: (event: ScriptEvent) => ScriptCallbackResult): Effect.Effect<() => void, never, never>
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
query |
ProjectionEventSelector | undefined |
|||
handler |
(event: ScriptEvent) => ScriptCallbackResult |
Returns: () => void
Errors: never
Example
const script = require("lucent/script");
const unsubscribe = yield* api.events.on(
{ type: "monster-death" },
function* (event) {
yield* script.log(`Monster ${event.monsterMapId} died.`);
},
);
yield* script.sleep("30 seconds");
unsubscribe();
api.events.once()
Waits for the next matching event. With a trigger, starts listening before
running that action so an immediate event is not missed.
Returns null if the trigger returns false or the wait times out. The
timeout starts after the trigger finishes; omitting it waits indefinitely.
Timing out stops the wait but does not undo the action started by the trigger.
api.events.once<const T extends ScriptEventType, E = never, R = never>(query: ScriptEventSelectorForType<T>, options?: TriggeredWaitOptions<E, R> | undefined): Effect.Effect<ScriptEventForType<T> | null, E, Exclude<R, Scope.Scope>>
api.events.once<E = never, R = never>(selector?: ProjectionEventSelector | undefined, options?: TriggeredWaitOptions<E, R> | undefined): Effect.Effect<ProjectionEvent | null, E, Exclude<R, Scope.Scope>>
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
selector |
ProjectionEventSelector | undefined |
|||
options |
TriggeredWaitOptions<E, R> | undefined |
Returns: ScriptEvent | null
Errors: E
Example
const script = require("lucent/script");
const [monster] = yield* api.monsters.getAvailable();
if (monster !== undefined) {
const death = yield* api.events.once(
{ type: "monster-death", monsterMapId: monster.monsterMapId },
{
trigger: api.combat.attack(monster.monsterMapId),
timeout: "30 seconds",
},
);
yield* api.combat.cancelAutoAttack();
if (death === null) {
yield* script.log("Attack failed or the monster did not die in time.");
}
}