SourcePawn

The script API — how the C++ interfaces, schema classes and hooks look from a .sp, and where scripts work differently.

A SourcePawn plugin is a .sp compiled with spcomp into an .smx and dropped into addons/source2mod/plugins/, next to the C++ plugins. It talks to the same core through the same API: there is no second, smaller "script API", only a second language. How to set up, compile and load a first script is on SourcePawn plugins; this section is about writing them.

One include

plugin.sp
#include <source2mod/api>

source2mod/api pulls in everything. The pieces can be included alone (source2mod/commands, source2mod/schema, …), each named after the area it covers:

IncludeC++
core, functionsThe language core, natives, forwards, libraries — ISource2ModNatives
engineISource2ModAPI (Source2ModApi.Log, Format), the engine server, CGlobalVars
schema, entitiesThe schema classes, ISource2ModEntities
convars, commandsISource2ModConVars, ISource2ModCommands
events, listenerISource2ModEvents, the ISource2ModListener callbacks as forwards
gamehooks, hooks, gameconfig, addressesISource2ModGameHooks, raw KHooks, ISource2ModGameConfig, ISource2ModAddresses
schedulerISource2ModScheduler
adt, datapackSourceMod's ArrayList, StringMap, ArrayStack, IntMap, DataPack
netmessages, sounds, transmit, trace, menus, customhud, scripts, translations, targeting, files, paths, json, http, sql, cookies, geoip, maps, features, permissions, clients, utilsThe interfaces of the same names (ISource2ModNetworkMessages, ISource2ModSounds, …)

The include set ships with every Source2Mod build in addons/source2mod/scripting/include, and lives in the SDK under public/scripting.

How the C++ API maps

The script API follows the C++ one name for name, so the rest of the documentation reads for both languages:

C++SourcePawn
An interface: g_pSource2ModCommands->RegisterConCommand(...)A methodmap of static methods, named without the I and the version: Source2ModCommands.RegisterConCommand(...)
A schema class: CCSPlayerPawn*A methodmap of the same name and base class: CCSPlayerPawn
A field: pPawn->m_iHealth = 150;A property: pawn.m_iHealth = 150; — a write to a networked field reaches the clients the same way
A vector, color or string fieldA method of the field's name that fills a buffer, and Set_<name>() to write it
A helper: pPawn->Teleport(...), pController->GetPlayerPawn()The same method: pawn.Teleport(...), player.GetPlayerPawn()
CEntityInstance*, CHandle<T>An entity handle; NULL_ENTITY for none
Services, the scene node, the game rulesA SchemaObject (pawn.m_pItemServices); IsNull for none
A hook or listener returns a Source2ModHookIdHook* / Register* / Add* return an int id that the matching Unhook* / Unregister* / Remove* takes
KHook::Action::Ignore / Override / SupersedeAction_Ignore / Action_Override / Action_Supersede (Source2ModAction)
ISource2ModListener::OnClientPutInServer, …Forwards named Source2Mod_On…: declare the function and it is called
A lambdaA function of the script; an any data argument carries what the lambda captured
An object the API hands out (ISource2ModJSONDocument*, a menu, a SQL connection)A Handle of the same name; delete closes it
uint64 (a SteamID, a 64-bit field)Decimal text, or two cells where the include says so
uint64 player masksint mask[2] and the PlayerMask_* stocks

Everything a script registers — commands, hooks, listeners, timers, natives, handles — belongs to it and goes when it unloads.

The same command in both languages:

plugin.cpp
bool MyPlugin::Load(PluginId id, ISource2ModAPI* api, char* error, size_t maxlen, bool late)
{
    SOURCE2MOD_SAVEVARS();

    g_pSource2ModCommands->RegisterConCommand("heal", [](const Source2ModCommandContext& context, const Source2ModCommandArgs& args, bool post)
    {
        CPlayerSlot slot = context.GetPlayerSlot();
        CCSPlayerController* pPlayer = slot.IsValid() ? CCSPlayerController::FromSlot(slot) : nullptr;
        CCSPlayerPawn* pPawn = pPlayer ? pPlayer->GetPlayerPawn() : nullptr;
        if (!pPawn || !pPlayer->m_bPawnIsAlive())
            return;

        pPawn->m_iHealth = 100;
        g_pSource2ModCommands->ReplyToCommand(context, "Healed.");
    }, "myplugin.heal");

    return true;
}

Two kinds of action

SourcePawn scripts meet two enums that both answer "what now":

EnumValuesAnswered by
Source2ModActionAction_Ignore, Action_Override, Action_SupersedeHooks: game events, game hooks, raw hooks, command listeners, entity outputs — the C++ KHook::Action
ActionPlugin_Continue, Plugin_Changed, Plugin_Handled, Plugin_StopFunctions of a GlobalForward / PrivateForward between plugins, as in SourceMod

In this section

On this page