Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/HarbourMasters/Starship/llms.txt

Use this file to discover all available pages before exploring further.

Engine events cover the core game loop and all built-in HUD draw calls. They are defined in port/hooks/list/EngineEvent.h and are the most commonly used hooks for frame-level mod logic and UI replacement.

Game Loop Events

These events fire at well-defined points in the engine’s main update cycle. None carry extra fields beyond the base IEvent.
EventWhen it firesCancellable
DisplayPreUpdateEventBefore the display update beginsYes
DisplayPostUpdateEventAfter the display update completesNo
GamePreUpdateEventBefore game logic runs for the frameYes
GamePostUpdateEventAfter game logic runs for the frameNo
PlayUpdateEventDuring the play-state update tickYes
PlayUpdateEvent is cancellable and is used internally by the debug-pause feature. If your listener sets cancelled = true, the engine skips the remainder of the play-state update for that tick — effectively freezing gameplay.

Example — per-frame logic in DisplayPostUpdateEvent

mymod.c
#include "port/hooks/list/EngineEvent.h"

void OnDisplayUpdatePost(IEvent* event) {
    // Runs every frame after the display update
    if (CVarGetInteger("gMyModEnabled", 0) == 0) {
        return;
    }
    MyMod_DoFrameWork();
}

void MyMod_Register() {
    REGISTER_LISTENER(DisplayPostUpdateEvent, OnDisplayUpdatePost, EVENT_PRIORITY_NORMAL);
}

Example — pausing gameplay with PlayUpdateEvent

pause_hook.c
#include "port/hooks/list/EngineEvent.h"

void OnPlayUpdate(IEvent* event) {
    if (CVarGetInteger("gMyModFreeze", 0)) {
        event->cancelled = true; // freeze the play state
    }
}

void MyMod_Register() {
    REGISTER_LISTENER(PlayUpdateEvent, OnPlayUpdate, EVENT_PRIORITY_HIGH);
}

Player Update Events

Player update events fire around the per-player update tick and carry a pointer to the Player struct being updated.
player
Player*
required
Pointer to the Player struct for the player being updated this tick.
EventWhen it firesCancellable
PlayerPreUpdateEventBefore a player’s update runsYes
PlayerPostUpdateEventAfter a player’s update completesNo

Example — PlayerPostUpdateEvent

infinite_boost.c
#include "port/hooks/list/EngineEvent.h"

void OnPlayerUpdatePost(IEvent* evt) {
    PlayerPostUpdateEvent* event = (PlayerPostUpdateEvent*)evt;

    if (CVarGetInteger("gInfiniteBoost", 0) == 1) {
        if (event->player->boostSpeed < 0.0f) {
            event->player->boostSpeed += 0.5f;
            if (event->player->boostSpeed > 0.0f) {
                event->player->boostSpeed = 0.0f;
            }
        }
    }
}

void MyMod_Register() {
    REGISTER_LISTENER(PlayerPostUpdateEvent, OnPlayerUpdatePost, EVENT_PRIORITY_NORMAL);
}

HUD Draw Events

HUD draw events fire immediately before the engine renders each HUD element. Cancelling a HUD event suppresses the default rendering so your listener can draw a replacement.

Quick Reference

EventElement drawnExtra fieldsCancellable
DrawRadarHUDEventRadar backgroundYes
DrawRadarMarkArwingEventArwing blip on radars32 colorIdxYes
DrawRadarMarkWolfenEventWolfen blip on radarYes
DrawBoostGaugeHUDEventBoost/brake gaugeYes
DrawBombCounterHUDEventBomb count displayYes
DrawIncomingMsgHUDEvent”Incoming” messageYes
PreSetupRadioMsgEventRadio message setups32* radioRedBoxNo
DrawGoldRingsHUDEventGold ring counterYes
DrawLivesCounterHUDEventLives counterYes
DrawTrainingRingPassCountHUDEventTraining ring countYes
DrawEdgeArrowsHUDEventEdge warning arrowsYes
DrawBossHealthHUDEventBoss health barYes
DrawGlobalHUDPreEventBefore all HUD is drawnYes
DrawGlobalHUDPostEventAfter all HUD is drawnNo

Field Details

DrawRadarMarkArwingEvent

colorIdx
s32
required
Index into the engine’s arwing colour palette array. Modify this value inside a non-cancelling listener to tint the radar blip, or cancel the event and draw your own.

PreSetupRadioMsgEvent

radioRedBox
s32*
required
Pointer to the boolean flag that controls whether the radio message box renders with a red (enemy) border. Write *ev->radioRedBox = true to force enemy styling.
PreSetupRadioMsgEvent uses CALL_EVENT in the engine (not CALL_CANCELLABLE_EVENT), so setting cancelled = true has no effect on engine flow. Use the radioRedBox pointer to influence rendering.

Code Examples

Replace the boost gauge

custom_boost_gauge.c
#include "port/hooks/list/EngineEvent.h"

void OnBoostGaugeDraw(IEvent* event) {
    if (CVarGetInteger("gMyCustomGauge", 0) == 0) {
        return;
    }

    // Suppress default rendering
    event->cancelled = true;

    // Draw custom gauge
    RCP_SetupDL(&gMasterDisp, SETUPDL_76_OPTIONAL);
    My_DrawBoostGauge(gPlayer[0].boostMeter);
}

void MyMod_Register() {
    REGISTER_LISTENER(DrawBoostGaugeHUDEvent, OnBoostGaugeDraw, EVENT_PRIORITY_HIGH);
}

Colour-code arwing radar blips

radar_colors.c
#include "port/hooks/list/EngineEvent.h"

void OnArwingRadarMark(IEvent* evt) {
    DrawRadarMarkArwingEvent* event = (DrawRadarMarkArwingEvent*)evt;

    // Force all arwing blips to use colour index 2 (blue)
    event->colorIdx = 2;
    // Do NOT cancel — let the engine draw with the modified index
}

void MyMod_Register() {
    REGISTER_LISTENER(DrawRadarMarkArwingEvent, OnArwingRadarMark, EVENT_PRIORITY_NORMAL);
}

Force enemy radio styling

enemy_radio.c
#include "port/hooks/list/EngineEvent.h"

void OnPreSetupRadioMsg(IEvent* evt) {
    PreSetupRadioMsgEvent* event = (PreSetupRadioMsgEvent*)evt;

    // Always use the red enemy box
    *event->radioRedBox = true;
}

void MyMod_Register() {
    REGISTER_LISTENER(PreSetupRadioMsgEvent, OnPreSetupRadioMsg, EVENT_PRIORITY_NORMAL);
}

Overlay extra HUD elements

hud_overlay.c
#include "port/hooks/list/EngineEvent.h"

void OnGlobalHUDPost(IEvent* event) {
    // DrawGlobalHUDPostEvent fires after everything else is drawn —
    // safe to add overlays here without cancelling existing HUD
    if (CVarGetInteger("gShowSpeedometer", 0)) {
        My_DrawSpeedometer(gPlayer[0].baseSpeed);
    }
}

void MyMod_Register() {
    REGISTER_LISTENER(DrawGlobalHUDPostEvent, OnGlobalHUDPost, EVENT_PRIORITY_NORMAL);
}
Use DrawGlobalHUDPostEvent to add supplemental HUD overlays. Use individual element events (e.g. DrawBoostGaugeHUDEvent) when you need to replace a specific element. The post-event approach avoids unintended interactions with other mods that target specific elements.

Build docs developers (and LLMs) love