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
// --- 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.