---
title: "Write Your First AMX Mod X Plugin (Hello World)"
excerpt: "A complete, working first plugin: register a chat command that reports a player's health, compiled and installed step by step. Real Pawn, not pseudocode."
category: "plugin-dev"
tags: "amxmodx, beginner"
image: ""
read_time: "8 min read"
---
<p>The fastest way to understand AMX Mod X is to write a plugin that does something real, compile it, and watch it run on your server. This one registers a chat command — typing <code>/hp</code> reports your health and armor — and greets players when they connect. It is short, it compiles, and it touches the three things every plugin uses: <code>plugin_init</code>, a command callback, and a client event. If the Pawn syntax here is unfamiliar, read <a href="/tutorials/pawn-basics-for-amxx">Pawn language basics</a> first.</p>
<h2>1. Create the .sma source</h2>
<p>Make a file <code>myfirst.sma</code>. The <code>#include <amxmodx></code> line pulls in the core API; <code>#include <cstrike></code> gives you CS-specific natives like armor:</p>
<pre>#include <amxmodx>
#include <cstrike>
#define PLUGIN "My First Plugin"
#define VERSION "1.0.0"
#define AUTHOR "Your Name"
public plugin_init() {
register_plugin(PLUGIN, VERSION, AUTHOR)
register_clcmd("say /hp", "cmd_hp")
register_clcmd("say_team /hp", "cmd_hp")
}
public cmd_hp(id) {
if (!is_user_alive(id)) {
client_print(id, print_chat, "[MyPlugin] You are dead.")
return PLUGIN_HANDLED
}
new health = get_user_health(id)
new armor = cs_get_user_armor(id)
new name[32]
get_user_name(id, name, charsmax(name))
client_print(id, print_chat, "[MyPlugin] %s - HP: %d, Armor: %d", name, health, armor)
return PLUGIN_HANDLED
}
public client_putinserver(id) {
new name[32]
get_user_name(id, name, charsmax(name))
client_print(0, print_chat, "[MyPlugin] Welcome, %s!", name)
}</pre>
<h2>2. Understand what each part does</h2>
<ul>
<li><strong><code>plugin_init()</code></strong> runs once when the plugin loads. <code>register_plugin</code> is mandatory — it names the plugin in <code>amxx list</code>.</li>
<li><strong><code>register_clcmd("say /hp", "cmd_hp")</code></strong> ties the chat text <code>/hp</code> to your <code>cmd_hp</code> function. Registering both <code>say</code> and <code>say_team</code> means it works whether typed in all-chat or team-chat.</li>
<li><strong><code>cmd_hp(id)</code></strong> receives the player's id (1–32). Returning <code>PLUGIN_HANDLED</code> stops the <code>/hp</code> text from also appearing as a public chat message.</li>
<li><strong><code>client_putinserver(id)</code></strong> is a forward AMXX calls when a player finishes connecting. <code>client_print(0, ...)</code> with id <code>0</code> prints to everyone.</li>
</ul>
<h2>3. Compile it</h2>
<p>Compile <code>myfirst.sma</code> into <code>myfirst.amxx</code>. The full walkthrough is in <a href="/tutorials/compile-sma-to-amxx">compiling a .sma into .amxx</a>; the short version on the server box is:</p>
<pre>cd /home/steam/hlds/cstrike/addons/amxmodx/scripting
./amxxpc myfirst.sma</pre>
<p>A clean compile ends with <code>Done.</code> and produces <code>compiled/myfirst.amxx</code>. Warnings about unused symbols are fine; <em>errors</em> stop the build and must be fixed.</p>
<h2>4. Install it</h2>
<p>Copy the compiled plugin into the plugins folder and register it:</p>
<pre>cp compiled/myfirst.amxx ../plugins/myfirst.amxx</pre>
<p>Add a line to <code>addons/amxmodx/configs/plugins.ini</code>:</p>
<pre>myfirst.amxx</pre>
<p>Then reload plugins without restarting the whole server — from RCON or the server console:</p>
<pre>amxx reload</pre>
<p>Or just change the map. <code>amxx reload</code> re-reads <code>plugins.ini</code>.</p>
<h2>5. Test in game</h2>
<p>Join the server and type <code>/hp</code> in chat. You should see your name, HP, and armor printed back to you, and no <code>/hp</code> text leaking to public chat. Connect a second client and the whole server should see the welcome line.</p>
<h2>6. Add a cvar to toggle it</h2>
<p>Hard-coded behaviour is fine for a first plugin, but a real one is configurable. Add a cvar so admins can switch the welcome message off without recompiling. Register it in <code>plugin_init</code> and check it before printing:</p>
<pre>new g_pWelcome
public plugin_init() {
register_plugin(PLUGIN, VERSION, AUTHOR)
register_clcmd("say /hp", "cmd_hp")
register_clcmd("say_team /hp", "cmd_hp")
g_pWelcome = register_cvar("myplugin_welcome", "1")
}
public client_putinserver(id) {
if (!get_pcvar_num(g_pWelcome))
return
new name[32]
get_user_name(id, name, charsmax(name))
client_print(0, print_chat, "[MyPlugin] Welcome, %s!", name)
}</pre>
<p>Now admins can put <code>myplugin_welcome 0</code> in <code>server.cfg</code> (or better, an <code>amxx.cfg</code>) to silence the greeting. Recompile, reload, and the cvar exists immediately — verify with <code>myplugin_welcome</code> in the console.</p>
<h2>Common errors</h2>
<ul>
<li><strong>Plugin shows as <code>bad load</code> in <code>amxx list</code></strong> — the <code>.amxx</code> was built for a newer AMXX than the server runs, or the file is corrupt. Recompile with the matching compiler; see <a href="/tutorials/install-amx-mod-x-1-9">AMX Mod X 1.9</a>.</li>
<li><strong><code>/hp</code> also appears in chat</strong> — you returned <code>PLUGIN_CONTINUE</code> (or nothing) instead of <code>PLUGIN_HANDLED</code>.</li>
<li><strong><code>cs_get_user_armor</code> undefined</strong> — you forgot <code>#include <cstrike></code>.</li>
<li><strong>Nothing happens on <code>/hp</code></strong> — the plugin is not in <code>plugins.ini</code>, or you did not <code>amxx reload</code> / change map.</li>
<li><strong>Garbage or truncated name</strong> — the <code>name</code> buffer is too small or you passed the wrong length; use <code>charsmax(name)</code>.</li>
</ul>
<h2>Verification</h2>
<p>In the server console:</p>
<pre>amxx list</pre>
<p>Your plugin must appear as <code>running</code> (not <code>bad load</code> or <code>debug</code>). Once it does and <code>/hp</code> works in game, you have the full loop: edit, compile, install, reload. From here, add a cvar to toggle the feature and explore the <code>cstrike</code> and <code>fun</code> natives — and when you want a proper editor, set up <a href="/tutorials/vscode-amxx-setup">VS Code for AMX Mod X</a>.</p>