AMX Mod X gives you three fundamentally different ways to react to what happens in a round, and choosing wrong means either code that cannot see what you need or a dependency you did not have to take on. register_event listens to network messages. Ham Sandwich hooks virtual functions inside the game DLL. ReAPI hooks ReGameDLL's real functions with named arguments. They overlap in what they can do but differ sharply in what they can see, whether they can change it, and what they require to be installed.
1. register_event — the network message layer
Events fire when the game DLL sends a message to a client: someone died (DeathMsg), health changed (Health), a weapon became active (CurWeapon). It is pure core AMXX — no module, no engine replacement — so it runs on stock HLDS as happily as on ReHLDS. See the register_event guide for details.
Its limitation is that it is a notification, not an interception. By the time DeathMsg is sent, the player is already dead. You can react, but you cannot prevent, and you cannot read anything the message does not carry. It is also occasionally lossy: a message that the DLL chooses not to send is an event you never see.
2. Ham Sandwich — virtual function hooks
Ham Sandwich (module hamsandwich) hooks the virtual methods of game entities: Ham_TakeDamage, Ham_Killed, Ham_Spawn, Ham_Player_PreThink. These fire as the function runs, in both a pre and a post variant, so you can read the real arguments and — crucially — block or modify them:
#include <amxmodx>
#include <hamsandwich>
public plugin_init()
{
register_plugin("Ham Demo", "1.0", "CSB")
RegisterHam(Ham_TakeDamage, "player", "fw_take_damage", 0)
}
public fw_take_damage(victim, inflictor, attacker, Float:damage, bits)
{
// halve all incoming damage
SetHamParamFloat(4, damage * 0.5)
return HAM_HANDLED
}
Ham Sandwich works on both original CS and ReGameDLL, which is its great advantage: portable damage/spawn/kill hooks that run anywhere. The cost is that it deals in raw offsets — entity classnames, parameter positions — and gives you no named members. See the Ham Sandwich guide.
3. ReAPI — the ReGameDLL native layer
ReAPI (module reapi) exposes ReGameDLL and ReHLDS internals directly: hook chains (RegisterHookChain), named members (get_member/set_member), and high-level natives (rg_give_item, rg_add_account). It is the richest and cleanest of the three — but it requires ReGameDLL. A plugin that #include <reapi> will not load on a server running the stock game DLL.
#include <amxmodx>
#include <reapi>
public plugin_init()
{
register_plugin("ReAPI Demo", "1.0", "CSB")
RegisterHookChain(RG_CBasePlayer_TakeDamage, "on_take_damage", 0)
}
public on_take_damage(const victim, inflictor, attacker, Float:damage, bits)
{
SetHookChainArg(4, ATYPE_FLOAT, damage * 0.5)
return HC_CONTINUE
}
If you ship a ReAPI plugin, set both reapi_required and regamedll_required in its metadata — the two go together. Install steps are in the ReAPI install guide, which itself depends on ReGameDLL.
4. The decision rule
| register_event | Ham Sandwich | ReAPI | |
|---|---|---|---|
| Requires | Core AMXX only | hamsandwich module | ReGameDLL + reapi |
| Can block / modify | No | Yes | Yes |
| Named arguments | No | No | Yes |
| Runs on stock CS DLL | Yes | Yes | No |
In practice:
- You only need to know something happened — a kill for a HUD, a weapon switch for a speed cap — use
register_event. It is the lightest and most portable. - You need to change damage, spawning, or killing, and the plugin must run on any server — use Ham Sandwich. It is the portable interception layer.
- You are already on ReGameDLL and want clean, correct, named access — use ReAPI. It replaces piles of Ham + fakemeta guesswork with readable natives, at the price of a hard dependency.
5. They compose
Real plugins mix all three: a register_event on DeathMsg to update a scoreboard, a RegisterHam(Ham_Spawn, ...) to give spawn protection, and — on a ReGameDLL server — rg_add_account to hand out money. There is no rule against combining them; the rule is to take the lightest tool that can see and do what a given feature needs, so the plugin loads on the widest set of servers.
Common mistakes
- Reaching for ReAPI on a stock-DLL server — the plugin fails to load with a module error. Confirm ReGameDLL first with
regamedll_versionin the console. - Trying to block damage with
register_event— impossible; events are notifications. Move the logic toHam_TakeDamageor the ReAPI hook chain. - Hooking the same effect in two layers — e.g. blocking damage in Ham and ReAPI. Pick one; double-hooking produces confusing double-applied modifications.
Verification
For any hook, add a server_print at the top of the handler and confirm it fires exactly once per real in-game event. If a Ham or ReAPI plugin refuses to load, check the AMXX logs for a module-load line — a missing hamsandwich or reapi module is the usual cause, covered in the module-failed-to-load fix.









