Search docs
Search modules and symbols
Modules

Docs / API / Modules / ui

HUD

Game CS2

@s2script/cs2

Custom Panorama HUD: ui.components() (modals, badges, toasts) and the ui.hud() primitive.

Import

import { HudResult } from "@s2script/cs2";

Author-time types ship in the npm package; the engine injects the runtime at plugin load. Add @s2script/sdk to your plugin's dependencies.

API reference

Generated from the shipped type definitions.

type
HudResult

Result of a drive call: null on success, or a human-readable reason it did not happen.

interface
LayoutSlot

One pre-declared row/slot in a pooled collection.

readonly id: string
readonly vars: readonly string[]
interface
LayoutDescriptor

What a layout offers — the contract between Panorama markup and server-side drive calls.

readonly addons: readonly string[]
Decimal workshop addon ids clients must mount (via MultiAddonManager).
readonly resource: string
Source .xml path under panorama/layout/custom_game/.
readonly hideClass: string
Class that hides a panel when applied.
readonly text: Readonly<Record<string, string>>
panelId -> dialog variable name for Hud.setText.
readonly buttons: readonly string[]
Button ids delivered by Hud.onClick / CtxUi.onCustomHudClicked.
readonly meters: Readonly<Record<string, string>>
Meter name -> fill panel id (width driven via s2-w0..s2-w10 classes).
readonly slots?: Readonly<Record<string, readonly LayoutSlot[]>>
Named pools of fixed slots (e.g. list rows). Each slot carries its own var list.
const
DEFAULT_HUD_DESCRIPTOR

Default descriptor for the shipped s2script_hud.xml in workshop addon 3790153369. **This targets a PROBE, not a HUD.** s2script_hud.xml carries literal text and has no dialog variable bindings at all, so a panel driven through this descriptor permanently reads "S2SCRIPT PROBE OK" and no call can change it. That is deliberate: literal text is what let us prove the render pipeline end to end when nothing else could be trusted, and standalone-renders and driveable-by-a-plugin cannot both be true of one layout. Use it to answer "is my addon mounted and rendering at all?" — and nothing else. For real UI, use CtxUi.components, which drives the generic pool in s2script_lib.xml and hands out panels through a claim so two plugins cannot collide on the same one.

interface
OnCustomHudClickedView

Block-scoped view of one custom HUD click. Valid only during the handler.

readonly player: EntityRef | null
The clicking controller, books-gated. Null when unresolved.
readonly buttonId: string
Globally scoped button id from the layout markup.
interface
Hud

Typed custom HUD bound to one layout descriptor and its owned entity.

readonly layout: LayoutDescriptor
show(slot: number, panelId: string, opts?: { cursor?: boolean }): HudResult
hide(slot: number, panelId: string): HudResult
cursor(slot: number, on: boolean): HudResult
set(slot: number, id: string, value: string | number): HudResult
Set text where panel id equals the dialog variable name.
setText(slot: number, panelId: string, value: string): HudResult
Set text using the descriptor's explicit text map.
setClass(slot: number, panelId: string, className: string, on: boolean): HudResult
setMeter(slot: number, meterName: string, percent: number): HudResult
Set a meter 0..100 (quantized to 10% CSS steps s2-w0..s2-w10).
capacity(poolName: string): number
setPool(slot: number, poolName: string, entries: readonly (readonly string[])[]): HudResult
onClick(buttonId: string, handler: (slot: number) => void): void
setDisabled(slot: number, buttonId: string, disabled: boolean): HudResult
forget(slot: number): void
interface
CtxUi
components(descriptor?: LayoutDescriptor): Components
The component library — pooled generic panels driven with data, not ids. Prefer this over CtxUi.hud unless you ship your own workshop layout.
createLayout(descriptor?: LayoutDescriptor): HudResult
Spawn the layout entity for descriptor. Returns null on success, or a reason. Call from player-join (ctx.clients.onActive), a game event, a command, or any other callback after a client is active. hud() / CtxUi.components also spawn at that point, so this is only needed to force a spawn before the first of those calls. OnMapStart is still too early — wait for an active client. Idempotent.
hud(descriptor?: LayoutDescriptor): Hud
Default shipped descriptor, or pass a custom LayoutDescriptor.
onCustomHudClicked(handler: (view: OnCustomHudClickedView) => HookResultValue | void): void
Raw click observer — player + globally scoped button id only. Always observes; cannot suppress the engine/map handler. Prefer Hud.onClick for typed routing.
const
ui

Load-window custom HUD API. Same object as the former ctx.ui. Throws after settle.

type
Variant

Toast / footer-button colouring. ghost is the low-emphasis default for footers.

interface
Row

One list row. Three columns: a is primary and flexes, b and c are right-aligned.

readonly a: string
readonly b?: string
readonly c?: string
readonly disabled?: boolean
Greys the row. Cosmetic only — onPick still fires, so you can say WHY it is unavailable.
interface
FooterButton
readonly text: string
readonly variant?: Variant
readonly onClick: (slot: number) => void
interface
ModalSpec
readonly title: string | ((slot: number) => string)
readonly subtitle?: string | ((slot: number) => string)
Defaults to a page indicator when the list pages.
readonly rows: readonly Row[] | ((slot: number) => readonly Row[])
Full list; the library pages it. Called per repaint, so it may read live state.
readonly onPick?: (slot: number, index: number, row: Row) => void
readonly detail?: (slot: number, row: Row | undefined, cursor: number) => readonly string[]
Up to 4 detail lines for the selected row. The LAST line renders in a clamped, fixed-height box — put attacker-controlled text there, and escape it before it reaches this call.
readonly buttons?: readonly FooterButton[]
Up to 5; Prev/Next claim the trailing two automatically when the list pages.
readonly pageSize?: number
readonly width?: "sm" | "md" | "lg" | "xl"
Sheet width. Default md (560px).
interface
BadgeSpec
readonly corner?: "tl" | "tr" | "bl" | "br"
readonly title?: string
readonly accent?: "accent" | "good" | "warn" | "bad"
interface
Badge

A persistent corner element — the thing chat cannot be, because chat scrolls away.

show(slot: number, data?: { title?: string; text?: string }): void
hide(slot: number): void
release(): void
interface
ToastSpec
readonly title?: string
readonly message?: string
readonly variant?: Variant
readonly holdSeconds?: number
0 keeps it up until something replaces it. Default 6.
interface
Components
readonly descriptor: LayoutDescriptor
ensure(): HudResult
Spawn the pool's layout entity. Same timing as CtxUi.createLayout. components() also spawns once a client is active.
readonly hud: Hud
The underlying primitive, for anything the library does not cover.
modal(spec: ModalSpec): Modal | null
Claim a pooled modal. Null when all are in use.
badge(spec?: BadgeSpec): Badge | null
Claim a pooled corner badge. Null when all are in use.
toast(slot: number, spec: ToastSpec): HudResult
hideAll(slot: number): void
Hide every pooled panel for one player.
forget(slot: number): void
budget(): {
    panelIds: number;
    classNames: number;
    variables: number;
    declared: number;
    warnAt: number;
    cap: number;
  }
Names interned so far, per engine vector. Each has its OWN cap of 1024 (not one shared 3072), and all are shared by every plugin on the HUD entity — past the cap a name is refused and its value simply never arrives. set spends from two vectors at once, charging its panel id and its dialog variable name to different ledgers. Interning is idempotent, so these climb only on a name's FIRST use; repainting is free.
Back to modules All packages

s2script — Source 2 plugin framework

GitHub