<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.alliedmods.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Cj2At1</id>
	<title>AlliedModders Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.alliedmods.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Cj2At1"/>
	<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/Special:Contributions/Cj2At1"/>
	<updated>2026-05-10T08:12:16Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.6</generator>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Advanced_Scripting_(AMX_Mod_X)&amp;diff=4571</id>
		<title>Advanced Scripting (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Advanced_Scripting_(AMX_Mod_X)&amp;diff=4571"/>
		<updated>2007-05-29T22:15:12Z</updated>

		<summary type="html">&lt;p&gt;Cj2At1: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This article will briefly summarize some of the more advanced topics of [[:Category:Scripting (AMX Mod X)|AMX Mod X Scripting]].&lt;br /&gt;
&lt;br /&gt;
=Tasks=&lt;br /&gt;
&lt;br /&gt;
Tasks are timers that let you run code at an interval, either once or repeated. They are useful for things like waiting a few seconds, setting objects to destroy themselves, or just repeating a task over and over.&lt;br /&gt;
&lt;br /&gt;
A task can be set in a number of different ways. The actual function is set_task():&lt;br /&gt;
&amp;lt;pawn&amp;gt;set_task(Float:time,const function[],id = 0,parameter[]=&amp;quot;&amp;quot;,len = 0,flags[]=&amp;quot;&amp;quot;, repeat = 0)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The parameters break down as such:&lt;br /&gt;
&lt;br /&gt;
* Float:time - Interval of timer in seconds (minimum 0.1 seconds)&lt;br /&gt;
* function[] - A string that contains the public function to run on the timer&lt;br /&gt;
* id - A unique id to assign to the task&lt;br /&gt;
* parameter - An array contain data to send to the timer function&lt;br /&gt;
* len - Size of the array to send to the timer function&lt;br /&gt;
* flags - One of the following:&lt;br /&gt;
** &amp;quot;a&amp;quot; - Repeat task a specified number of times&lt;br /&gt;
** &amp;quot;b&amp;quot; - Loop task infinitely&lt;br /&gt;
** &amp;quot;c&amp;quot; - do task on time after a map timeleft&lt;br /&gt;
** &amp;quot;d&amp;quot; - do task on time before a map timeleft&lt;br /&gt;
* repeat - If flags is &amp;quot;a&amp;quot;, specifies the number of times to repeat the task&lt;br /&gt;
&lt;br /&gt;
An example of a task is below. It will slap a specified player 5 times, once per second.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//the timed function receives the parameter array and its task id&lt;br /&gt;
public slapTask(params[], id)&lt;br /&gt;
{&lt;br /&gt;
   new player = params[0]&lt;br /&gt;
   user_slap(player, 5)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public start_slapping(id)&lt;br /&gt;
{&lt;br /&gt;
   new params[1]&lt;br /&gt;
   params[0] = id&lt;br /&gt;
   //we don't need a specific id&lt;br /&gt;
   set_task(1.0, &amp;quot;slapTask&amp;quot;, 0, params, 1, &amp;quot;a&amp;quot;, 5)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that if you specify 0 for parameter length, then the task function should look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public slapTask(id)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Menus=&lt;br /&gt;
&lt;br /&gt;
Menus are HUD messages that give a player a choice of options to select. They are quite messy to deal with but can be very useful for things like voting and command selection.&lt;br /&gt;
&lt;br /&gt;
Menus must be registered by two things - a set of &amp;quot;keys&amp;quot; that tells how many options to register and a string which identifies the menu as unique. This string must appear in the beginning of every menu you want to trigger your function. When you display a menu, you can show it to one or more players. Once they hit a key, the result of their key press will be sent to the function you registered the menu to.&lt;br /&gt;
&lt;br /&gt;
For our example, we'll make a menu that displays a list of guns: AK47, M4A1, or AWP, to a player. Whichever he selects, he will be given.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
#include &amp;lt;amxmisc&amp;gt;&lt;br /&gt;
#include &amp;lt;fun&amp;gt;&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    register_plugin(&amp;quot;Menu Demo&amp;quot;, &amp;quot;1.0&amp;quot;, &amp;quot;BAILOPAN&amp;quot;)&lt;br /&gt;
    new keys = MENU_KEY_0|MENU_KEY_1|MENU_KEY_2&lt;br /&gt;
    register_menucmd(register_menuid(&amp;quot;Which Weapon?&amp;quot;), keys, &amp;quot;giveWeapon&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Two commands are apparent here - register_menuid and register_menucmd. register_menuid registers a short phrase that will appear at the beginning of the menu, then returns an id. This id is the first parameter to register_menucmd. The second parameter to register_menucmd is the key configuration. Our menu will have three options, so we've added three menu keys in. In actuality, these are bitwise flags totalling &amp;quot;7&amp;quot;, but that's not important. The last parameter is the public function that will handle the menu results.&lt;br /&gt;
&lt;br /&gt;
Next, how do we show the menu? Let's make a quick console command: &amp;quot;giveme&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    register_plugin(&amp;quot;Menu Demo&amp;quot;, &amp;quot;1.0&amp;quot;, &amp;quot;BAILOPAN&amp;quot;)&lt;br /&gt;
    new keys = MENU_KEY_0|MENU_KEY_1|MENU_KEY_2&lt;br /&gt;
    register_menucmd(register_menuid(&amp;quot;Which Weapon?&amp;quot;), keys, &amp;quot;giveWeapon&amp;quot;)&lt;br /&gt;
    register_clcmd(&amp;quot;giveme&amp;quot;, &amp;quot;showWeaponMenu&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
register_clcmd is similar to register_concmd, except it only takes two parameters. It's used to register any command a client can use (except for special ones, like  attack).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//The clcmd function will just give us the player id&lt;br /&gt;
public showWeaponMenu(id)&lt;br /&gt;
{&lt;br /&gt;
    new menu[192]&lt;br /&gt;
    new keys = MENU_KEY_0|MENU_KEY_1|MENU_KEY_2&lt;br /&gt;
&lt;br /&gt;
    format(menu, 191, &amp;quot;Which Weapon?^n^n1. AK47^n2. M4A1^n3. AWP&amp;quot;)&lt;br /&gt;
    show_menu(id, keys, menu)&lt;br /&gt;
    return PLUGIN_HANDLED&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Our menu function will get the player id and the key they pressed&lt;br /&gt;
public giveWeapon(id, key)&lt;br /&gt;
{&lt;br /&gt;
    //key will start at zero&lt;br /&gt;
    if (key == 0)&lt;br /&gt;
    {&lt;br /&gt;
         give_item(id, &amp;quot;weapon_ak47&amp;quot;)&lt;br /&gt;
    } else if (key == 1) {&lt;br /&gt;
         give_item(id, &amp;quot;weapon_m4a1&amp;quot;)&lt;br /&gt;
    } else if (key == 2) {&lt;br /&gt;
         give_item(id, &amp;quot;weapon_awp&amp;quot;)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And we're done! The format line may be a little confusing. The &amp;quot;^n&amp;quot; means &amp;quot;new line&amp;quot;, so the menu looks nicely formatted. You can use other modifiers in VGUI2 mods, such as &amp;quot;\w&amp;quot; for white text, &amp;quot;\r&amp;quot; for red text, and &amp;quot;\y&amp;quot; for yellow text. When a player types the command, he will see the menu. When he hits a key, the giveWeapon function will receive his id and the key number he pressed. Then he will get a gun corresponding to what he chose.&lt;br /&gt;
&lt;br /&gt;
=Events/Messages=&lt;br /&gt;
&lt;br /&gt;
For this demonstration, we're going to extend the above example. Every time a player respawns, he will be shown the menu to choose a weapon (note - we're ignoring other things like blocking buying and removing buyzones, this is just a demonstration).&lt;br /&gt;
&lt;br /&gt;
Messages are a way for Half-Life clients to talk to servers, and vice versa. They are specially formatted lists of parameters. For example, the message &amp;quot;DeathMsg&amp;quot; (message id 83) has three parameters: Attacker (byte), Victim (byte), and Weapon (string). You can either capture messages or send them. Here, we'll do a simple demonstration of both. First let's make it so a user gets their gun menu when they spawn.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    register_plugin(&amp;quot;Menu Demo&amp;quot;, &amp;quot;1.0&amp;quot;, &amp;quot;BAILOPAN&amp;quot;)&lt;br /&gt;
    new keys = MENU_KEY_0|MENU_KEY_1|MENU_KEY_2&lt;br /&gt;
    register_menucmd(register_menuid(&amp;quot;Which Weapon?&amp;quot;), keys, &amp;quot;giveWeapon&amp;quot;)&lt;br /&gt;
    //flags - b means &amp;quot;sent to one target&amp;quot;, e means &amp;quot;target is alive&amp;quot;&lt;br /&gt;
    //this event is sent when a player spawns&lt;br /&gt;
    register_event(&amp;quot;ResetHUD&amp;quot;, &amp;quot;hook_hud&amp;quot;, &amp;quot;be&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public hook_hud(id)&lt;br /&gt;
{&lt;br /&gt;
    //since we specify no parameters to the task,&lt;br /&gt;
    //the task id will be given to the function&lt;br /&gt;
    //this is useful because we can reuse our old&lt;br /&gt;
    //show menu function which takes an id&lt;br /&gt;
    set_task(0.2, &amp;quot;showWeaponMenu&amp;quot;, id)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that we've set a small delay when we receive the message - this is to make sure that the user has had time to respawn. register_event can take more parameters in order to help restrict the event you catch - for example only matching certain parameters. You can read more about this in the function reference.&lt;br /&gt;
&lt;br /&gt;
Now, let's say we want to figure out when a player has died...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    register_plugin(&amp;quot;Message Demo&amp;quot;, &amp;quot;1.0&amp;quot;, &amp;quot;BAILOPAN&amp;quot;)&lt;br /&gt;
    //this message informs everyone of a death, so we use&lt;br /&gt;
    // flag &amp;quot;a&amp;quot; - global event&lt;br /&gt;
    register_event(&amp;quot;DeathMsg&amp;quot;, &amp;quot;hook_death&amp;quot;, &amp;quot;a&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public hook_death()&lt;br /&gt;
{&lt;br /&gt;
    new Killer = read_data(1) //get the first message parameter&lt;br /&gt;
    new Victim = read_data(2) //get the second message parameter&lt;br /&gt;
    new headshot = read_data(3) //was this a headshot?&lt;br /&gt;
    new weapon[32]&lt;br /&gt;
    read_data(4, weapon, 31)  //get the weapon name&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, let's say we want to make a simple function for generating a death message:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;stock make_deathMsg(Killer, Victim, const weapon[])&lt;br /&gt;
{&lt;br /&gt;
    //message_begin starts a message.  NEVER start two messages at once.&lt;br /&gt;
    //MSG_ALL means send the message to everyone&lt;br /&gt;
    //get_user_msgid returns the id of a message name&lt;br /&gt;
    //{0,0,0} is the origin vector - not used here&lt;br /&gt;
    //0 is the target - no specific target here&lt;br /&gt;
    message_begin(MSG_ALL, get_user_msgid(&amp;quot;DeathMsg&amp;quot;), {0,0,0}, 0) &lt;br /&gt;
    write_byte(Killer)&lt;br /&gt;
    write_byte(Victim)&lt;br /&gt;
    write_string(weapon)&lt;br /&gt;
    message_end()&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To find more about messages, consult the HLSDK, AMX Mod X forums, HL-related programming sites, or other plugins. To list the messages a mod has, type &amp;quot;meta game&amp;quot; in the server console (with metamod loaded). You can also use register_message, the more advanced message disection method found in the Engine module.&lt;br /&gt;
&lt;br /&gt;
=Catching Log Messages=&lt;br /&gt;
&lt;br /&gt;
Catching log messages is not used heavily any more, but it's still good to know how to do it. As log messages are sent by the mod, AMX Mod X will be able to catch them and let you hook them. For our example, let's give everyone $16,000 on round start.&lt;br /&gt;
&lt;br /&gt;
The log messages for rounds are sent like this: World triggered &amp;quot;Round_Start&amp;quot;. AMX Mod X will consider &amp;quot;World_triggered&amp;quot; as the first parameter and &amp;quot;Round_Start&amp;quot; as the second parameter. So:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    register_plugin(&amp;quot;Log Demo&amp;quot;, &amp;quot;1.0&amp;quot;, &amp;quot;BAILOPAN&amp;quot;)&lt;br /&gt;
    //this will filter for two parameters&lt;br /&gt;
    //roundstart is the public function&lt;br /&gt;
    register_logevent(&amp;quot;roundstart&amp;quot;, 2, &amp;quot;0=World triggered&amp;quot;, &amp;quot;1=Round_Start&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public roundstart()&lt;br /&gt;
{&lt;br /&gt;
    //set a small delay to make sure everyone spawns&lt;br /&gt;
    set_task(1.0, &amp;quot;roundDelay&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public roundDelay(taskId)&lt;br /&gt;
{&lt;br /&gt;
    new players[32], num&lt;br /&gt;
    get_players(players, num)&lt;br /&gt;
    new i&lt;br /&gt;
    for (i=0; i&amp;lt;num; i  )&lt;br /&gt;
    {&lt;br /&gt;
         cs_set_user_money(players[i], 16000)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also read specific log parameters with read_logdata(), which can only be used inside the &amp;quot;plugin_log()&amp;quot; forward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//receives all log messages&lt;br /&gt;
public plugin_log()&lt;br /&gt;
{&lt;br /&gt;
    new data[32]&lt;br /&gt;
    read_logdata(data, 31)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Multi-Lingual Support=&lt;br /&gt;
&lt;br /&gt;
Adding multi-lingual support to a plugin can be difficult, but it's usually worth it if you have clients who are willing to translate your strings into their native language.&lt;br /&gt;
&lt;br /&gt;
The first step is to identify what needs to be translated. Say you have a call like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new score = get_score()&lt;br /&gt;
client_print(id, print_chat, &amp;quot;[AMXX] Your score is %d&amp;quot;, score)&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a good candidate for being multi-lingual. First, create a .txt file (preferrably named after your plugin) and store it in addons\amxmodx\data\lang\. Let's use &amp;quot;myplugin.txt&amp;quot; for the example. For each language, add an entry to the file. Entries are set up as 'keys', which are matched to 'translation strings'. Observe:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;(addons\amxmodx\data\lang\myplugin.txt)&lt;br /&gt;
&lt;br /&gt;
[en]&lt;br /&gt;
SCORE_MSG = Your score is %d&lt;br /&gt;
&lt;br /&gt;
[de]&lt;br /&gt;
SCORE_MSG = Ihr Spielergebnis ist %d&lt;br /&gt;
&lt;br /&gt;
[es]&lt;br /&gt;
SCORE_MSG = Su cuenta es %d&lt;br /&gt;
&lt;br /&gt;
[fr]&lt;br /&gt;
SCORE_MSG = Votre score est %d&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, in plugin_init(), you must register the language keys:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    ...&lt;br /&gt;
    //assumes placed in amxmodx\data\lang&lt;br /&gt;
    register_dictionary(&amp;quot;myplugin.txt&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, here comes the hard part. AMX Mod X's Multi-Lingual API is built into the format() style routines. For anything that looks like or uses format()-style strings, you can use the ML API.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;    client_print(id, print_chat, &amp;quot;[AMXX] %L&amp;quot;, id, &amp;quot;SCORE_MSG&amp;quot;, get_score())&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Let's break this down. For each %L that appears, we need at least two parameters. The first parameter is the TARGET. This must be a player id, LANG_SERVER (meaning show in the server's native language), or LANG_PLAYER. LANG_PLAYER is a special modifier that should only be used when sending a message to all players - it means &amp;quot;show in every player's native language&amp;quot;. The second parameter is the key string that identifies the language phrase to translate. Lastly, if the translated string requires any parameters itself (ours needs %d, one integer), that must be added as well.&lt;br /&gt;
&lt;br /&gt;
You can get very complicated designs with this, but it's recommended that you keep things simple for clarity. Here is a final example using a global message to all players, assuming the key HELLO is properly translated in all the languages available:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;    client_print(0, print_chat, &amp;quot;[AMXX] %L&amp;quot;, LANG_PLAYER, &amp;quot;HELLO&amp;quot;)&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=SQL Support=&lt;br /&gt;
&lt;br /&gt;
SQL support has greatly improved in AMX Mod X. There is a common set of natives that work with a single driver, so as long as one (and only one) SQL module is loaded, the SQL (or DBI) natives will work. Here is a short primer on how to use the DBI natives:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//Create a connection&lt;br /&gt;
	new Sql:mysql = dbi_connect(&amp;quot;localhost&amp;quot;, &amp;quot;dvander&amp;quot;, &amp;quot;pass&amp;quot;, &amp;quot;dbase&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
//If the connection is less than 1, it is bad	&lt;br /&gt;
	if (mysql &amp;lt; SQL_OK) {&lt;br /&gt;
		new err[255]&lt;br /&gt;
		new errNum = dbi_error(mysql, err, 254)&lt;br /&gt;
		server_print(&amp;quot;error1: %s|%d&amp;quot;, err, errNum)&lt;br /&gt;
		return 1&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	server_print(&amp;quot;Connection handle: %d&amp;quot;, mysql)&lt;br /&gt;
//Run a query&lt;br /&gt;
	new Result:ret = dbi_query(mysql, &amp;quot;INSERT INTO config (keyname, val) VALUES ('amx', 'yes')&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
//If the query is less than RESULT_NONE, it failed	&lt;br /&gt;
	if (ret &amp;lt; RESULT_NONE) {&lt;br /&gt;
		new err[255]&lt;br /&gt;
		new errNum = dbi_error(mysql, err, 254)&lt;br /&gt;
		server_print(&amp;quot;error2: %s|%d&amp;quot;, err, errNum)&lt;br /&gt;
		return 1&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
//Do a select query	&lt;br /&gt;
	new Result:res = dbi_query(mysql, &amp;quot;SELECT * FROM config&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
//If the query is less than or equal to RESULT_FAILED, you got an invalid result and can't do anything with it.&lt;br /&gt;
	if (res &amp;lt;= RESULT_FAILED) {&lt;br /&gt;
		new err[255]&lt;br /&gt;
		new errNum = dbi_error(mysql, err, 254)&lt;br /&gt;
		server_print(&amp;quot;error3: %s|%d&amp;quot;, err, errNum)&lt;br /&gt;
		return 1&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	server_print(&amp;quot;Result handle: %d&amp;quot;, res)&lt;br /&gt;
&lt;br /&gt;
//Loop through the result set	&lt;br /&gt;
	while (res&lt;/div&gt;</summary>
		<author><name>Cj2At1</name></author>
		
	</entry>
</feed>