Knight docs
EN ID
GitHub

Your First Gamemode

Build a small but complete deathmatch gamemode step by step.

This walkthrough builds a small team deathmatch: two teams, classes, spawn protection, a score command and a kill feed. Every piece is explained.

1. The file

Create Gamemodes/tdm.sa. A gamemode is a single file; there are no required includes.

knight
#include <knight>   // optional; natives are built in

// --- configuration written to server.cfg -------------------------------
system::config() {
    server.name = "Knight TDM";
    server.max_players = 64;
    server.port = 7777;
    server.language = "English";
};

// --- module state (shared by every callback) ---------------------------
let SPAWN_PROTECT_MS = 3000;
let protectionUntil = {};
let kills = {};
let deaths = {};
let teamScores = { "red": 0, "blue": 0 };

function now() { return GetTickCount(); }
function key(prefix, id) { return prefix + id; }

system::config() runs before the server starts. Everything else is declared at module level and shared across callbacks.

2. Classes for two teams

knight
system::start() {
    SetGameModeText("Knight TDM");
    ShowPlayerMarkers(1);
    SetWeather(10);
    SetWorldTime(12);

    // AddPlayerClass(skin, x, y, z, angle, weapon1, ammo1, weapon2, ammo2, ...)
    // Red team (skin 287) and Blue team (skin 285) at different spawns.
    AddPlayerClass(287, 1958.4, 1343.2, 15.4, 270.0, 24, 100, 31, 200);
    AddPlayerClass(285, 1965.0, 1343.2, 15.4, 90.0, 24, 100, 31, 200);

    Log("TDMs ready");
};
Note
The class index is the order of AddPlayerClass calls. The engine sends it back in player::request_class and lets the player pick with the normal class screen.

3. Welcome and class selection

knight
player::connect(int playerid) {
    kills[key("k", playerid)] = 0;
    deaths[key("d", playerid)] = 0;
    SendClientMessage(playerid, "Welcome to Knight TDM!");
};

player::request_class(int playerid, int classid) {
    // Allow every class; return false to block selection.
    return true;
};

player::spawn(int playerid) {
    let until = now() + SPAWN_PROTECT_MS;
    protectionUntil[key("p", playerid)] = until;
    SetPlayerHealth(playerid, 100.0);
    SetPlayerArmour(playerid, 50.0);
    SendClientMessage(playerid, "Spawn protection: {SPAWN_PROTECT_MS / 1000}s");
};

4. Kill feed and scores

knight
player::death(int playerid, Player killer, int reason) {
    deaths[key("d", playerid)] = GetPlayerScore(playerid);

    if (killer != null) {
        let kid = killer;
        kills[key("k", kid)] = GetPlayerScore(kid) + 1;
        SetPlayerScore(kid, GetPlayerScore(kid) + 1);
        GivePlayerMoney(kid, 100);
        SendClientMessage(kid, "You killed {PlayerName(playerid)}");
    }

    SendClientMessage(playerid, "You died. Respawning...");
    SendDeathMessage(playerid, killer, reason);
};
Warning
killer is null when a player dies from falling, drowning or a world cause. Always check for null before using it.

5. Commands

knight
player::command("/stats") {
    SendClientMessage(playerid, "Kills: {kills[key(\"k\", playerid)]} | Deaths: {deaths[key(\"d\", playerid)]}");
};

player::command("/heal") {
    SetPlayerHealth(playerid, 100.0);
    SendClientMessage(playerid, "Healed.");
};

player::command("/tp", float x, float y, float z) {
    SetPlayerPos(playerid, x, y, z);
    SendClientMessage(playerid, "Teleported.");
};

6. Check and run

bash
knight -check Gamemodes/tdm.sa
knight-server -cfg server.cfg -gamemode Gamemodes/tdm.sa

Connect with a SA-MP 0.3.7 client, pick a class, spawn, and shoot. /stats shows your score.

Tip
Read the Callbacks and Native Functions pages to extend this gamemode.