Generated from the shipped type definitions.
A CS2 player pawn (the in-world body): the generated CCSPlayerPawn schema fields + the liveness-gated ref.
controller is the typed reverse hop (shadows the raw generated m_hController handle).
Nav props (sceneNode, weaponServices, movementServices, aimPunchServices) are generated from nav-targets.json.
— The backing entity ref (the pawn's liveness-gated identity; escape hatch to the raw EntityRef surface). readonly isValid: boolean
— SourceMod/CSSharp-sense validity: the pawn is live (liveness-gated) AND fully spawned (out of the
engine EF_IN_STAGING_LIST). Prefer this over ref.isValid() for any pawn WRITE — a staged-but-live
pawn passes ref.isValid() yet segfaults on SetModel/SetParent. Falls back to liveness if the
staging-flag read is unavailable.readonly controller: Player | null
— The player controlling this pawn, or null if stale/absent.readonly origin: Vector | null
— World-space position (via the CGameSceneNode pointer chain), or null if stale.readonly angles: QAngle | null
— Body world rotation (via the CGameSceneNode pointer chain); distinct from the view/aim eyeAngles.readonly sceneNode: SceneNode | null
— The pawn's scene node (world transform) — absOrigin/absRotation/scale/…, via the CBodyComponent→CGameSceneNode chain.readonly weaponServices: WeaponServices | null
— The pawn's weapon services (active weapon, …).readonly movementServices: MovementServices | null
— The pawn's movement services (duck/ladder/…).readonly aimPunchServices: AimPunchServices | null
— The pawn's aim-punch services (recoil angles).setVelocity(x: number, y: number, z: number): boolean
— Best-effort velocity write (m_vecAbsVelocity); returns false if stale/unresolved. — The pawn's MoveType_t (uint8; null on a stale ref). Setting writes both m_MoveType and
m_nActualMoveType + notifies. Values (MoveType_t): NONE=0, WALK=2, NOCLIP=7. — The currently-pressed button mask (low 32 bits; IN_USE/E = 32). 0 if the mask is unreadable. — Kill this pawn via the sig-resolved CommitSuicide engine op (liveness-gated; no-op if stale). giveNamedItem(name: string): Weapon | null
— Give this pawn a named item/weapon (e.g. CsItem.AK47 or a raw "weapon_*" string). Returns the created
Weapon, or null if unresolved/failed/stale.readonly activeWeapon: Weapon | null
— The currently-deployed weapon (m_hActiveWeapon), or null if none/stale.readonly weapons: Weapon[]
— This pawn's held weapons (m_hMyWeapons, a CUtlVector<CHandle>). Empty if stale/unresolved/none.removeWeapon(weapon: Weapon): boolean
— Remove ONE weapon (unequip via RemovePlayerItem + destroy via UTIL_Remove). false if absent/stale. — Remove ALL held weapons (folds over Weapon.remove). true iff every one removed. — Alias of stripWeapons — destroy all held weapons. dropActiveWeapon(): boolean
— DEFERRED (always false): a true drop spawns a world pickup, not composable from remove(); needs the
DropActivePlayerWeapon signature-resolve.readonly nextAttack: number | null
— The current fire gate (m_flNextAttack, seconds), or null if unresolved/stale. Read companion to blockFiring.blockFiring(seconds?: number): boolean
— Block ALL weapon fire for seconds (default effectively-indefinite) by writing m_flNextAttack. The
gate is server-authoritative and time-based: a durable block needs a large value or a per-frame refresh.
Returns false if unresolved/stale. — Clear a fire block (m_flNextAttack = now). Returns false if unresolved/stale. aimTrace(opts?: { distance?: number; mask?: number; ignoreEntity?: EntityRef }): TraceHit | null
— Ray-trace from this pawn's eyes along its view angles — "what is this player looking at".
Eye = the body world origin + a standing view-offset (~64u); direction = eyeAngles. Ignores
this pawn's own entity unless ignoreEntity is given. Returns null if the transform/angles are
unreadable (stale ref). distance defaults to 8192.emitSound(name: string, opts?: { recipients?: number[]; volume?: number }): number
— Play a named CS2 SoundEvent from this pawn (the liveness-gated source entity; a stale ref emits
nothing). Returns the engine sound GUID (nonzero) or 0. Bot recipients are always skipped. Entry point for the Pawn body object — resolve the in-world pawn for a player slot.
import { Pawn } from "@s2script/cs2";
const pawn = Pawn.forSlot(0);
if (pawn) console.log(pawn.activeWeapon?.clip1);
forSlot(slot: number): Pawn | null
— The Pawn for a player slot, or null if unoccupied / invalidated. A CS2 player (the persistent controller entity): the generated CCSPlayerController schema fields
(team/score/ping/…) + the liveness-gated controller ref. pawn is the typed body (shadows the raw
generated m_hPawn handle). Referenced by slot (0-based); a stored Player degrades to null on reuse.
— The backing entity ref (the persistent controller's liveness-gated identity; degrades to null on reuse). — The 0-based player slot (CPlayerSlot). readonly pawn: Pawn | null
— This player's in-world pawn (the body), or null if dead/absent. — The engine user-id (session-stable; NOT a schema field). -1 if unassigned/absent. — The client's SteamID64 as a decimal string (engine GetClientXUID). "0" for bots / unauthenticated.
This is the AUTHORITATIVE id for admin lookups (Admin.get/forSlot use it). Do NOT confuse it with
the schema-generated steamID (capital ID, from m_steamID) — that controller field is string | null
and can be "0"/null, so using it for authorization decisions is unreliable. kick(reason?: string): void
— Disconnect this player (engine KickClient).setName(name: string): boolean
— Overwrite the player's display name (m_iszPlayerName); returns false if stale/unresolved.changeTeam(team: number): void
— Move this player's controller to team (Spectator=1, Terrorist=2, CounterTerrorist=3) via the
sig-resolved CCSPlayerController::ChangeTeam. Serial-gated; a no-op if the ref is stale or the
signature is unresolved. team is bounded to 0..3 engine-side. — Move this player to the Spectator team (= changeTeam(1)). switchTeam(team: number): void
— NON-LETHAL team switch between Terrorist (2) and CounterTerrorist (3) via the sig-resolved
CCSPlayerController::SwitchTeam: the player stays alive and keeps their weapons (vs changeTeam,
which has jointeam semantics and usually kills). Works on DEAD controllers too (a pure
scoreboard/win-condition team move). CAVEAT: the engine MAY respawn the pawn during the call —
re-resolve player.pawn on the next frame before any pawn write. Game events the engine fires
inside the call do not re-dispatch to JS handlers on that frame (re-entrancy skip). For None (0) /
Spectator (1) this dispatches to changeTeam (CSSharp/SwiftlyS2 parity) — prefer spectate().
Serial-gated; a no-op if the ref is stale or the signature is unresolved. Bounded 0..3 engine-side. — Respawn this (dead) player via the self-resolved CCSPlayerController::Respawn (byte-sig +
RTTI-vtable-membership load-validated). QUEUED: the engine call executes on the NEXT engine
frame, outside the JS isolate borrow, so the resulting player_spawn reaches EVERY plugin's
handlers — including the caller's. Safe from inside event/command handlers; no nextFrame
wrapping needed. Returns false when degraded: the player is already alive, the ref is stale,
or the Respawn descriptor failed its boot gates. Entry point for the Player controller object — resolve players by slot or user-id, enumerate
connected players, or resolve a SourceMod target string.
import { Player } from "@s2script/cs2";
for (const p of Player.all()) p.pawn?.slay();
fromSlot(slot: number): Player | null
— The Player for a 0-based slot, or null if the slot is unoccupied / the controller is stale. — Every connected player (slots with a valid controller). fromUserId(userId: number): Player | null
— Look up a connected player by engine user-id. null if no such player. Pawnless-safe. — Every connected player regardless of pawn (the pawnless enumeration). Complements all(). target(pattern: string, callerSlot: number, filterImmunity?: boolean): Player[]
— Resolve a SourceMod target string to matching connected players. #userid/name/@all/@me; empty on no match. callerSlot < 0 = server console (no @me). Game-event subscription (typed overlay). Importing from @s2script/cs2 gives the typed overloads:
Events.on("player_death", ev => ev.getPlayerSlot("attacker")) typechecks via the GameEvents map.
Events.onPre runs before broadcast and may return a HookResult to block.
Events.fire fires an event with typed field constraints.
The off signature matches @s2script/events semantics: removes ALL of this plugin's handlers for name.
on(name: K, handler: (ev: GameEvents[K]) => void): void
— Subscribe to a game event; the typed overload delivers the GameEvents[K] payload with typed field accessors.on(name: string, handler: (ev: GameEvent) => void): void
— Subscribe to a game event by raw name; the handler receives the generic GameEvent.off(name: string, handler: (ev: GameEvent) => void): void
— Remove ALL of this plugin's handlers for name (the handler arg is accepted for API symmetry but not matched).onPre(name: K, handler: (ev: GameEvents[K]) => HookResultValue | void): void
— Subscribe before broadcast; return a HookResultValue to block/modify. Typed payload overload.onPre(name: string, handler: (ev: GameEvent) => HookResultValue | void): void
— Subscribe before broadcast by raw name; return a HookResultValue to block/modify.fire(name: K, fields?: Record<string, number | string | boolean | bigint>, dontBroadcast?: boolean): boolean
— Fire a game event with typed field constraints; dontBroadcast keeps it server-side (not sent to clients). Returns false if the event is unknown.fire(name: string, fields?: Record<string, number | string | boolean | bigint>, dontBroadcast?: boolean): boolean
— Fire a game event by raw name; dontBroadcast keeps it server-side. Returns false if the event is unknown. Show-activity helper: SourceMod's FormatActivitySource per-recipient decision.
For each connected recipient, call formatSource(actorSlot, recipientSlot) to get
{ show, name } — whether to display the action to that recipient, and under what name
(real name for admins / self, generic label for non-admins, per the SHOW_ACTIVITY flags).
actorSlot < 0 = server console (always real "Console" label).
formatSource(actorSlot: number, recipientSlot: number): { show: boolean; name: string }
— SourceMod FormatActivitySource: per-recipient {show, name} for an admin action by actorSlot (actorSlot < 0 = server console). CS2 chat color control bytes (values from CounterStrikeSharp's ChatColors enum). Prepend one to a chat
message to color it — CS2 requires a leading control byte for the message to render at all. The plugin
owns color (SourceMod-parity): e.g. Chat.toAll(ChatColors.Green + "[SM] hello").
— Reset to the client's default chat color. readonly LightPurple: string
— Light-purple control byte.readonly DarkBlue: string
— Dark-blue control byte.readonly BlueGrey: string
— Blue-grey control byte.readonly LightRed: string
— Light-red control byte.fn pickPlayer(adminSlot: number, onPicked: (target: Player) => void): void
Show a target-picker Center menu of connected players to adminSlot (the adminmenu framework's shared
player picker; freezePlayer is on). The picked player is re-resolved via Player.fromUserId at select
time, so onPicked only ever receives a live target — a player who left in the meantime is skipped with
a chat notice to adminSlot, and onPicked is not called.
A live CEnvBeam handle. update() moves both endpoints; remove() destroys it.
— The backing CEnvBeam entity ref. update(start: Vector, end: Vector): void
— Move both endpoints — the beam redraws from start to end. — Destroy the beam entity; returns false if it's already gone / the ref is stale. Draw a point-to-point beam (a CEnvBeam) from start to end. Returns a handle, or null if the entity
couldn't be created. The beam is game-world-owned — call handle.remove() to clean up.
draw(start: Vector, end: Vector, opts?: { color?: [number, number, number, number]; width?: number }): BeamHandle | null
— Draw a point-to-point beam from start to end. opts.color is RGBA, opts.width in units. Returns a BeamHandle, or null if the entity couldn't be created. A live read view over CCSGameRules (via the cs_gamerules proxy). Every field is liveness-gated at the
proxy root and reads null if the proxy is gone (e.g. between maps).
readonly warmupPeriod: boolean | null
— In warmup (m_bWarmupPeriod).readonly freezePeriod: boolean | null
— In freeze time (m_bFreezePeriod) — players frozen at round start.readonly roundTime: number | null
— Configured round length in seconds (m_iRoundTime).readonly freezeTime: number | null
— Configured freeze-time length in seconds (m_iFreezeTime); the first slice of the round span.readonly totalRoundsPlayed: number | null
— Rounds played this match (m_totalRoundsPlayed).readonly gamePhase: number | null
— Current game phase enum (m_gamePhase).readonly bombPlanted: boolean | null
— The bomb is currently planted (m_bBombPlanted).readonly roundsPlayedThisPhase: number | null
— Rounds played in the current phase (m_nRoundsPlayedThisPhase).readonly gameRestart: boolean | null
— A game restart is queued (m_bGameRestart).readonly gameStartTime: number | null
— Match start time (m_flGameStartTime, GameTime_t).readonly matchWaitingForResume: boolean | null
— Match is paused awaiting resume (m_bMatchWaitingForResume).readonly hasMatchStarted: boolean | null
— The match has started (m_bHasMatchStarted).readonly roundStartTime: number | null
— m_fRoundStartTime (GameTime_t): the map-time at which the current round started.readonly timeElapsed: number | null
— Server.gameTime - roundStartTime — real seconds since the round started (freeze included; the
engine ends the round at roundStartTime + roundTime). null pre-round / no proxy.readonly timeRemaining: number | null
— roundTime - timeElapsed — real seconds until the engine ends the round (matches the HUD clock).setRoundTime(seconds: number): boolean
— Write m_iRoundTime and renetwork it (proxy notifyStateChanged at m_pGameRules — the HUD clock
repaints on clients). Returns false if the proxy is stale or an offset fails to resolve.setTimeRemaining(seconds: number): boolean
— Set the REMAINING round time (writes roundTime = timeElapsed + seconds).addTimeRemaining(seconds: number): boolean
— Extend/shrink the round clock by delta seconds (writes roundTime += seconds).terminateRound(reason: number, delay?: number): boolean
— Force the round to end with a RoundEndReason (sig-resolved CCSGameRules::TerminateRound).
QUEUED: executes on the NEXT engine frame, outside the JS isolate borrow, so every plugin's
round_end handler — including the caller's — fires normally (a state read immediately after
still sees the old round). delay (default 5s) is the engine's pre-restart delay. Returns true if
queued; false when degraded (unresolved signature, stale proxy, or reason outside 0..22). Read + drive CCSGameRules state. get() re-finds the cs_gamerules proxy each call (liveness-gated
cache); returns null when no proxy exists (e.g. pre-map-load).
get(): GameRulesView | null
— Re-find the cs_gamerules proxy and return a live GameRulesView, or null when no proxy exists (e.g. pre-map-load).terminateRound(reason: number, delay?: number): boolean
— Convenience over get()?.terminateRound(reason, delay) — false when no proxy. Team scoreboard scores (cs_team_manager entities, CTeam.m_iScore + notifyStateChanged). team is
0..3 (Unassigned/Spectator/T/CT), matched by m_iTeamNum; entities are re-found per call.
getScore(team: number): number | null
— Read the scoreboard score for team (0..3), or null if no matching cs_team_manager entity.setScore(team: number, score: number): boolean
— Overwrite the scoreboard score for team (writes m_iScore + notifyStateChanged). false if the entity isn't found.addScore(team: number, delta: number): boolean
— Add delta to team's scoreboard score. false if the entity isn't found. CS2 round-end reasons (CCSGameRules::TerminateRound / round_end.reason). Binary-validated against
our build (reason bound = 22; #SFUI_Notice_* switch). Gaps 2/3/15 are removed legacy VIP reasons.
readonly TerroristsEscaped: 4
— T's escaped (legacy es_ maps).readonly CTsPreventEscape: 5
— CT's prevented the escape.readonly EscapingTerroristsNeutralized: 6
— Escaping T's were neutralized.readonly TerroristsWin: 9
— T's win the round.readonly AllHostagesRescued: 11
— All hostages were rescued. — The VIP target was saved. readonly HostagesNotRescued: 13
— Hostages were not rescued in time.readonly TerroristsNotEscaped: 14
— T's did not escape in time.readonly GameCommencing: 16
— The game is (re)commencing / warmup.readonly TerroristsSurrender: 17
— T's surrendered.readonly CTsSurrender: 18
— CT's surrendered.readonly TerroristsPlanted: 19
— T's planted the bomb (round-end variant).readonly CTsReachedHostage: 20
— CT's reached the hostages.readonly SurvivalDraw: 22
— Survival-mode draw. cs_win_panel_round final_event values (validated at the live gate against a natural round end).
— CT's won (final_event = 2). readonly TerroristsWin: 3
— T's won (final_event = 3). Screen-fade user message (CUserMessageFade). duration/holdTime are engine fade units; color is a
packed RGBA fixed32. Returns false if the message/fields don't resolve.
to(slot: number, opts: { duration?: number; holdTime?: number; color?: number; flags?: number }): boolean
— Send a screen fade to slot. duration/holdTime are engine fade units; color is packed RGBA fixed32. false if unresolved.blind(slot: number, duration?: number): boolean
— Convenience full-screen blind (opaque fade) for duration — the canonical flashbang-style effect. Screen-shake user message (CUserMessageShake). command 0 = start. Returns false if unresolved.
to(slot: number, opts: { command?: number; amplitude?: number; frequency?: number; duration?: number }): boolean
— Send a screen shake to slot. command 0 = start; amplitude/frequency/duration are engine shake units. false if unresolved. Best-effort hint text (TextMsg-family). Returns false if the message/fields don't resolve.
to(slot: number, text: string): boolean
— Show text as hint text to slot. false if the message/fields don't resolve. A world-space coordinate triple (a corner or center of a TriggerZoneHandle box).
A live runtime trigger_multiple zone (from TriggerZone.create).
— The backing trigger_multiple entity ref. — The box center in world space. — Destroy the trigger entity; false if already gone/stale. Create arbitrary-box touch zones at runtime (a runtime trigger_multiple).
create(min: ZoneBox, max: ZoneBox, opts?: { model?: string; spawnflags?: number }): TriggerZoneHandle | null
— Create a runtime engine trigger_multiple whose touch volume is the arbitrary box [min,max].
Fires OnStartTouch/OnEndTouch (hook via Entity.onOutput). Non-solid (pass-through). Curated built-in CS2 soundevent names (see
— Player ping soundevent (UI.PlayerPing). readonly PingUrgent: string
— Urgent player ping soundevent (UI.PlayerPingUrgent).readonly Ak47Shot: string
— AK-47 single-shot soundevent (Weapon_AK47.Single).readonly DeagleShot: string
— Desert Eagle single-shot soundevent (Weapon_DEagle.Single). A CS2 weapon entity (CCSWeaponBase). All generated field accessors (clip1, clip2, fallbackPaintKit,
ownerEntity, inherited health/teamNum/...) are read+write; a stale weapon reads null.
— The backing entity ref (escape hatch to the raw EntityRef surface). — The weapon skin id (alias of the generated fallbackPaintKit). readonly owner: Pawn | null
— The holding Pawn (m_hOwnerEntity), or null if unowned (on the ground) / stale.setAmmo(clip: number, reserve?: number): boolean
— Set the magazine (clip1). reserve is accepted but deferred (m_pReserveAmmo layout). false if stale. — Unequip from the owner (RemovePlayerItem) + destroy the entity (UTIL_Remove). true iff removed. Entry point for the Weapon entity object — wrap a raw EntityRef or enumerate weapons
by class name. Prefer Pawn's activeWeapon/weapons/giveNamedItem for owned weapons.
import { Weapon } from "@s2script/cs2";
// `ent` is an EntityRef, e.g. from Entity.onSpawn("weapon_*", …)
const weapon = Weapon.fromEntity(ent);
if (weapon) weapon.setAmmo(90);
fromEntity(ref: EntityRef | null): Weapon | null
— Wrap a raw weapon EntityRef; null if ref is null.findAll(className: string): Weapon[]
— Every live entity of className as a Weapon (e.g. "weapon_ak47").