<?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=Shooting+King</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=Shooting+King"/>
	<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/Special:Contributions/Shooting_King"/>
	<updated>2026-04-19T10:18:28Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.6</generator>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMX_Mod_X_1.9_API_Changes&amp;diff=11239</id>
		<title>AMX Mod X 1.9 API Changes</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMX_Mod_X_1.9_API_Changes&amp;diff=11239"/>
		<updated>2021-09-30T19:21:27Z</updated>

		<summary type="html">&lt;p&gt;Shooting King: Assign an Amxmodx category&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{alert|info|&amp;lt;span style&amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt;&amp;quot;vertical-align: super;&amp;quot;&amp;gt;[[File:Ambox_content_soft.svg|35px]]&amp;lt;/span&amp;gt;{{ns|2}}{{resize|200%|This version is not yet released. The release notes are not final.}}|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|These are just the API changes from AMX Mod X 1.8.2 to AMX Mod X 1.9. Click here for the full [[AMX Mod X 1.9 Release Notes]].|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Hint:|This page includes hidden examples or API reference that you can toggle with {{tt|{{hidden|id=hint|labelonly=yes}}}}.|opt=full-border}}&lt;br /&gt;
{{hidden|id=hint|contentonly=yes|content=🙌 Congratulations for understanding the hint!{{margin|10px|}}}}&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
A large part of the scripting documentation has been improved and an online version with searching capability can be found at https://amxmodx.org/api/.&lt;br /&gt;
&lt;br /&gt;
== Gamedata ==&lt;br /&gt;
&lt;br /&gt;
As stated in the Release Notes, we have now gamedata files to avoid to hard code data related to the game or engine. Such files located in the {{tt|amxmodx/data/gamedata/}} directory.&lt;br /&gt;
&lt;br /&gt;
Gamedata files shipped with AMX Mod X can and will be updated at any time, therefore it is strongly discouraged to edit them manually.&amp;lt;br /&amp;gt;&lt;br /&gt;
To make custom gamedata changes, please use the {{tt|custom}} folder under the {{tt|gamedata}} directory. All files under this directory are parsed (in an undefined order) after the main files are loaded. They will never be overwritten.&lt;br /&gt;
&lt;br /&gt;
The files structure is currently arranged this way:&lt;br /&gt;
&lt;br /&gt;
{{tt|&lt;br /&gt;
├─ '''common.games'''&lt;br /&gt;
│  ├─ entities.games&lt;br /&gt;
│  │  └─ ''$mod''&lt;br /&gt;
│  │	 ├─ offsets-''$class''.txt&lt;br /&gt;
│  │	 ├─ ...&lt;br /&gt;
│  ├─ gamerules.games&lt;br /&gt;
│  │  └─ ''$mod''&lt;br /&gt;
│  │	 ├─ offsets-''$class''.txt&lt;br /&gt;
│  │	 ├─ ...&lt;br /&gt;
│  ├─ hostages.games&lt;br /&gt;
│  │  └─ ''$mod''&lt;br /&gt;
│  │	 ├─ offsets-''$class''.txt&lt;br /&gt;
│  │	 ├─ ...&lt;br /&gt;
│  ├─ others.games&lt;br /&gt;
│  │  └─ ''$mod''&lt;br /&gt;
│  │	 ├─ offsets-''$class''.txt&lt;br /&gt;
│  │	 ├─ ...&lt;br /&gt;
│  ├─ functions.engine.txt&lt;br /&gt;
│  ├─ globalvars.engine.txt&lt;br /&gt;
│  └─ {{color|#006699|master.games.txt}}&lt;br /&gt;
├─ '''modules.games'''&lt;br /&gt;
│  ├─ {{color|#006699|master.games.txt}}&lt;br /&gt;
│  └─ game.cstrike.txt&lt;br /&gt;
|bgcolor=white}}&lt;br /&gt;
 &lt;br /&gt;
The main directories are:&lt;br /&gt;
* {{tt|'''common.games'''|bgcolor=white}} contains the shared data.&lt;br /&gt;
* {{tt|'''modules.games'''|bgcolor=white}} contains the data per module.&lt;br /&gt;
&lt;br /&gt;
In those directories, you will find:&lt;br /&gt;
* {{tt|{{color|#006699|master.games.txt|bgcolor=white}}|bgcolor=white}} which references all the files to be loaded by the core/modules.&lt;br /&gt;
&lt;br /&gt;
Inside {{tt|'''common.games'''|bgcolor=white}} directory:&lt;br /&gt;
* {{tt|entities.games|bgcolor=white}}, {{tt|entities.games|bgcolor=white}}, {{tt|entities.games|bgcolor=white}} and {{tt|others.games|bgcolor=white}} directories contains the ''$class'' member's offset per-''$mod''. Related to gamerules object but also player, hostage, item and weapons entities.&lt;br /&gt;
* {{tt|functions.engine.txt|bgcolor=white}} contains the symbols/signatures of functions in the engine.&lt;br /&gt;
* {{tt|globalvars.engine.txt|bgcolor=white}} contains the symbols/signatures of global variables in the engine.&lt;br /&gt;
&lt;br /&gt;
Inside {{tt|'''modules.games'''|bgcolor=white}} directory:&lt;br /&gt;
* {{tt|game.cstrike.txt|bgcolor=white}} contains CS-specific data such as the symbol/signatures of functions and others static datas. &lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|More details about the file format can be found in the Quick Guide in [[#Game_Config_Parser]].|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
== Compiler ==&lt;br /&gt;
&lt;br /&gt;
Along a bunch of fixed issues, there are some improvements/features worth to be noted.&lt;br /&gt;
&lt;br /&gt;
=== Emscripten support ===&lt;br /&gt;
&lt;br /&gt;
The AMX Mod X Compiler can now be compiled with [https://kripken.github.io/emscripten-site/ Emscripten] allowing it to run inside of a web browser.&lt;br /&gt;
&lt;br /&gt;
A good example is [https://spider.limetech.io/ Spider], a web-based, entirely client-side, editor and compiler for [Source]Pawn development (by {{user|59029|asherkin}}).&lt;br /&gt;
&lt;br /&gt;
=== Increased Limits ===&lt;br /&gt;
&lt;br /&gt;
Name/function and input line maximum length (in characters) have been increased.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Old value&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | New value&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | Name/Function&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|31|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|63|bgcolor=white}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | Input Line&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|511|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|4095|bgcolor=white}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Predefined Constants ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Global&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|__BINARY__|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | Name of the compiled plugin. Example: {{tt|admin.amxx|bgcolor=none}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|__FILE__|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | Name of the source plugin. Custom includes is supported. Example: {{tt|admin.sma|bgcolor=none}}, {{tt|myinclude/myfile.inc|bgcolor=none}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|__LINE__|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | Current line from the plugin's source code.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|Values are populated at compile time.|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
=== Pragma ===&lt;br /&gt;
&lt;br /&gt;
A new {{tt|&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;pragma deprecated}} has been added to tell the compiler that this specific {{tt|native|bgcolor=none}}/{{tt|stock|bgcolor=none}} is deprecated. &amp;lt;br /&amp;gt;&lt;br /&gt;
This will issue a warning upon the compilation.&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=pragma_example|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=pragma_example|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#pragma deprecated  Some comment here.&lt;br /&gt;
native foo();&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At compilation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
[...] warning 233: symbol &amp;quot;foo&amp;quot; is marked as deprecated: Some comment here.&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== String Literal Contatenation ===&lt;br /&gt;
&lt;br /&gt;
This basically allows you to concatenate literal strings and stringizing a parameter in macro substitution ''only'' (so possible breakage is very limited).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Symbol&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | To concatenate&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|+|bgcolor=white}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | To Stringize&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;|bgcolor=white}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=concat_example|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=concat_example|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#define PROJECT_AUTHOR    &amp;quot;AMX Mod X&amp;quot;&lt;br /&gt;
#define PROJECT_COPYRIGHT &amp;quot;Copyright (C) 2017  &amp;quot; + PROJECT_AUTHOR&lt;br /&gt;
&lt;br /&gt;
#define VERSION_MAJOR      &amp;quot;1&amp;quot;&lt;br /&gt;
#define VERSION_MINOR      &amp;quot;9&amp;quot;&lt;br /&gt;
#define VERSION_RELEASE    &amp;quot;0&amp;quot;&lt;br /&gt;
#define VERSION            VERSION_MAJOR + &amp;quot;.&amp;quot; + VERSION_MINOR + &amp;quot;.&amp;quot; + VERSION_RELEASE&lt;br /&gt;
&lt;br /&gt;
#define log(%1)  &amp;quot;logging: &amp;quot; + #%1 + &amp;quot;\n&amp;quot;&lt;br /&gt;
&lt;br /&gt;
foo()&lt;br /&gt;
{&lt;br /&gt;
    server_print(log(hello));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Internal Core Changes ==&lt;br /&gt;
&lt;br /&gt;
=== String Buffer ===&lt;br /&gt;
&lt;br /&gt;
The buffer size AMX Mod X uses internally to retrieve strings has been increased from {{tt|3k}} to {{tt|16k}}.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|A {{tt|MAX_STRING_LENGTH}} define has been added in {{tt|amxconst.inc}}.|opt=full-border}}&lt;br /&gt;
{{alert|info|Note:|By default plugins don't have enough memory available to allocate an array of this size.&amp;lt;br /&amp;gt;You probably should not use this define to actually declare a buffer unless you ''absolutely'' have to.&amp;lt;br /&amp;gt;Look at {{tt|&amp;lt;nowiki&amp;gt;#pragma dynamic&amp;lt;/nowiki&amp;gt;}} to increase a plugins available memory.|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
== New Core APIs ==&lt;br /&gt;
&lt;br /&gt;
=== Automatic Config File ===&lt;br /&gt;
&lt;br /&gt;
This provides a system for plugins to automatically generate config files with plugin's cvars which get executed on load. &amp;lt;br /&amp;gt;&lt;br /&gt;
This is done via the {{tt|AutoExecConfig}} native.&lt;br /&gt;
&lt;br /&gt;
Once all configuration files are executed, {{tt|OnConfigsExecuted}} is called. This forward will always be called, even if your plugin had no configs or if it was loaded late.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 ! Native&lt;br /&gt;
 ! Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|AutoExecConfig|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=AutoExecConfig|header=Specifies that the given config file should be executed after plugin load.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=AutoExecConfig|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Specifies that the given config file should be executed after plugin load.&lt;br /&gt;
 *&lt;br /&gt;
 * @note OnConfigsExecuted() will not be called until the config file has executed,&lt;br /&gt;
 *       but it will be called if the execution fails.&lt;br /&gt;
 * @note The name parameter should not contain dots, otherwise file will not be executed.&lt;br /&gt;
 *&lt;br /&gt;
 * @param autoCreate    If true, and the config file does not exist, such a config&lt;br /&gt;
 *                      file will be automatically created and populated with&lt;br /&gt;
 *                      information from the plugin's registered cvars.&lt;br /&gt;
 * @param name          Name of the config file, excluding the .cfg extension.&lt;br /&gt;
 *                      If empty, &amp;lt;plugin.filename.cfg&amp;gt; is assumed.&lt;br /&gt;
 * @param folder        Folder under plugins/ to use.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native AutoExecConfig(bool:autoCreate = true, const name[] = &amp;quot;&amp;quot;, const folder[] = &amp;quot;&amp;quot;);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 ! Forward&lt;br /&gt;
 ! Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|OnConfigsExecuted|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=OnConfigsExecuted|header=Called when the map has loaded, and all configs are done executing.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=OnConfigsExecuted|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Called when the map has loaded, and all configs are done executing.&lt;br /&gt;
 * This includes servercfgfile (server.cfg), amxx.cfg, plugin's config, and&lt;br /&gt;
 * per-map config.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This is best place to initialize plugin functions which are based on cvar data.&lt;br /&gt;
 * @note This will always be called once and only once per map.  It will be&lt;br /&gt;
 *       called few seconds after plugin_cfg().&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
forward OnConfigsExecuted();&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|OnAutoConfigsBuffered|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=OnAutoConfigsBuffered|header=Called when the map has loaded, right after {{tt|plugin_cfg}} but any time before {{tt|OnConfigsExecuted}}.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=OnAutoConfigsBuffered|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Called when the map has loaded, right after plugin_cfg() but any time&lt;br /&gt;
 * before OnConfigsExecuted.  It's called after amxx.cfg and  all&lt;br /&gt;
 * AutoExecConfig() exec commands have been added to the server command buffer.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This will always be called once and only once per map.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
forward OnAutoConfigsBuffered();&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=autoexecconfig_example|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=autoexecconfig_example|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&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;Hat&amp;quot;, &amp;quot;User&amp;quot;, &amp;quot;1.0&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    create_cvar(&amp;quot;mysqlk_database&amp;quot;, &amp;quot;&amp;quot;, .description = &amp;quot;MySQL database&amp;quot;);&lt;br /&gt;
    create_cvar(&amp;quot;mysqlk_host&amp;quot;, &amp;quot;localhost&amp;quot;, .description = &amp;quot;MySQL host, use this to configure various^nthings for your server.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    AutoExecConfig();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That would export a config file that looks like this:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
// This file was auto-generated by AMX Mod X (v1.9)&lt;br /&gt;
// Cvars for plugin &amp;quot;Hat&amp;quot; by &amp;quot;User&amp;quot; (hat.amxx, v1.0)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// MySQL database&lt;br /&gt;
// -&lt;br /&gt;
// Default: &amp;quot;&amp;quot;&lt;br /&gt;
mysqlk_database &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// MySQL host, use this to configure various&lt;br /&gt;
// things for your server.&lt;br /&gt;
// -&lt;br /&gt;
// Default: &amp;quot;localhost&amp;quot;&lt;br /&gt;
mysqlk_host &amp;quot;localhost&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== DataPack ===&lt;br /&gt;
&lt;br /&gt;
This offers you a way to dynamically store and move around various types of data.&lt;br /&gt;
&lt;br /&gt;
Datapacks provide a way to store and move around arbitrary amounts (and types) of data in AMX Mox X, available from {{tt|datapack.inc}}.&amp;lt;br /&amp;gt;&lt;br /&gt;
Data is packed into a single cell value - the {{tt|DataPack}} handle. This handle can be passed around more easily, can be returned by functions and can simulate advanced concepts like string consummation.&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align: center; background-color: white;&amp;quot; colspan=&amp;quot;2&amp;quot; | {{color|steelblue|Creating &amp;amp; Disposing}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|CreateDataPack|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=CreateDataPack|header=Creates a new datapack.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Creates a new datapack.&lt;br /&gt;
 *&lt;br /&gt;
 * @return  New datapack handle, which must be freed via DestroyDataPack().&lt;br /&gt;
 */&lt;br /&gt;
native DataPack:CreateDataPack();&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|DestroyDataPack|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=DestroyDataPack|header=Destroys the datapack and frees its memory.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Destroys the datapack and frees its memory.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pack      Datapack handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return          True if disposed, false otherwise&lt;br /&gt;
 */&lt;br /&gt;
native DestroyDataPack(&amp;amp;DataPack:pack);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align: center; background-color: white;&amp;quot; colspan=&amp;quot;2&amp;quot; | {{color|steelblue|Resetting}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|ResetPack|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=ResetPack|header=Resets the datapack read/write position to the start.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Resets the datapack read/write position to the start.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pack      Datapack handle&lt;br /&gt;
 * @param clear     If true, clears the contained data&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid handle is provided, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native ResetPack(DataPack:pack, bool:clear = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align: center; background-color: white;&amp;quot; colspan=&amp;quot;2&amp;quot; | {{color|steelblue|Writing data}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|WritePackCell|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=WritePackCell|header=Packs a cell value into a datapack.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Packs a cell value into a datapack.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pack      Datapack handle&lt;br /&gt;
 * @param cell      Cell value to pack&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid handle is provided, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native WritePackCell(DataPack:pack, any:cell);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|WritePackFloat|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=WritePackFloat|header=Packs a float value into a datapack.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Packs a float value into a datapack.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pack      Datapack handle&lt;br /&gt;
 * @param val       Float value to pack&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid handle is provided, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native WritePackFloat(DataPack:pack, Float:val);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|WritePackString|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=WritePackString|header=Packs a string into a datapack.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Packs a string into a datapack.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pack      Datapack handle&lt;br /&gt;
 * @param str       String to pack&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Length of copied string&lt;br /&gt;
 * @error           If an invalid handle is provided, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native WritePackString(DataPack:pack, const str[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align: center; background-color: white;&amp;quot; colspan=&amp;quot;2&amp;quot; | {{color|steelblue|Reading data}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|ReadPackCell|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=ReadPackCell|header=Reads a cell from a Datapack.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Reads a cell from a Datapack.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pack      Datapack handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Cell value&lt;br /&gt;
 * @error           If an invalid handle is provided, or not enough data is left&lt;br /&gt;
 *                  in the datapack, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native any:ReadPackCell(DataPack:pack);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|ReadPackFloat|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=ReadPackFloat|header=Reads a float from a Datapack.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Reads a float from a datapack.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pack      Datapack handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Float value&lt;br /&gt;
 * @error           If an invalid handle is provided, or not enough data is left&lt;br /&gt;
 *                  in the datapack, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native Float:ReadPackFloat(DataPack:pack);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|ReadPackString|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=ReadPackString|header=Reads a string from a Datapack.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Reads a string from a Datapack.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pack      Datapack handle&lt;br /&gt;
 * @param buffer    Buffer to copy string to&lt;br /&gt;
 * @param maxlen    Maximum size of buffer&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Number of cells written to buffer&lt;br /&gt;
 * @error           If an invalid handle is provided, or not enough data is left&lt;br /&gt;
 *                  in the datapack, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native ReadPackString(DataPack:pack, buffer[], maxlen);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align: center; background-color: white;&amp;quot; colspan=&amp;quot;2&amp;quot; | {{color|steelblue|Managing position}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|GetPackPosition|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=GetPackPosition|header=Returns the datapack read/write position.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns the datapack read/write position.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pack      Datapack handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Position in the datapack, only usable with calls to SetPackPosition&lt;br /&gt;
 * @error           If an invalid handle is provided, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native DataPackPos:GetPackPosition(DataPack:pack);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|SetPackPosition|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=SetPackPosition|header=Sets the datapack read/write position.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets the datapack read/write position.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This should only ever be used with (known to be valid) positions&lt;br /&gt;
 *       returned by GetPackPosition(). It is not possible for plugins to safely&lt;br /&gt;
 *       compute datapack positions.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pack      Datapack handle&lt;br /&gt;
 * @param position  New position to set&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid handle is provided, or the new position is&lt;br /&gt;
 *                  out of datapack bounds, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native SetPackPosition(DataPack:pack, DataPackPos:position);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=datapack_example|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=datapack_example|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    // Creating&lt;br /&gt;
    new const DataPack:pack = CreateDataPack();&lt;br /&gt;
&lt;br /&gt;
    // Writing&lt;br /&gt;
    WritePackCell(pack, refCell);&lt;br /&gt;
    WritePackFloat(pack, refFloat);&lt;br /&gt;
    WritePackString(pack, refString);&lt;br /&gt;
&lt;br /&gt;
    // Reset before reading&lt;br /&gt;
    ResetPack(pack);&lt;br /&gt;
    server_print(&amp;quot;Datapack is readable: %s&amp;quot;, !IsPackEnded(pack) ? &amp;quot;yes&amp;quot; : &amp;quot;no&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    // Reading&lt;br /&gt;
    new cellValue = ReadPackCell(pack);&lt;br /&gt;
    new Float:floatValue = ReadPackFloat(pack);&lt;br /&gt;
    new buffer[32];&lt;br /&gt;
    ReadPackString(pack, buffer, charsmax(buffer));&lt;br /&gt;
    server_print(&amp;quot;cellValue = %d, floatValue = %f, buffer = %s&amp;quot;, cellValue, floatValue, buffer)&lt;br /&gt;
    server_print(&amp;quot;Datapack is no more readable: %s&amp;quot;, IsPackEnded(pack) ? &amp;quot;yes&amp;quot; : &amp;quot;no&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    // Clear all data&lt;br /&gt;
    ResetPack(pack, .clear = true);&lt;br /&gt;
    server_print(&amp;quot;Datapack is empty: %s&amp;quot;, IsPackEnded(pack) ? &amp;quot;yes&amp;quot; : &amp;quot;no&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    // Disposing&lt;br /&gt;
    DestroyDataPack(pack);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Game Config Parser ===&lt;br /&gt;
&lt;br /&gt;
Now we have gamedata files, we strongly encourage any plugins which hardcode static game datas to use the following API.&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align: center; background-color: white;&amp;quot; colspan=&amp;quot;2&amp;quot; | {{color|steelblue|Loading &amp;amp; Closing file}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|LoadGameConfigFile|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=LoadGameConfigFile|header=Loads a game config file.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Loads a game config file.&lt;br /&gt;
 *&lt;br /&gt;
 * @note The file path must be relative to the 'gamedata' folder under the data folder&lt;br /&gt;
 *       and the extension should be omitted.&lt;br /&gt;
 *&lt;br /&gt;
 * @param file          File to load&lt;br /&gt;
 *&lt;br /&gt;
 * @return              A handle to the game config file&lt;br /&gt;
 */&lt;br /&gt;
native GameConfig:LoadGameConfigFile(const file[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|CloseGameConfigFile|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=CloseGameConfigFile|header=Destroys a game config and frees its memory.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Destroys a game config and frees its memory.&lt;br /&gt;
 *&lt;br /&gt;
 * @note The function automatically sets the variable passed to it to 0 to aid&lt;br /&gt;
 *       in preventing accidental usage after destroy.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        Game config handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return              1 on success, 0 if an invalid handle was passed in&lt;br /&gt;
 */&lt;br /&gt;
native CloseGameConfigFile(&amp;amp;GameConfig:handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align: center; background-color: white;&amp;quot; colspan=&amp;quot;2&amp;quot; | {{color|steelblue|Getting value}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|GameConfGetOffset|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=GameConfGetOffset|header=Returns an offset value.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 *&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        Game config handle&lt;br /&gt;
 * @param key           Key to retrieve from the offset section&lt;br /&gt;
 *&lt;br /&gt;
 * @return              An offset, or -1 on failure&lt;br /&gt;
 * @error               Invalid game config handle&lt;br /&gt;
 */&lt;br /&gt;
native GameConfGetOffset(GameConfig:handle, const key[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|GameConfGetClassOffset|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=GameConfGetClassOffset|header=Returns an offset value given a classname.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns an offset value given a classname.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        Game config handle&lt;br /&gt;
 * @param classname     Class name to match from the offset section&lt;br /&gt;
 * @param key           Key to retrieve from the offset section&lt;br /&gt;
 *&lt;br /&gt;
 * @return              An offset, or -1 on failure&lt;br /&gt;
 * @error               Invalid game config handle&lt;br /&gt;
 */&lt;br /&gt;
native GameConfGetClassOffset(GameConfig:handle, const classname[], const key[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|GameConfGetKeyValue|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=GameConfGetKeyValue|header=Gets the value of a key from the &amp;quot;Keys&amp;quot; section.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets the value of a key from the &amp;quot;Keys&amp;quot; section.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        Game config handle&lt;br /&gt;
 * @param key           Key to retrieve from the Keys section&lt;br /&gt;
 * @param buffer        Destination string buffer&lt;br /&gt;
 * @param maxlen        Maximum length of output string buffer&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True if key existed, false otherwise&lt;br /&gt;
 * @error               Invalid game config handle&lt;br /&gt;
 */&lt;br /&gt;
native bool:GameConfGetKeyValue(GameConfig:handle, const key[], buffer[], maxlen);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|GameConfGetAddress|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=GameConfGetAddress|header=Finds an address calculation in a GameConfig file.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Finds an address calculation in a GameConfig file.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        Game config handle&lt;br /&gt;
 * @param name          Name of the property to find&lt;br /&gt;
 *&lt;br /&gt;
 * @return              An address calculated on success, otherwise 0 on failure.&lt;br /&gt;
 * @error               Invalid game config handle&lt;br /&gt;
 */&lt;br /&gt;
native GameConfGetAddress(GameConfig:handle, const name[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Quick guide:|{{hidden|id=gameconfguide|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=gameconfguide|contentonly=yes|content=&lt;br /&gt;
&lt;br /&gt;
{{color|steelblue|'''Config location'''}}&lt;br /&gt;
&lt;br /&gt;
Any default and new gamedata files must be located in {{tt|/amxmodx/data/gamedata/}} directory.&amp;lt;br /&amp;gt;&lt;br /&gt;
You can create your own directories inside as well.&lt;br /&gt;
&lt;br /&gt;
{{color|steelblue|'''Filename format'''}}&lt;br /&gt;
&lt;br /&gt;
The file name must end with {{tt|.txt}} extension, e.g. {{tt|myfile.txt}}&lt;br /&gt;
&lt;br /&gt;
{{color|steelblue|'''Loading a specific file'''}}&lt;br /&gt;
&lt;br /&gt;
The right way to load a file is to provide the filename without {{tt|.txt}} extension.&amp;lt;br /&amp;gt;&lt;br /&gt;
E.g. {{tt|LoadGameConfigFile(&amp;quot;myfile&amp;quot;)}} will try to load {{tt|/data/gamedata/myfile.txt}}.&lt;br /&gt;
&lt;br /&gt;
{{color|steelblue|'''Loading multiple files'''}}&lt;br /&gt;
&lt;br /&gt;
You are able to load several at once via a master file, named {{tt|master.game.txt}}. &amp;lt;br /&amp;gt;&lt;br /&gt;
A master file is basically a way to tell the parser to load any files listed inside and nothing else. &amp;lt;br /&amp;gt;&lt;br /&gt;
You can also specify whether a file should be loaded depending the mod name (such as {{tt|cstrike}}) or engine (dedicated server: {{tt|engine_ds}} or listen server: {{tt|engine_ls}}). &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
├─ gamedata&lt;br /&gt;
│  └─ myfolder&lt;br /&gt;
│	  ├─ myfile1.txt&lt;br /&gt;
│	  ├─ myfile2.txt&lt;br /&gt;
│	  ├─ myfile3.txt&lt;br /&gt;
│	  └─ master.game.txt&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{tt|master.game.txt}}:&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
&amp;quot;Game Master&amp;quot;           // Must start with this.&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;myfile1.txt&amp;quot;       // No option, will be loaded all the time&lt;br /&gt;
    {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    &amp;quot;myfile2.txt&amp;quot;       // Will be loaded for both servers&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;engine&amp;quot;  &amp;quot;engine_ds&amp;quot;&lt;br /&gt;
        &amp;quot;engine&amp;quot;  &amp;quot;engine_ls&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    &amp;quot;myfile3.txt&amp;quot;       // Will be loaded only if the mod is Counter-Strike.&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;game&amp;quot;  &amp;quot;cstrike&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then to load, you only need to provide your directory, e.g. {{tt|LoadGameConfigFile(&amp;quot;myfolder&amp;quot;)}}. &amp;lt;br /&amp;gt;&lt;br /&gt;
This will looks at the {{tt|/gamedata/myfolder/master.game.txt}} file and will load the listed files from there.&lt;br /&gt;
&lt;br /&gt;
{{color|darkblue|'''Config file format'''}}&lt;br /&gt;
&lt;br /&gt;
The config file has a specific format as well.&lt;br /&gt;
This must to start with:&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
&amp;quot;Games&amp;quot;&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you need to tell on what game the date will be loaded.&amp;lt;br /&amp;gt;&lt;br /&gt;
There are different values:&lt;br /&gt;
* {{tt|&amp;quot;&amp;lt;game name&amp;gt;&amp;quot;}}, such as {{tt|cstrike}}&lt;br /&gt;
* {{tt|&amp;quot;*&amp;quot;}} or {{tt|&amp;quot;#default&amp;quot;}} to match any game&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
&amp;quot;Games&amp;quot;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;cstrike&amp;quot;&lt;br /&gt;
    {&lt;br /&gt;
        // Counter-Strike only&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    &amp;quot;#default&amp;quot;&lt;br /&gt;
    {&lt;br /&gt;
        // Any game&lt;br /&gt;
        // Note you can create multiple game blocks.&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you need to create a block which inherit multiple games or engine, you can achieve it with {{tt|&amp;lt;nowiki&amp;gt;#supported&amp;lt;/nowiki&amp;gt;}} key.&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
&amp;quot;Games&amp;quot;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;#default&amp;quot;	// Must start with this&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;#supported&amp;quot;&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;game&amp;quot;   &amp;quot;cstrike&amp;quot;&lt;br /&gt;
            &amp;quot;game&amp;quot;   &amp;quot;czero&amp;quot;&lt;br /&gt;
&lt;br /&gt;
            &amp;quot;engine&amp;quot;  &amp;quot;engine_ds&amp;quot;  // you can specify the engine as well.&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
        // Data&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{color|darkblue|'''Data Type'''}}&lt;br /&gt;
&lt;br /&gt;
There are 5 different types of datas that you are allowed to store:&lt;br /&gt;
* ''Signature'':&lt;br /&gt;
: Retrieves an address from either a symbol or bytes. E.g. {{tt|@g_pGameRules}} or {{tt|\xDC\x2A\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x56}}&lt;br /&gt;
: Symbol must start with {{tt|@}}.&lt;br /&gt;
: For use with {{tt|GameConfGetAddress}} native.&lt;br /&gt;
* ''Address'':&lt;br /&gt;
: Reads a value from a given address (usually from signature reference)&lt;br /&gt;
: For use with {{tt|GameConfGetAddress}} native.&lt;br /&gt;
* ''Offset'':&lt;br /&gt;
: A platform-dependent value (windows, linux or mac)&lt;br /&gt;
: For use with {{tt|GameConfGetOffset}} native.&lt;br /&gt;
* ''Class Offset'':&lt;br /&gt;
: Same as Offset but can be grouped into a classname&lt;br /&gt;
: For use with {{tt|GameConfGetClassOffset}} native.&lt;br /&gt;
* ''Keyvalue'':&lt;br /&gt;
: simple key associated to a value.&lt;br /&gt;
: For use with {{tt|GameConfGetKeyValue}} native.&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
&amp;quot;Games&amp;quot;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;#default&amp;quot;&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;Signatures&amp;quot;&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;SV_DropClient&amp;quot;&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;library&amp;quot;   &amp;quot;engine&amp;quot; // This can be either &amp;quot;server&amp;quot; (mod), &amp;quot;engine_ds&amp;quot; (dedicated server) or &amp;quot;engine_ls' (listen server)&lt;br /&gt;
                &amp;quot;windows&amp;quot;   &amp;quot;\x55\x8B\x2A\x81\x2A\x2A\x2A\x2A\x2A\x8B\x2A\x2A\x53\x56\x8D&amp;quot;&lt;br /&gt;
                &amp;quot;linux&amp;quot;     &amp;quot;@SV_DropClient&amp;quot;&lt;br /&gt;
                &amp;quot;mac&amp;quot;       &amp;quot;@SV_DropClient&amp;quot; // Note: A symbol must start always with '@'&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            &amp;quot;g_pGameRules&amp;quot;&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;library&amp;quot;   &amp;quot;server&amp;quot;&lt;br /&gt;
                &amp;quot;windows&amp;quot;   &amp;quot;\x8B\x2A\x2A\x2A\x2A\x2A\x85\x2A\x74\x2A\x8B\x2A\xFF\x2A\x2A\xA1&amp;quot; // StartFrame()&lt;br /&gt;
                &amp;quot;linux&amp;quot;     &amp;quot;@g_pGameRules&amp;quot;&lt;br /&gt;
                &amp;quot;mac&amp;quot;       &amp;quot;@g_pGameRules&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        &amp;quot;Offsets&amp;quot;&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;something&amp;quot;&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;windows&amp;quot;   &amp;quot;4&amp;quot;&lt;br /&gt;
                &amp;quot;linux&amp;quot;     &amp;quot;2&amp;quot;&lt;br /&gt;
                &amp;quot;mac&amp;quot;       &amp;quot;0&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        &amp;quot;Classes&amp;quot;&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;CSomething&amp;quot;&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;Offsets&amp;quot;&lt;br /&gt;
                {&lt;br /&gt;
                    &amp;quot;windows&amp;quot;   &amp;quot;4&amp;quot;&lt;br /&gt;
                    &amp;quot;linux&amp;quot;     &amp;quot;2&amp;quot;&lt;br /&gt;
                    &amp;quot;mac&amp;quot;       &amp;quot;0&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        &amp;quot;Addresses&amp;quot;&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;GameRulesPointer&amp;quot; // Gets the address of &amp;quot;g_pGameRules&amp;quot;, adds 2 bytes on windows and 0 byte on linux/mac.&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;signature&amp;quot;  &amp;quot;g_pGameRules&amp;quot;&lt;br /&gt;
&lt;br /&gt;
                &amp;quot;windows&amp;quot;&lt;br /&gt;
                {&lt;br /&gt;
                    &amp;quot;read&amp;quot;   &amp;quot;2&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                &amp;quot;read&amp;quot;  &amp;quot;0&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            &amp;quot;Something&amp;quot; // Gets the address of &amp;quot;SV_DropClient&amp;quot; and adds 5 bytes, on linux platform only.&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;linux&amp;quot;&lt;br /&gt;
                {&lt;br /&gt;
                    signature &amp;quot;SV_DropClient&amp;quot;&lt;br /&gt;
                    &amp;quot;read&amp;quot;    &amp;quot;5&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        &amp;quot;Keys&amp;quot;&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;key1&amp;quot;   &amp;quot;value1&amp;quot;&lt;br /&gt;
            &amp;quot;Key2&amp;quot;   &amp;quot;value2&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Hasher ===&lt;br /&gt;
&lt;br /&gt;
Supports several new hash types: CRC32, MD5, SHA*, Keccak*.&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|The following API deprecates {{tt|md5}} and {{tt|md5_file}} natives.|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|hash_string|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=hash_string|header=Generates a hash value (message digest).|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Generates a hash value (message digest)&lt;br /&gt;
 *&lt;br /&gt;
 * @param string        String to be hashed.&lt;br /&gt;
 * @param type          Type of selected hashing algorithm. See Hash_* constants in amxconst.inc file.&lt;br /&gt;
 * @param output        Output string to store hash in.&lt;br /&gt;
 * @param outputSize    The maximum size of the output string to store hash in.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Number of written bytes.&lt;br /&gt;
 */&lt;br /&gt;
native hash_string(const string[], const HashType:type, output[], const outputSize);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|hash_file|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=hash_file|header=Generates a hash value using the contents of a given file.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Generates a hash value using the contents of a given file&lt;br /&gt;
 *&lt;br /&gt;
 * @param fileName      Path of file to be hashed.&lt;br /&gt;
 * @param type          Type of selected hashing algorithm. See Hash_* constants in amxconst.inc file.&lt;br /&gt;
 * @param output        Output string to store hash in.&lt;br /&gt;
 * @param outputSize    The maximum size of the output string to store hash in.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Number of written bytes.&lt;br /&gt;
 * @error               If the file couldn't be opened, an error is thrown.&lt;br /&gt;
 */&lt;br /&gt;
native hash_file(const fileName[], const HashType:type, output[], const outputSize);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
The available {{tt|HashType}} constants are:&lt;br /&gt;
&lt;br /&gt;
* {{tt|Hash_Crc32}}&lt;br /&gt;
* {{tt|Hash_Md5}}&lt;br /&gt;
* {{tt|Hash_Sha1}}&lt;br /&gt;
* {{tt|Hash_Sha256}}&lt;br /&gt;
* {{tt|Hash_Sha3_224}}&lt;br /&gt;
* {{tt|Hash_Sha3_256}}&lt;br /&gt;
* {{tt|Hash_Sha3_384}}&lt;br /&gt;
* {{tt|Hash_Sha3_512}}&lt;br /&gt;
* {{tt|Hash_Keccak_224}}&lt;br /&gt;
* {{tt|Hash_Keccak_256}}&lt;br /&gt;
* {{tt|Hash_Keccak_384}}&lt;br /&gt;
* {{tt|Hash_Keccak_512}}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=hasher_example|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=hasher_example|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    new hash1[32];&lt;br /&gt;
    new const message[] = &amp;quot;Hello World!&amp;quot;;&lt;br /&gt;
    new const length = hash_string(message, Hash_Md5, hash1, charsmax(hash1));&lt;br /&gt;
&lt;br /&gt;
    server_print(&amp;quot;hash1 = %s&amp;quot;, hash1);&lt;br /&gt;
&lt;br /&gt;
    new hash2[32];&lt;br /&gt;
    new const fileName[] = &amp;quot;server.cfg&amp;quot;;&lt;br /&gt;
    new const length = hash_file(message, Hash_Md5, hash2, charsmax(hash2));&lt;br /&gt;
&lt;br /&gt;
    server_print(&amp;quot;hash2 = %s&amp;quot;, hash2);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Stack Structure ===&lt;br /&gt;
&lt;br /&gt;
A stack is a LIFO (last in, first out) dynamic vector of of items.&lt;br /&gt;
&lt;br /&gt;
Stacks provide only two operations:&lt;br /&gt;
* Push, adding an item to the top.&lt;br /&gt;
* Pop, removing an item from the top, in reverse-push order.&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|An example is available in the {{tt|testsuite}} directory, see [https://github.com/alliedmodders/amxmodx/blob/master/plugins/testsuite/stacktest.sma stacktest.sma].|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align: center; background-color: white;&amp;quot; colspan=&amp;quot;2&amp;quot; | {{color|steelblue|Creating &amp;amp; Destroying}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|CreateStack|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=CreateStack|header=Creates a stack structure.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Creates a stack structure. A stack is a LIFO (last in, first out) vector of&lt;br /&gt;
 * of items. It has O(1) insertion and O(1) removal.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Stacks provide only two operations: Push (adding an item to the top)&lt;br /&gt;
 * 		 and Pop (remove an item from the top, in reverse-push order).&lt;br /&gt;
 * @note The contents of the stack are uniform; i.e. storing a string and then&lt;br /&gt;
 *       retrieving it as an integer is NOT the same as str_to_num()!&lt;br /&gt;
 * @note The &amp;quot;blocksize&amp;quot; determines how many cells each stack slot has, it can&lt;br /&gt;
 *       not be changed after creation.&lt;br /&gt;
 *&lt;br /&gt;
 * @param blocksize     The number of cells each entry in the stack can hold&lt;br /&gt;
 *&lt;br /&gt;
 * @return              New stack Handle, which must be freed via DestroyStack()&lt;br /&gt;
 * @error               If an invalid blocksize is provided an error will be&lt;br /&gt;
 *                      thrown.&lt;br /&gt;
 */&lt;br /&gt;
native Stack:CreateStack(blocksize = 1);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|DestroyStack|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=DestroyStack|header=Destroys a stack and frees its memory.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Destroys a stack and frees its memory.&lt;br /&gt;
 *&lt;br /&gt;
 * @note The function automatically sets the variable passed to it to 0 to aid&lt;br /&gt;
 *       in preventing accidental usage after destroy.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Stack to destroy&lt;br /&gt;
 *&lt;br /&gt;
 * @return          1 if the Stack was destroyed, 0 if nothing had to be&lt;br /&gt;
 *                  destroyed (invalid handle)&lt;br /&gt;
 */&lt;br /&gt;
native DestroyStack(&amp;amp;Stack:handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align: center; background-color: white;&amp;quot; colspan=&amp;quot;2&amp;quot; | {{color|steelblue|Pushing Data}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|PushStackCell|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=PushStackCell|header=Pushes a value onto the end of the stack, adding a new index.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Pushes a value onto the end of the stack, adding a new index.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This may safely be used even if the stack has a blocksize greater than&lt;br /&gt;
 *       1.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Stack handle&lt;br /&gt;
 * @param value     Value to push&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid handle is provided or the resizing&lt;br /&gt;
 *                  operation runs out of memory, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native PushStackCell(Stack:handle, any:value);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|PushStackString|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=PushStackString|header=Pushes a string onto the end of a stack, truncating it if it is too long.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Pushes a string onto the end of a stack, truncating it if it is too long.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Stack handle&lt;br /&gt;
 * @param value     String to push&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid handle is provided or the resizing&lt;br /&gt;
 *                  operation runs out of memory, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native PushStackString(Stack:handle, const value[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|PushStackArray|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=PushStackArray|header=Pushes an array of cells onto the end of a stack.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Pushes an array of cells onto the end of a stack. The cells are pushed as a&lt;br /&gt;
 * block (i.e. the entire array takes up one stack slot), rather than pushing&lt;br /&gt;
 * each cell individually.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Stack handle&lt;br /&gt;
 * @param values    Block of values to copy&lt;br /&gt;
 * @param size      If not set, the number of elements copied from the array&lt;br /&gt;
 *                  will be equal to the blocksize, if set higher than the&lt;br /&gt;
 *                  blocksize, the operation will be truncated,&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid handle is provided or the resizing&lt;br /&gt;
 *                  operation runs out of memory, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native PushStackArray(Stack:handle, const any:values[], size= -1);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align: center; background-color: white;&amp;quot; colspan=&amp;quot;2&amp;quot; | {{color|steelblue|Poping Data}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|PopStackCell|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=PopStackCell|header=Pops a cell value from a stack.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Pops a cell value from a stack.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Stack handle&lt;br /&gt;
 * @param value     Variable to store the value in&lt;br /&gt;
 * @param block     Optionally specify which block to read from (useful if the&lt;br /&gt;
 *                  blocksize is &amp;gt; 0)&lt;br /&gt;
 * @param asChar    Optionally read as a byte instead of a cell&lt;br /&gt;
 *&lt;br /&gt;
 * @return          True on success, false if the stack is empty.&lt;br /&gt;
 * @error           If an invalid handle, invalid block or invalid byte is&lt;br /&gt;
 *                  provided, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native bool:PopStackCell(Stack:handle, &amp;amp;any:value, block = 0, bool:asChar = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|PopStackString|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=PopStackString|header=Pops a string value from a stack.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Pops a string value from a stack.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        Stack handle&lt;br /&gt;
 * @param buffer        Buffer to copy string to&lt;br /&gt;
 * @param maxlength     Maximum size of the buffer&lt;br /&gt;
 * @param written       Variable to store number of characters copied to&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True on success, false if the stack is empty&lt;br /&gt;
 * @error               If an invalid handle is provided an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native bool:PopStackString(Stack:handle, buffer[], maxlength, &amp;amp;written = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|PopStackArray|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=PopStackArray|header=Pops an array of cells from a stack.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Pops an array of cells from a stack.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Stack handle&lt;br /&gt;
 * @param buffer    Array to copy value to&lt;br /&gt;
 * @param size      Size of buffer, if not set (-1) assumes the size is equal to&lt;br /&gt;
 *                  the stack blocksize&lt;br /&gt;
 *&lt;br /&gt;
 * @return          True on success, false if the stack is empty&lt;br /&gt;
 * @error           If an invalid handle is provided an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native bool:PopStackArray(Stack:handle, any:buffer[], size = -1);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align: center; background-color: white;&amp;quot; colspan=&amp;quot;2&amp;quot; | {{color|steelblue|Others}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|IsStackEmpty|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=IsStackEmpty|header=Returns if a stack is empty.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns if a stack is empty.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Stack handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return          True if empty, false if not empty&lt;br /&gt;
 * @error           If an invalid handle is provided an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native bool:IsStackEmpty(Stack:handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Stock&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|PopStack|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=PopStack|header=Pops a value off a stack, ignoring it completely.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Pops a value off a stack, ignoring it completely.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Stack handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return          True if a value was popped, false if stack is empty&lt;br /&gt;
 * @error           If an invalid handle is provided an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
stock PopStack(Stack:handle)&lt;br /&gt;
{&lt;br /&gt;
    new value;&lt;br /&gt;
    return PopStackCell(handle, value);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Text Parser INI/SMC ===&lt;br /&gt;
&lt;br /&gt;
Event-based text parser to read data in an unified way. It supports INI and SMC (similar to VTF) formats.&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|An example is available in the {{tt|testsuite}} directory, see [https://github.com/alliedmodders/amxmodx/blob/master/plugins/testsuite/textparse_test.sma textparse.sma].|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
'''SMC Format'''&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Technical format detail:|{{hidden|id=smc-format|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=smc-format|contentonly=yes|content=&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * The SMC file format is defined as:&lt;br /&gt;
 *    WHITESPACE: 0x20, \n, \t, \r&lt;br /&gt;
 *    IDENTIFIER: Any ASCII character EXCLUDING &amp;quot;, {, }, ;, //, / *, or WHITESPACE.&lt;br /&gt;
 *    STRING    : Any set of symbols enclosed in quotes.&lt;br /&gt;
 *&lt;br /&gt;
 *    Note: if a STRING does not have quotes, it is parsed as an IDENTIFIER.&lt;br /&gt;
 *&lt;br /&gt;
 * Basic syntax is comprised of SECTIONBLOCKs.&lt;br /&gt;
 *    A SECTIONBLOCK defined as:&lt;br /&gt;
 *&lt;br /&gt;
 *    SECTIONNAME&lt;br /&gt;
 *    {&lt;br /&gt;
 *        OPTION&lt;br /&gt;
 *    }&lt;br /&gt;
 *&lt;br /&gt;
 * OPTION can be repeated any number of times inside a SECTIONBLOCK.&lt;br /&gt;
 * A new line will terminate an OPTION, but there can be more than one OPTION per line.&lt;br /&gt;
 * OPTION is defined any of:&lt;br /&gt;
 *    &amp;quot;KEY&amp;quot;  &amp;quot;VALUE&amp;quot;&lt;br /&gt;
 *    SECTIONBLOCK&lt;br /&gt;
 *&lt;br /&gt;
 * SECTIONNAME, KEY, VALUE, and SINGLEKEY are strings&lt;br /&gt;
 * SECTIONNAME cannot have trailing characters if quoted, but the quotes can be optionally removed.&lt;br /&gt;
 * If SECTIONNAME is not enclosed in quotes, the entire sectionname string is used (minus surrounding whitespace).&lt;br /&gt;
 * If KEY is not enclosed in quotes, the key is terminated at first whitespace.&lt;br /&gt;
 * If VALUE is not properly enclosed in quotes, the entire value string is used (minus surrounding whitespace).&lt;br /&gt;
 * The VALUE may have inner quotes, but the key string may not.&lt;br /&gt;
 *&lt;br /&gt;
 * WHITESPACE should be ignored.&lt;br /&gt;
 * Comments are text occurring inside the following tokens, and should be stripped&lt;br /&gt;
 * unless they are inside literal strings:&lt;br /&gt;
 *    ;&amp;lt;TEXT&amp;gt;&lt;br /&gt;
 *    //&amp;lt;TEXT&amp;gt;&lt;br /&gt;
 *    / *&amp;lt;TEXT&amp;gt; * /&lt;br /&gt;
 *&lt;br /&gt;
 * Example file below:&lt;br /&gt;
 *   &amp;quot;SomeSection&amp;quot;&lt;br /&gt;
 *   {&lt;br /&gt;
 *	      /**&lt;br /&gt;
 *	       * Some comment&lt;br /&gt;
 *         */&lt;br /&gt;
 *	      &amp;quot;Key&amp;quot;		&amp;quot;value&amp;quot;&lt;br /&gt;
 *   }&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 ! Native&lt;br /&gt;
 ! Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|SMC_CreateParser|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=SMC_CreateParser|header=Creates a new SMC parser.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=SMC_CreateParser|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Parser invalid code.&lt;br /&gt;
 */&lt;br /&gt;
enum SMCParser&lt;br /&gt;
{&lt;br /&gt;
    Invalid_SMCParser = 0&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Parse result directive.&lt;br /&gt;
 */&lt;br /&gt;
enum SMCResult&lt;br /&gt;
{&lt;br /&gt;
    SMCParse_Continue,          /* Continue parsing */&lt;br /&gt;
    SMCParse_Halt,              /* Stop parsing here */&lt;br /&gt;
    SMCParse_HaltFail           /* Stop parsing and return failure */&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Creates a new SMC parser.&lt;br /&gt;
 * This is used to set parse hooks.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              A new handle to an SMC Parse structure.&lt;br /&gt;
 */&lt;br /&gt;
native SMCParser:SMC_CreateParser();&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|SMC_DestroyParser|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=SMC_DestroyParser|header=Disposes of an SMC parser.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=SMC_DestroyParser|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Disposes of an SMC parser.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        Handle to an SMC Parse structure.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True if disposed, false otherwise.&lt;br /&gt;
 */&lt;br /&gt;
native SMC_DestroyParser(&amp;amp;SMCParser:handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|SMC_ParseFile|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=SMC_ParseFile|header=Parses a config file.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=SMC_ParseFile|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Parses a config file.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        A handle to an SMC Parse structure.&lt;br /&gt;
 * @param file          A string containing the file path.&lt;br /&gt;
 * @param line          An optional by reference cell to store the last line number read.&lt;br /&gt;
 * @param col           An optional by reference cell to store the last column number read.&lt;br /&gt;
 * @param data          An optional handle or value to pass through to callback functions&lt;br /&gt;
 *&lt;br /&gt;
 * @return              An SMCParseError result.&lt;br /&gt;
 * @error               Invalid or corrupt handle.&lt;br /&gt;
 */&lt;br /&gt;
native SMCError:SMC_ParseFile(SMCParser:handle, const file[], &amp;amp;line = 0, &amp;amp;col = 0, any:data = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Parse error codes.&lt;br /&gt;
 */&lt;br /&gt;
enum SMCError&lt;br /&gt;
{&lt;br /&gt;
    SMCError_Okay = 0,          /* No error */&lt;br /&gt;
    SMCError_StreamOpen,        /* Stream failed to open */&lt;br /&gt;
    SMCError_StreamError,       /* The stream died... somehow */&lt;br /&gt;
    SMCError_Custom,            /* A custom handler threw an error */&lt;br /&gt;
    SMCError_InvalidSection1,   /* A section was declared without quotes, and had extra tokens */&lt;br /&gt;
    SMCError_InvalidSection2,   /* A section was declared without any header */&lt;br /&gt;
    SMCError_InvalidSection3,   /* A section ending was declared with too many unknown tokens */&lt;br /&gt;
    SMCError_InvalidSection4,   /* A section ending has no matching beginning */&lt;br /&gt;
    SMCError_InvalidSection5,   /* A section beginning has no matching ending */&lt;br /&gt;
    SMCError_InvalidTokens,     /* There were too many unidentifiable strings on one line */&lt;br /&gt;
    SMCError_TokenOverflow,     /* The token buffer overflowed */&lt;br /&gt;
    SMCError_InvalidProperty1,  /* A property was declared outside of any section */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|SMC_SetParseStart|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=SMC_SetParseStart|header=Sets the SMC_ParseStart function of a parse handle.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=SMC_SetParseStart|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets the SMC_ParseStart function of a parse handle.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  Below is the prototype of callback:&lt;br /&gt;
 *        -&lt;br /&gt;
 *          Called when parsing is started.&lt;br /&gt;
 *&lt;br /&gt;
 *          @param handle        Handle to an SMC Parse structure.&lt;br /&gt;
 *          @param data          Handle or value passed in SMC_ParseFile&lt;br /&gt;
 *&lt;br /&gt;
 *          @noreturn&lt;br /&gt;
 *&lt;br /&gt;
 *          public OnParseStart(SMCParser:handle, any:data)&lt;br /&gt;
 *        -&lt;br /&gt;
 * @param handle        Handle to an SMC Parse structure.&lt;br /&gt;
 * @param func          A ParseStart callback.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error               Invalid or corrupt handle.&lt;br /&gt;
 */&lt;br /&gt;
native SMC_SetParseStart(SMCParser:handle, const func[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|SMC_SetParseEnd|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=SMC_SetParseEnd|header=Sets the SMC_ParseEnd function of a parse handle.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=SMC_SetParseEnd|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets the SMC_ParseEnd function of a parse handle.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  Below is the prototype of callback:&lt;br /&gt;
 *        -&lt;br /&gt;
 *          Called when parsing is halted.&lt;br /&gt;
 *&lt;br /&gt;
 *          @param handle        Handle to an SMC Parse structure.&lt;br /&gt;
 *          @param halted        True if abnormally halted, false otherwise.&lt;br /&gt;
 *          @param failed        True if parsing failed, false otherwise.&lt;br /&gt;
 *          @param data          Handle or value passed in SMC_ParseFile&lt;br /&gt;
 *&lt;br /&gt;
 *          @noreturn&lt;br /&gt;
 *&lt;br /&gt;
 *          public OnParseEnd(SMCParser:handle, bool:halted, bool:failed, any:data)&lt;br /&gt;
 *        -&lt;br /&gt;
 * @param handle        Handle to an SMC Parse structure.&lt;br /&gt;
 * @param func          A ParseEnd callback.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error               Invalid or corrupt handle.&lt;br /&gt;
 */&lt;br /&gt;
native SMC_SetParseEnd(SMCParser:handle, const func[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|SMC_SetReaders|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=SMC_SetReaders|header=Sets the three main reader functions.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=SMC_SetReaders|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets the three main reader functions.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  Enclosing quotes are always stripped.&lt;br /&gt;
 * @note  Below is the prototype of callbacks:&lt;br /&gt;
 *        -&lt;br /&gt;
 *          NewSection:&lt;br /&gt;
 *              Called when the parser finds a new section or sub-section.&lt;br /&gt;
 *&lt;br /&gt;
 *              @param handle           Handle to an SMC Parse structure.&lt;br /&gt;
 *              @param name             String containing section name.&lt;br /&gt;
 *              @param data             Handle or value passed in SMC_ParseFile&lt;br /&gt;
 *&lt;br /&gt;
 *              @return                 An SMCResult action to take.&lt;br /&gt;
 *&lt;br /&gt;
 *              public SMCResult:OnNewSection(SMCParser:handle, const name[], any:data)&lt;br /&gt;
 *&lt;br /&gt;
 *          KeyValue:&lt;br /&gt;
 *              Called when the parser finds a new key/value pair.&lt;br /&gt;
 *&lt;br /&gt;
 *              @param handle        Handle to an SMC Parse structure.&lt;br /&gt;
 *              @param key           String containing key name.&lt;br /&gt;
 *              @param value         String containing value name.&lt;br /&gt;
 *              @param data          Handle or value passed in SMC_ParseFile&lt;br /&gt;
 *&lt;br /&gt;
 *              @return              An SMCResult action to take.&lt;br /&gt;
 *&lt;br /&gt;
 *              public SMCResult:OnKeyValue(SMCParser:handle, const key[], const value[], any:data)&lt;br /&gt;
 *&lt;br /&gt;
 *          EndSection:&lt;br /&gt;
 *              Called when the parser finds the end of the current section.&lt;br /&gt;
 *&lt;br /&gt;
 *              @param handle        Handle to an SMC Parse structure.&lt;br /&gt;
 *              @param data          Handle or value passed in SMC_ParseFile&lt;br /&gt;
 *&lt;br /&gt;
 *              @return              An SMCResult action to take.&lt;br /&gt;
 *&lt;br /&gt;
 *              public SMCResult:OnEndSection(SMCParser:handle, any:data)&lt;br /&gt;
 * -&lt;br /&gt;
 * @param handle        Handle to an SMC Parse structure.&lt;br /&gt;
 * @param kv            A KeyValue callback.&lt;br /&gt;
 * @param ns            An optional NewSection callback.&lt;br /&gt;
 * @param es            An optional EndSection callback.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native SMC_SetReaders(SMCParser:smc, const kvFunc[], const nsFunc[] = &amp;quot;&amp;quot;, const esFunc[] = &amp;quot;&amp;quot;);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|SMC_SetRawLine|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=SMC_SetRawLine|header=Sets a raw line reader on an text parser handle.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=SMC_SetRawLine|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a raw line reader on an text parser handle.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  Below is the prototype of callbacks:&lt;br /&gt;
 *        -&lt;br /&gt;
 *          Called whenever a raw line is read.&lt;br /&gt;
 *&lt;br /&gt;
 *          @param handle        Handle to an SMC Parse structure.&lt;br /&gt;
 *          @param line          A string containing the raw line from the file.&lt;br /&gt;
 *          @param lineno        The line number it occurs on.&lt;br /&gt;
 *          @param data          Handle or value passed in SMC_ParseFile&lt;br /&gt;
 *&lt;br /&gt;
 *          @return              An SMCResult action to take.&lt;br /&gt;
 *&lt;br /&gt;
 *          public SMCResult:SMC_RawLine(SMCParser:handle, const line[], lineno, any:data)&lt;br /&gt;
 *        -&lt;br /&gt;
 * @param handle        Handle to an SMC Parse structure.&lt;br /&gt;
 * @param func          A RawLine callback.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native SMC_SetRawLine(SMCParser:handle, const func[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|SMC_GetErrorString|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=SMC_GetErrorString|header=Gets an error string for an SMCError code.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=SMC_GetErrorString|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets an error string for an SMCError code.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  SMCError_Okay returns false.&lt;br /&gt;
 * @note  SMCError_Custom (which is thrown on SMCParse_HaltFail) returns false.&lt;br /&gt;
 *&lt;br /&gt;
 * @param error         The SMCParseError code.&lt;br /&gt;
 * @param buffer        A string buffer for the error (contents undefined on failure).&lt;br /&gt;
 * @param buf_max       The maximum size of the buffer.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True on success, false otherwise.&lt;br /&gt;
 */&lt;br /&gt;
native bool:SMC_GetErrorString(SMCError:error, buffer[], buf_max);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
'''INI Format'''&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Technical format detail:|{{hidden|id=ini-format|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=ini-format|contentonly=yes|content=&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * The INI file format is defined as:&lt;br /&gt;
 *    WHITESPACE: 0x20, \n, \t, \r&lt;br /&gt;
 *    IDENTIFIER: A-Z a-z 0-9 _ - , + . $ ? /&lt;br /&gt;
 *    STRING    : Any set of symbols&lt;br /&gt;
 *&lt;br /&gt;
 * Basic syntax is comprised of SECTIONs.&lt;br /&gt;
 *    A SECTION is defined as:&lt;br /&gt;
 *    [SECTIONNAME]&lt;br /&gt;
 *    OPTION&lt;br /&gt;
 *    OPTION&lt;br /&gt;
 *    OPTION...&lt;br /&gt;
 *&lt;br /&gt;
 * SECTIONNAME is an IDENTIFIER.&lt;br /&gt;
 *    OPTION can be repeated any number of times, once per line.&lt;br /&gt;
 *    OPTION is defined as one of:&lt;br /&gt;
 *      KEY = &amp;quot;VALUE&amp;quot;&lt;br /&gt;
 *      KEY = VALUE&lt;br /&gt;
 *      KEY&lt;br /&gt;
 *    Where KEY is an IDENTIFIER and VALUE is a STRING.&lt;br /&gt;
 *&lt;br /&gt;
 * WHITESPACE should always be omitted.&lt;br /&gt;
 *    COMMENTS should be stripped, and are defined as text occurring in:&lt;br /&gt;
 *    ;&amp;lt;TEXT&amp;gt;&lt;br /&gt;
 *&lt;br /&gt;
 * Example file below.  Note that the second line is technically invalid.&lt;br /&gt;
 * The event handler must decide whether this should be allowed.&lt;br /&gt;
 *    --FILE BELOW--&lt;br /&gt;
 *    [gaben]&lt;br /&gt;
 *    hi = clams&lt;br /&gt;
 *    bye = &amp;quot;NO CLAMS&amp;quot;&lt;br /&gt;
 *&lt;br /&gt;
 *    [valve]&lt;br /&gt;
 *    cannot&lt;br /&gt;
 *    maintain&lt;br /&gt;
 *    products&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 ! Native&lt;br /&gt;
 ! Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|INI_CreateParser|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=INI_CreateParser|header=Creates a new SMC parser.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=INI_CreateParser|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Parser invalid code.&lt;br /&gt;
 */&lt;br /&gt;
enum INIParser&lt;br /&gt;
{&lt;br /&gt;
    Invalid_INIParser = 0&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Creates a new INI parser.&lt;br /&gt;
 * This is used to set parse hooks.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              A new handle to an INI Parse structure.&lt;br /&gt;
 */&lt;br /&gt;
native INIParser:INI_CreateParser();&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|INI_DestroyParser|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=INI_DestroyParser|header=Disposes of an INI parser.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=INI_DestroyParser|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Disposes of an INI parser.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        Handle to an INI Parse structure.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True if disposed, false otherwise.&lt;br /&gt;
 */&lt;br /&gt;
native INI_DestroyParser(&amp;amp;INIParser:handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|INI_ParseFile|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=INI_ParseFile|header=Parses an INI config file.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=INI_ParseFile|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Parses an INI config file.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        A handle to an INI Parse structure.&lt;br /&gt;
 * @param file          A string containing the file path.&lt;br /&gt;
 * @param line          An optional by reference cell to store the last line number read.&lt;br /&gt;
 * @param col           An optional by reference cell to store the last column number read.&lt;br /&gt;
 * @param data          An optional handle or value to pass through to callback functions&lt;br /&gt;
 *&lt;br /&gt;
 * @return              An SMCParseError result.&lt;br /&gt;
 * @error               Invalid or corrupt handle.&lt;br /&gt;
 */&lt;br /&gt;
native bool:INI_ParseFile(INIParser:handle, const file[], &amp;amp;line = 0, &amp;amp;col = 0, any:data = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|INI_ParseStart|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=INI_ParseStart|header=Sets the INI_ParseStart function of a parse handle.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=INI_ParseStart|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets the INI_ParseStart function of a parse handle.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  Below is the prototype of callback:&lt;br /&gt;
 *        -&lt;br /&gt;
 *          Called when parsing is started.&lt;br /&gt;
 *&lt;br /&gt;
 *          @param handle        A handle to an INI Parse structure.&lt;br /&gt;
 *          @param data          Handle or value passed in INI_ParseFile&lt;br /&gt;
 *&lt;br /&gt;
 *          @noreturn&lt;br /&gt;
 *&lt;br /&gt;
 *          public OnParseStart(INIParser:handle, any:data)&lt;br /&gt;
 *        -&lt;br /&gt;
 * @param handle        Handle to an INI Parse structure.&lt;br /&gt;
 * @param func          A ParseStart callback.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error               Invalid or corrupt handle.&lt;br /&gt;
 */&lt;br /&gt;
native INI_SetParseStart(INIParser:handle, const func[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|INI_SetParseEnd|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=INI_SetParseEnd|header=Sets the INI_ParseEnd function of a parse handle.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=INI_SetParseEnd|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets the INI_ParseEnd function of a parse handle.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  Below is the prototype of callback:&lt;br /&gt;
 *        -&lt;br /&gt;
 *          Called when parsing is halted.&lt;br /&gt;
 *&lt;br /&gt;
 *          @param handle        A handle to an INI Parse structure.&lt;br /&gt;
 *          @param halted        True if abnormally halted, false otherwise.&lt;br /&gt;
 *          @param data          Handle or value passed in INI_ParseFile&lt;br /&gt;
 *&lt;br /&gt;
 *          @noreturn&lt;br /&gt;
 *&lt;br /&gt;
 *          public OnParseEnd(INIParser:handle, bool:halted, any:data)&lt;br /&gt;
 *        -&lt;br /&gt;
 * @param handle        Handle to an INI Parse structure.&lt;br /&gt;
 * @param func          A ParseEnd callback.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error               Invalid or corrupt handle.&lt;br /&gt;
 */&lt;br /&gt;
native INI_SetParseEnd(INIParser:handle, const func[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|INI_SetReaders|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=INI_SetReaders|header=Sets the two main reader functions.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=INI_SetReaders|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets the two main reader functions.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  Below is the prototype of callback:&lt;br /&gt;
 *        -&lt;br /&gt;
 *          NewSection:&lt;br /&gt;
 *              Called when the parser finds a new section.&lt;br /&gt;
 *&lt;br /&gt;
 *              @param handle           Handle to an INI Parse structure.&lt;br /&gt;
 *              @param section          Name of section in between the [ and ] characters.&lt;br /&gt;
 *              @param invalid_tokens   True if invalid tokens were detected in the name.&lt;br /&gt;
 *              @param close_bracket    True if a closing bracket was detected, false otherwise.&lt;br /&gt;
 *              @param extra_tokens     True if extra tokens were detected on the line.&lt;br /&gt;
 *              @param curtok           Contains current token in the line where the section name starts.&lt;br /&gt;
 *                                      You can add to this offset when failing to point to a token.&lt;br /&gt;
 *              @param data             Handle or value passed in INI_ParseFile&lt;br /&gt;
 *&lt;br /&gt;
 *              @return                 True to keep parsing, false otherwise.&lt;br /&gt;
 *&lt;br /&gt;
 *              public bool:OnNewSection(INIParser:handle, const section[], bool:invalid_tokens, bool:close_bracket, bool:extra_tokens, curtok, any:data)&lt;br /&gt;
 *&lt;br /&gt;
 *          KeyValue:&lt;br /&gt;
 *              Called when the parser finds a new key/value pair.&lt;br /&gt;
 *&lt;br /&gt;
 *              @param handle           Handle to an INI Parse structure.&lt;br /&gt;
 *              @param key              Name of key.&lt;br /&gt;
 *              @param value            String containing value (with quotes stripped, if any).&lt;br /&gt;
 *              @param invalid_tokens   Whether or not the key contained invalid tokens.&lt;br /&gt;
 *              @param equal_token      There was an '=' sign present (in case the value is missing).&lt;br /&gt;
 *              @param quotes           Whether value was enclosed in quotes.&lt;br /&gt;
 *              @param curtok           Contains the token index of the start of the value string.&lt;br /&gt;
 *                                      This can be changed when returning false.&lt;br /&gt;
 *              @param data             Handle or value passed in INI_ParseFile&lt;br /&gt;
 *&lt;br /&gt;
 *              @return                 True to keep parsing, false otherwise.&lt;br /&gt;
 *&lt;br /&gt;
 *              public bool:OnKeyValue(INIParser:handle, const key[], const value[], bool:invalid_tokens, bool:equal_token, bool:quotes, curtok, any:data)&lt;br /&gt;
 *        -&lt;br /&gt;
 * @param handle        Handle to an INI Parse structure.&lt;br /&gt;
 * @param kv            A KeyValue callback.&lt;br /&gt;
 * @param ns            An optional NewSection callback.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native INI_SetReaders(INIParser:smc, const kvFunc[], const nsFunc[] = &amp;quot;&amp;quot; );&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|INI_SetRawLine|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=INI_SetRawLine|header=Sets a raw line reader on an INI parser handle.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=INI_SetRawLine|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a raw line reader on an INI parser handle.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  Below is the prototype of callback:&lt;br /&gt;
 *        -&lt;br /&gt;
 *          Called whenever a raw line is read.&lt;br /&gt;
 *&lt;br /&gt;
 *          @param handle       The INI Parse handle.&lt;br /&gt;
 *          @param line         Contents of line.&lt;br /&gt;
 *          @param lineno       The line number it occurs on.&lt;br /&gt;
 *          @param curtok       Pointer to optionally store failed position in string.&lt;br /&gt;
 *          @param data         Handle or value passed in INI_ParseFile&lt;br /&gt;
 *&lt;br /&gt;
 *          @return             True to keep parsing, false otherwise.&lt;br /&gt;
 *&lt;br /&gt;
 *          public bool:OnRawLine(INIParser:smc, const line[], lineno, curtok, any:data)&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        Handle to an INI Parse structure.&lt;br /&gt;
 * @param func          A RawLine callback.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native INI_SetRawLine(INIParser:handle, const func[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
== Existing core APIs additions ==&lt;br /&gt;
&lt;br /&gt;
=== Client ===&lt;br /&gt;
&lt;br /&gt;
''' Behavior changes '''&lt;br /&gt;
&lt;br /&gt;
* The following natives can now be used on connecting players: {{tt|find_player}}, {{tt|get_players}} and {{tt|engclient_print}} (console only).&lt;br /&gt;
* {{tt|set_user_rendering}} default {{tt|color}} and {{tt|amount}} are now set to 0 to follow game behavior.&lt;br /&gt;
&lt;br /&gt;
''' (Dis)connection '''&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|The {{tt|client_disconnect}} forward is deprecated in favor of {{tt|client_disconnected}}.&amp;lt;br /&amp;gt;This will be called in some additional cases that {{tt|client_disconnect}} doesn't cover, most notably when a client aborts the connection process. &amp;lt;br /&amp;gt;It is guaranteed to pair with the {{tt|client_connect}} forward.|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 ! Forward&lt;br /&gt;
 ! Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|client_connectex|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=client_connectex|header=Called when a client is connecting.|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Called when a client is connecting.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This forward is called too early to do anything that directly affects&lt;br /&gt;
 *       the client.&lt;br /&gt;
 *&lt;br /&gt;
 * @param id        Client index&lt;br /&gt;
 * @param name      Client name&lt;br /&gt;
 * @param ip        Client ip address with port&lt;br /&gt;
 * @param reason    A reason that will be displayed when player gets rejected (can be overwritten)&lt;br /&gt;
 *&lt;br /&gt;
 * @return          PLUGIN_CONTINUE to let a client join to the server&lt;br /&gt;
 *                  PLUGIN_HANDLED or higher to prevent a client to join&lt;br /&gt;
 */&lt;br /&gt;
forward client_connectex(id, const name[], const ip[], reason[128]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|client_disconnected|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=client_disconnected|header=Called when a client is disconnected from the server.|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Called when a client is disconnected from the server.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This will be called in some additional cases that client_disconnect doesn't cover,&lt;br /&gt;
 *       most notably when a client aborts the connection process. It is guaranteed to pair&lt;br /&gt;
 *       with the client_connect() forward.&lt;br /&gt;
 * @note When this fires the player entity is still valid (e.g. is_user_connected(id) will&lt;br /&gt;
 *       return true), but no networked commands will reach the client.&lt;br /&gt;
 *&lt;br /&gt;
 * @param id         Client index&lt;br /&gt;
 * @param drop       If true, the game has explicitly dropped the client&lt;br /&gt;
 * @param message    If drop is true, a writable buffer containing the disconnect info message&lt;br /&gt;
 * @param maxlen     Maximum size of buffer&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
forward client_disconnected(id, bool:drop, message[], maxlen);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|client_remove|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=client_remove|header=Called when a client entity has been removed from the server.|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Called when a client entity has been removed from the server.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This fires after the client_disconnected() forward, when the player entity has been&lt;br /&gt;
 *       removed (e.g. is_user_connected(id) will return false).&lt;br /&gt;
 *&lt;br /&gt;
 * @param id         Client index&lt;br /&gt;
 * @param drop       If true, the game has explicitly dropped the client&lt;br /&gt;
 * @param message    If drop is true, contains the disconnect info message&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
forward client_remove(id, bool:drop, const message[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' New Natives &amp;amp; Stocks '''&lt;br /&gt;
&lt;br /&gt;
For the sake of better understanding and readability, {{tt|find_player}} and {{tt|get_players}} have now their counterparts which use the flags {{hidden|id=find-get-players|labelonly=yes}} as name constants instead of letter. It is encouraged to use them instead.&lt;br /&gt;
&lt;br /&gt;
{{hidden|id=find-get-players|contentonly=yes|content=&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * FindPlayerFlags constants for find_player_ex()&lt;br /&gt;
 */&lt;br /&gt;
enum FindPlayerFlags (&amp;lt;&amp;lt;= 1)&lt;br /&gt;
{&lt;br /&gt;
	FindPlayer_None = 0,           // None&lt;br /&gt;
	FindPlayer_MatchName = 1,      // Match with name&lt;br /&gt;
	FindPlayer_MatchNameSubstring, // Match with name substring&lt;br /&gt;
	FindPlayer_MatchAuthId,        // Match with authid&lt;br /&gt;
	FindPlayer_MatchIP,            // Match with ip&lt;br /&gt;
	FindPlayer_MatchTeam,          // Match with team name&lt;br /&gt;
	FindPlayer_ExcludeDead,        // Do not include dead clients&lt;br /&gt;
	FindPlayer_ExcludeAlive,       // Do not include alive clients&lt;br /&gt;
	FindPlayer_ExcludeBots,        // Do not include bots&lt;br /&gt;
	FindPlayer_ExcludeHuman,       // Do not include human clients&lt;br /&gt;
	FindPlayer_LastMatched,        // Return last matched client instead of the first&lt;br /&gt;
	FindPlayer_MatchUserId,        // Match with userid&lt;br /&gt;
	FindPlayer_CaseInsensitive,    // Match case insensitively&lt;br /&gt;
	FindPlayer_IncludeConnecting   // Include connecting clients&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 ! Native &amp;amp; Stock&lt;br /&gt;
 ! Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|find_player_ex|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=find_player_ex|header=Finds a player given a filter.|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Find a player given a filter.&lt;br /&gt;
 *&lt;br /&gt;
 * @note If matching by userid, do not also specify FindPlayer_MatchName, FindPlayer_MatchNameSubstring&lt;br /&gt;
 *       or FindPlayer_MatchAuthId, or the function may not return a correct result.&lt;br /&gt;
 *&lt;br /&gt;
 * @param flags     Filtering flags (enum FindPlayerFlags); valid flags are:&lt;br /&gt;
 *                    FindPlayer_MatchName - match with name&lt;br /&gt;
 *                    FindPlayer_MatchNameSubstring - match with name substring&lt;br /&gt;
 *                    FindPlayer_MatchAuthId - match with authid&lt;br /&gt;
 *                    FindPlayer_MatchIP - match with ip&lt;br /&gt;
 *                    FindPlayer_MatchTeam - match with team name&lt;br /&gt;
 *                    FindPlayer_ExcludeDead - do not include dead clients&lt;br /&gt;
 *                    FindPlayer_ExcludeAlive - do not include alive clients&lt;br /&gt;
 *                    FindPlayer_ExcludeBots - do not include bots&lt;br /&gt;
 *                    FindPlayer_ExcludeHuman - do not include human clients&lt;br /&gt;
 *                    FindPlayer_LastMatched - return last matched client instead of the first&lt;br /&gt;
 *                    FindPlayer_MatchUserId - match with userid&lt;br /&gt;
 *                    FindPlayer_CaseInsensitive - match case insensitively&lt;br /&gt;
 *                    FindPlayer_IncludeConnecting - include connecting clients&lt;br /&gt;
 * @param ...       String to match against (integer if FindPlayer_MatchUserId is specified)&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Client index, or 0 if no client was found&lt;br /&gt;
 */&lt;br /&gt;
native find_player_ex(FindPlayerFlags:flags, ...);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_players_ex|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_players_ex|header=Stores a filtered list of client indexes to an array.|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Stores a filtered list of client indexes to an array.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Example retrieving all alive CTs:&lt;br /&gt;
 *       get_players_ex(players, num, GetPlayers_ExcludeDead | GetPlayers_MatchTeam, &amp;quot;CT&amp;quot;)&lt;br /&gt;
 *&lt;br /&gt;
 * @param players   Array to store indexes to&lt;br /&gt;
 * @param num       Variable to store number of indexes to&lt;br /&gt;
 * @param flags     Optional filtering flags (enum GetPlayersFlags); valid flags are:&lt;br /&gt;
 *                    GetPlayers_None - No filter (Default)&lt;br /&gt;
 *                    GetPlayers_ExcludeDead - do not include dead clients&lt;br /&gt;
 *                    GetPlayers_ExcludeAlive - do not include alive clients&lt;br /&gt;
 *                    GetPlayers_ExcludeBots - do not include bots&lt;br /&gt;
 *                    GetPlayers_ExcludeHuman - do not include human clients&lt;br /&gt;
 *                    GetPlayers_MatchTeam - match with team&lt;br /&gt;
 *                    GetPlayers_MatchNameSubstring - match with part of name&lt;br /&gt;
 *                    GetPlayers_CaseInsensitive - match case insensitive&lt;br /&gt;
 *                    GetPlayers_ExcludeHLTV - do not include HLTV proxies&lt;br /&gt;
 *                    GetPlayers_IncludeConnecting - include connecting clients&lt;br /&gt;
 * @param team      String to match against if the &amp;quot;e&amp;quot; or &amp;quot;f&amp;quot; flag is specified&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
stock get_players_ex(players[MAX_PLAYERS], &amp;amp;num, GetPlayersFlags:flags = GetPlayers_None, const team[] = &amp;quot;&amp;quot;)&lt;br /&gt;
{&lt;br /&gt;
    new strFlags[10];&lt;br /&gt;
    get_flags(_:flags, strFlags, charsmax(strFlags));&lt;br /&gt;
    get_players(players, num, strFlags, team);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_playersnum_ex|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_playersnum_ex|header=Returns the number of clients on the server that match the specified flags.|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns the number of clients on the server that match the specified flags.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Example retrieving all alive CTs:&lt;br /&gt;
 *       new AliveCt = get_playersnum_ex(GetPlayers_ExcludeDead | GetPlayers_MatchTeam, &amp;quot;CT&amp;quot;)&lt;br /&gt;
 *&lt;br /&gt;
 * @param flags     Optional filtering flags (enum GetPlayersFlags); valid flags are:&lt;br /&gt;
 *                    GetPlayers_None - No filter (Default)&lt;br /&gt;
 *                    GetPlayers_ExcludeDead - do not include dead clients&lt;br /&gt;
 *                    GetPlayers_ExcludeAlive - do not include alive clients&lt;br /&gt;
 *                    GetPlayers_ExcludeBots - do not include bots&lt;br /&gt;
 *                    GetPlayers_ExcludeHuman - do not include human clients&lt;br /&gt;
 *                    GetPlayers_MatchTeam - match with team&lt;br /&gt;
 *                    GetPlayers_MatchNameSubstring - match with part of name&lt;br /&gt;
 *                    GetPlayers_CaseInsensitive - match case insensitive&lt;br /&gt;
 *                    GetPlayers_ExcludeHLTV - do not include HLTV proxies&lt;br /&gt;
 *                    GetPlayers_IncludeConnecting - include connecting clients&lt;br /&gt;
 * @param team      String to match against if the GetPlayers_MatchTeam or GetPlayers_MatchNameSubstring flag is specified&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Number of clients on the server that match the specified flags&lt;br /&gt;
 */&lt;br /&gt;
stock get_playersnum_ex(GetPlayersFlags:flags = GetPlayers_None, const team[] = &amp;quot;&amp;quot;)&lt;br /&gt;
{&lt;br /&gt;
	new PlayersNum;&lt;br /&gt;
	get_players_ex(_, PlayersNum, flags, team);&lt;br /&gt;
	return PlayersNum;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=cvar_example|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=cvar_example|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
findPlayer()&lt;br /&gt;
{&lt;br /&gt;
    new const dead_player = find_player_ex(FindPlayer_MatchName | FindPlayer_ExcludeAlive, &amp;quot;egg&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
getPlayer()&lt;br /&gt;
{&lt;br /&gt;
    new playersList[MAX_PLAYERS], playersCount;&lt;br /&gt;
    get_players_ex(playersList, playersCount, GetPlayers_ExcludeDead | GetPlayers_MatchTeam, &amp;quot;CT&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    // ...&lt;br /&gt;
&lt;br /&gt;
    new const aliveCTsCount = get_playersnum_ex(GetPlayers_ExcludeDead | GetPlayers_MatchTeam, &amp;quot;CT&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
''' New params '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | parameter&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|user_silentkill|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|flag|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=user_silentkill|header=If nonzero, the death will not affect the client's score.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
stock user_silentkill(index, flag = 1)&lt;br /&gt;
{&lt;br /&gt;
    static msgid = 0;&lt;br /&gt;
    new msgblock;&lt;br /&gt;
    if (!msgid)&lt;br /&gt;
    {&lt;br /&gt;
        msgid = get_user_msgid(&amp;quot;DeathMsg&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    msgblock = get_msg_block(msgid);&lt;br /&gt;
    set_msg_block(msgid, BLOCK_ONCE);&lt;br /&gt;
    user_kill(index, flag);&lt;br /&gt;
    set_msg_block(msgid, msgblock);&lt;br /&gt;
&lt;br /&gt;
    return 1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Forward&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | parameter&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|client_authorized|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|authid|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=client_authorized|header=Client auth|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
forward client_authorized(id, const authid[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Command ===&lt;br /&gt;
&lt;br /&gt;
''' Callback '''&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|amxclient_cmd|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=amxclient_cmd|header=Executes a command from the client without actually sending it to the client's DLL. &amp;lt;br /&amp;gt;Similar to {{tt|engclient_cmd|bgcolor=white}} with the difference this triggers plugin command hooks.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=amxclient_cmd|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Execute a command from the client without actually sending it to the client's&lt;br /&gt;
 * DLL. This triggers plugin command hooks.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This emulates a client command on the server side, and is an excellent&lt;br /&gt;
 *       tool to force a client to do certain actions related to the game.&lt;br /&gt;
 * @note The command has to stand alone in the command parameter, only add&lt;br /&gt;
 *       arguments using the designated parameters.&lt;br /&gt;
 * @note Commands emulated using this function will trigger other plugin's&lt;br /&gt;
 *       command hooks. For an alternative that doesn't, see engclient_cmd()&lt;br /&gt;
 *&lt;br /&gt;
 * @param index         Client index, use 0 to execute from all clients&lt;br /&gt;
 * @param command       Client command to execute on&lt;br /&gt;
 * @param arg1          Optional command arguments&lt;br /&gt;
 * @param arg2          Optional command arguments&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If a single client is specified and the index is not within&lt;br /&gt;
 *                  the range of 1 to MaxClients, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native amxclient_cmd(index, const command[], const arg1[] = &amp;quot;&amp;quot;, const arg2[] = &amp;quot;&amp;quot;);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' Arguments conversion'''&lt;br /&gt;
&lt;br /&gt;
New natives to retrieve a command's argument directly as an integer or float instead of as a string ({{tt|read_argv()}}).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|read_argv_int|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=read_argv_int|header=Retrieves argument of client command as integer value.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=read_argv_int|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves argument of client command as integer value.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Should only be used inside of the client_command() forward.&lt;br /&gt;
 *&lt;br /&gt;
 * @param id        Argument index starting from 1&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Integer value&lt;br /&gt;
 */&lt;br /&gt;
native read_argv_int(id);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|read_argv_float|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=read_argv_float|header=Retrieves argument of client command as float value.|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=read_argv_float|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves argument of client command as float value.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Should only be used inside of the client_command() forward.&lt;br /&gt;
 *&lt;br /&gt;
 * @param id        Argument index starting from 1&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Float value&lt;br /&gt;
 */&lt;br /&gt;
native Float:read_argv_float(id);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=read_argv_int-ex|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=read_argv_int-ex|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    register_clcmd(&amp;quot;set_level&amp;quot;, &amp;quot;@OnSetLevel&amp;quot;, .info = &amp;quot;&amp;lt;value&amp;gt; - Sets a custom level&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@OnSetLevel(const client, const command_level, const command_id)&lt;br /&gt;
{&lt;br /&gt;
    new const value = read_argv_int(1);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
''' Translatable description '''&lt;br /&gt;
&lt;br /&gt;
In order to encourage the translations of command's description, a new parameter is available.&amp;lt;br /&amp;gt;&lt;br /&gt;
This is useful for use with the {{tt|amx_help}} client command for example.&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | parameter&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|register_clcmd|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|register_concmd|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|register_srvcmd|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|info_ml|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=register_cmd|header=If true, the parameter {{tt|info|bgcolor=white}} will be looked up as multilingual key.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Registers a callback to be called when the client executes a command from the&lt;br /&gt;
 * console.&lt;br /&gt;
 *&lt;br /&gt;
 * @note For a list of possible access flags, see the ADMIN_* constants in&lt;br /&gt;
 *       amxconst.inc&lt;br /&gt;
 * @note Opting in to FlagManager enables the admin privileges to be overwritten&lt;br /&gt;
 *       by the end user via the cmdaccess.ini config file.&lt;br /&gt;
 * @note Automatic detection for FlagManager will only include a command if it&lt;br /&gt;
 *       has required privileges (flags is not -1) and it is not a command&lt;br /&gt;
 *       starting with &amp;quot;say&amp;quot;.&lt;br /&gt;
 *&lt;br /&gt;
 * @param client_cmd    Command to register&lt;br /&gt;
 * @param function      Callback function&lt;br /&gt;
 * @param flags         Admin privilege flags required&lt;br /&gt;
 * @param info          Command description&lt;br /&gt;
 * @param FlagManager   0 opts out of flag manager, 1 opts in, -1 selects&lt;br /&gt;
 *                      automatically&lt;br /&gt;
 * @param info_ml       If true, the parameter &amp;quot;info&amp;quot; will be looked up as multilingual key&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Command id, 0 on failure&lt;br /&gt;
 * @error               If an invalid callback function is specified, an error&lt;br /&gt;
 *                      will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native register_clcmd(const client_cmd[], const function[], flags = -1, const info[] = &amp;quot;&amp;quot;, FlagManager = -1, bool:info_ml = false);&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Registers a callback to be called when the client or server executes a&lt;br /&gt;
 * command from the console.&lt;br /&gt;
 *&lt;br /&gt;
 * @note For a list of possible access flags, see the ADMIN_* constants in&lt;br /&gt;
 *       amxconst.inc&lt;br /&gt;
 * @note Opting in to FlagManager enables the admin privileges to be overwritten&lt;br /&gt;
 *       by the end user via the cmdaccess.ini config file.&lt;br /&gt;
 * @note Automatic detection for FlagManager will only include a command if it&lt;br /&gt;
 *       has required privileges (flags is not -1) and it is not a command&lt;br /&gt;
 *       starting with &amp;quot;say&amp;quot;.&lt;br /&gt;
 *&lt;br /&gt;
 * @param client_cmd    Command to register&lt;br /&gt;
 * @param function      Callback function&lt;br /&gt;
 * @param flags         Admin privilege flags required&lt;br /&gt;
 * @param info          Command description&lt;br /&gt;
 * @param FlagManager   0 opts out of flag manager, 1 opts in, -1 selects&lt;br /&gt;
 *                      automatically&lt;br /&gt;
 * @param info_ml       If true, the parameter &amp;quot;info&amp;quot; will be looked up as multilingual key&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Command id, 0 on failure&lt;br /&gt;
 * @error               If an invalid callback function is specified, an error&lt;br /&gt;
 *                      will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native register_concmd(const cmd[], const function[], flags = -1, const info[] = &amp;quot;&amp;quot;, FlagManager = -1, bool:info_ml = false);&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Registers a callback to be called when the server executes a command from the&lt;br /&gt;
 * console.&lt;br /&gt;
 *&lt;br /&gt;
 * @note For a list of possible access flags, see the ADMIN_* constants in&lt;br /&gt;
 *       amxconst.inc&lt;br /&gt;
 *&lt;br /&gt;
 * @param client_cmd    Command to register&lt;br /&gt;
 * @param function      Callback function&lt;br /&gt;
 * @param flags         Admin privilege flags required&lt;br /&gt;
 * @param info          Command description&lt;br /&gt;
 * @param info_ml       If true, the parameter &amp;quot;info&amp;quot; will be looked up as multilingual key&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Command id, 0 on failure&lt;br /&gt;
 * @error               If an invalid callback function is specified, an error&lt;br /&gt;
 *                      will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native register_srvcmd(const server_cmd[], const function[], flags = -1, const info[] = &amp;quot;&amp;quot;, bool:info_ml = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=trans-cmd|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=trans-cmd|contentonly=yes|content=&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
[en]&lt;br /&gt;
MY_KEY = Hello world!&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    register_clcmd(&amp;quot;my_command&amp;quot;, &amp;quot;OnMyCommand&amp;quot;, ADMIN_CFG, &amp;quot;MY_KEY&amp;quot;, .info_ml = true);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Cvar ===&lt;br /&gt;
&lt;br /&gt;
In order to manage cvars more easily, several new cvar features have been added.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|A cvar managed at least once is now cached internally, for faster lookup, that's it.|opt=full-border}}&lt;br /&gt;
{{alert|info|Note:|The cvar API is now moved to its own {{tt|cvars.inc|bgcolor=none}} include file.|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
''' Hooking '''&lt;br /&gt;
&lt;br /&gt;
You can now hook when a cvar value has changed.  This allows plugins to react to cases where other plugins or clients change a cvar's value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 ! Native&lt;br /&gt;
 ! Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|hook_cvar_change|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=hook_cvar_change|header=To create a hook|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=hook_cvar_change|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Creates a hook for when a cvar's value is changed.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Changing the cvar value from within this forward can lead to infinite&lt;br /&gt;
 *       recursion and should be avoided.&lt;br /&gt;
 * @note The callback will be called in the following manner:&lt;br /&gt;
 *&lt;br /&gt;
 * public cvar_change_callback(pcvar, const old_value[], const new_value[])&lt;br /&gt;
 *&lt;br /&gt;
 *   pcvar         - Pointer to cvar that was changed&lt;br /&gt;
 *   old_value     - Buffer containing the previous value of the cvar&lt;br /&gt;
 *   new_value     - Buffer containing the new value of the cvar&lt;br /&gt;
 *&lt;br /&gt;
 * The return value is ignored&lt;br /&gt;
 *&lt;br /&gt;
 * @param pcvar     Pointer to cvar&lt;br /&gt;
 * @param callback  Name of callback function&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Callback handle that can be used with&lt;br /&gt;
 *                  [disable|enable]_cvar_hook&lt;br /&gt;
 * @error           If an invalid cvar pointer or callback function is provided,&lt;br /&gt;
 *                  an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native cvarhook:hook_cvar_change(pcvar, const callback[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|disable_cvar_hook|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=disable_cvar_hook|header=To disable a hook|labelpos=left|labelonly=yes}}&lt;br /&gt;
{{hidden|id=disable_cvar_hook|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Disables a cvar hook, stopping it from being called.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Use the handle returned by hook_cvar_change as the parameter here.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Forward to disable&lt;br /&gt;
 * @error           If an invalid hook handle is provided, an error will be&lt;br /&gt;
 *                  thrown.&lt;br /&gt;
 */&lt;br /&gt;
native disable_cvar_hook(cvarhook:handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|enable_cvar_hook|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=enable_cvar_hook|header=To enable a hook|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Enables a cvar hook, restoring it to being called.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Use the handle returned by hook_cvar_change as the parameter here.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Forward to enable&lt;br /&gt;
 * @error           If an invalid hook handle is provided, an error will be&lt;br /&gt;
 *                  thrown.&lt;br /&gt;
 */&lt;br /&gt;
native enable_cvar_hook(cvarhook:handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=cvar_example|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=cvar_example|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
new cvarhook:CvarHandle;&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    CvarHandle = hook_cvar_change(get_cvar_pointer(&amp;quot;mp_timelimit&amp;quot;), &amp;quot;@OnTimelimitChange&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    register_concmd(&amp;quot;enable_hook&amp;quot; , &amp;quot;@OnConsoleCommand_EnableHook&amp;quot;);&lt;br /&gt;
    register_concmd(&amp;quot;disable_hook&amp;quot;, &amp;quot;@OnConsoleCommand_DisableHook&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@OnTimelimitChange(const pointer, const old_value[], const new_value[])&lt;br /&gt;
{&lt;br /&gt;
    server_print(&amp;quot;mp_timelimit: %s -&amp;gt; %s&amp;quot;, old_value, new_value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@OnClientCommand_EnableHook()&lt;br /&gt;
{&lt;br /&gt;
    enable_cvar_hook(CvarHandle);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@OnClientCommand_DisableHook()&lt;br /&gt;
{&lt;br /&gt;
    disable_cvar_hook(CvarHandle);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
''' Binding '''&lt;br /&gt;
&lt;br /&gt;
There are situations where you don't need to hook/manage a cvar value and you would wish to not deal with cvar pointers. &amp;lt;br /&amp;gt;&lt;br /&gt;
You can now bind a cvar's value to a global variable. This means that variable value will be always up to date.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 ! Native&lt;br /&gt;
 ! Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|bind_pcvar_num|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=bind_pcvar_num|header=To bind an integer|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Binds a cvar's integer value to a global variable. The variable will then&lt;br /&gt;
 * always contain the current cvar value as it is automatically kept up to date.&lt;br /&gt;
 *&lt;br /&gt;
 * @note The variable *has* to be a global or a static variable. Local variables&lt;br /&gt;
 *       created within functions can not be used for technical reasons.&lt;br /&gt;
 * @note Variables can not be bound to multiple cvars.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pcvar     Pointer to cvar&lt;br /&gt;
 * @param var       Global variable to keep updated&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid cvar pointer or variable is provided, an error&lt;br /&gt;
 *                  will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native bind_pcvar_num(pcvar, &amp;amp;any:var);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|bind_pcvar_float|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=bind_pcvar_float|header=To bind a float|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Binds a cvar's float value to a global variable. The variable will then&lt;br /&gt;
 * always contain the current cvar value as it is automatically kept up to date.&lt;br /&gt;
 *&lt;br /&gt;
 * @note The variable *has* to be a global or a static variable. Local variables&lt;br /&gt;
 *       created within functions can not be used for technical reasons.&lt;br /&gt;
 * @note Variables can not be bound to multiple cvars.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pcvar     Pointer to cvar&lt;br /&gt;
 * @param var       Global variable to keep updated&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid cvar pointer or variable is provided, an error&lt;br /&gt;
 *                  will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native bind_pcvar_float(pcvar, &amp;amp;Float:var);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|bind_pcvar_string|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=bind_pcvar_string|header=To bind a string|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Binds a cvar's string value to a global array. The array will then&lt;br /&gt;
 * always contain the current cvar value as it is automatically kept up to date.&lt;br /&gt;
 *&lt;br /&gt;
 * @note The array *has* to be a global or a static array. Local arrays&lt;br /&gt;
 *       created within functions can not be used for technical reasons.&lt;br /&gt;
 * @note Arrays can not be bound to multiple cvars.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pcvar     Pointer to cvar&lt;br /&gt;
 * @param var       Global array to keep updated&lt;br /&gt;
 * @param varlen    Maximum length of string array&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid cvar pointer or variable is provided, an error&lt;br /&gt;
 *                  will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native bind_pcvar_string(pcvar, any:var[], varlen);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=bind_example|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=bind_example|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
new CvarTimelimit;&lt;br /&gt;
new Float:CvarBuyTime;&lt;br /&gt;
new CvarSomething[32];&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    bind_pcvar_num(get_cvar_pointer(&amp;quot;mp_timelimit&amp;quot;), CvarTimelimit);&lt;br /&gt;
    bind_pcvar_float(get_cvar_pointer(&amp;quot;mp_buytime&amp;quot;), CvarBuyTime);&lt;br /&gt;
    bind_pcvar_string(register_cvar(&amp;quot;amx_something&amp;quot;, &amp;quot;something&amp;quot;), CvarSomething, charsmax(CvarSomething));&lt;br /&gt;
&lt;br /&gt;
    server_print(&amp;quot;mp_timelimit  current value: %d&amp;quot;, CvarTimelimit);&lt;br /&gt;
    server_print(&amp;quot;mp_buytime    current value: %f&amp;quot;, CvarBuyTime);&lt;br /&gt;
    server_print(&amp;quot;amx_something current value: %s&amp;quot;, CvarSomething);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
''' Boundary '''&lt;br /&gt;
&lt;br /&gt;
Having a better control over a cvar's value, we can enforce the value to be in a defined boundary.&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! Description&lt;br /&gt;
 ! Native&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_pcvar_bounds|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_pcvar_bounds|header=To get a boundary|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves the specified value boundary of a cvar.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pcvar     Pointer to cvar&lt;br /&gt;
 * @param type      Type of boundary to retrieve&lt;br /&gt;
 * @param value     Variable to store the specified boundary to&lt;br /&gt;
 *&lt;br /&gt;
 * @return          True if the cvar has a boundary set, false otherwise&lt;br /&gt;
 * @error           If an invalid cvar pointer or boundary type is provided,&lt;br /&gt;
 *                  an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native bool:get_pcvar_bounds(pcvar, CvarBounds:type, &amp;amp;Float:value);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|set_pcvar_bounds|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=set_pcvar_bounds|header=To set a boundary|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets the specified boundary of a cvar.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pcvar     Pointer to cvar&lt;br /&gt;
 * @param type      Type of boundary to set&lt;br /&gt;
 * @param set       If true the cvar boundary will be set, otherwise it will be&lt;br /&gt;
 *                  removed (value is ignored)&lt;br /&gt;
 * @param value     Floating point value to use as the boundary&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid cvar pointer or boundary type is provided, an&lt;br /&gt;
 *                  error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native set_pcvar_bounds(pcvar, CvarBounds:type, bool:set, Float:value = 0.0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|{{tt|CvarBounds|bgcolor=none}} has the following values:&lt;br /&gt;
* {{tt|CvarBound_Upper}}&lt;br /&gt;
* {{tt|CvarBound_Lower}}|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=bounds_example|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=bounds_example|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    new const pointer = register_cvar(&amp;quot;amx_leet&amp;quot;, &amp;quot;1337&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    // Defines min and max value&lt;br /&gt;
    set_pcvar_bounds(pointer, CvarBound_Lower, .set = true, 0.0);&lt;br /&gt;
    set_pcvar_bounds(pointer, CvarBound_Upper, .set = true, 42.0);&lt;br /&gt;
&lt;br /&gt;
    // Current value should be &amp;quot;42&amp;quot;.&lt;br /&gt;
    server_print(&amp;quot;amx_something current value: %f&amp;quot;, get_pcvar_float(pointer));&lt;br /&gt;
&lt;br /&gt;
    // Removes the lower bound.&lt;br /&gt;
    set_pcvar_bounds(pointer, CvarBound_Lower, .set = false);&lt;br /&gt;
&lt;br /&gt;
    new Float:value;&lt;br /&gt;
&lt;br /&gt;
    if (get_pcvar_bounds(pointer, CvarBound_Upper, value))&lt;br /&gt;
    {&lt;br /&gt;
        server_print(&amp;quot;amx_something should have an upper bound: %f&amp;quot;, value);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!get_pcvar_bounds(pointer, CvarBound_Upper, value))&lt;br /&gt;
    {&lt;br /&gt;
        server_print(&amp;quot;amx_something should not have an lower bound);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
''' Constant '''&lt;br /&gt;
&lt;br /&gt;
A missing {{tt|FCVAR_NOEXTRAWHITEPACE}} flag has been added.&amp;lt;br /&amp;gt;&lt;br /&gt;
It automatically strips trailing/leading white space from the string value.&lt;br /&gt;
&lt;br /&gt;
''' Creating '''&lt;br /&gt;
&lt;br /&gt;
A new {{tt|create_cvar}} {{hidden|id=create_cvar|labelonly=yes}} native has been added, similar to {{tt|register_cvar|bgcolor=none}} but with two new features:&lt;br /&gt;
{{hidden|id=create_cvar|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Creates a new cvar for the engine.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This has the same effect as register_cvar() but provides more options.&lt;br /&gt;
 * @note For a list of possible cvar flags see FCVAR_* constants above.&lt;br /&gt;
 * @note If an already existing cvar is registered it will not be duplicated.&lt;br /&gt;
 *       The default value is only set when the cvar is registered for the very&lt;br /&gt;
 *       first time since the server was started. Cvar bounds are overwritten&lt;br /&gt;
 *       by the create_cvar() call just as if they were re-set using&lt;br /&gt;
 *       set_pcvar_bounds().&lt;br /&gt;
 * @note The returned cvar pointer should be used with the get_pcvar_* and&lt;br /&gt;
 *       set_pcvar_* set of functions.&lt;br /&gt;
 *&lt;br /&gt;
 * @param name          Cvar name&lt;br /&gt;
 * @param string        Default cvar value&lt;br /&gt;
 * @param flags         Optional bitsum of flags specifying cvar behavior&lt;br /&gt;
 * @param description   Optional description of the cvar&lt;br /&gt;
 * @param has_min       Optional boolean that specifies if the cvar has a&lt;br /&gt;
 *                      minimum value&lt;br /&gt;
 * @param min_val       Minimum floating point value&lt;br /&gt;
 * @param has_max       Optional boolean that specifies if the cvar has a&lt;br /&gt;
 *                      maximum value&lt;br /&gt;
 * @param max_val       Maximum floating point value&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Unique cvar pointer&lt;br /&gt;
 * @error               If invalid bounds are provided (min_val &amp;gt; max_val or&lt;br /&gt;
 *                      vice versa), an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native create_cvar(const name[], const string[], flags = FCVAR_NONE, const description[] = &amp;quot;&amp;quot;, bool:has_min = false, Float:min_val = 0.0, bool:has_max = false, Float:max_val = 0.0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | ''Description''&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | Similar to command, you can explain shorlty what does the cvar. The message can be retrieved with {{tt|get_plugins_cvar|bgcolor=white}} and can be read from {{tt|amxx cvars|bgcolor=white}} detailed output. &amp;lt;br /&amp;gt; The description is used with {{tt|AutoExecConfig|bgcolor=white}} for example.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | ''Boudary''&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | You can set directly a boudary, either a minimum value, a maximum value or both.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=creeate_cvar_example|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=creeate_cvar_example|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    create_cvar(&amp;quot;amx_something1&amp;quot;, &amp;quot;1&amp;quot;, FCVAR_NONE, &amp;quot;My description here&amp;quot;, true, 1.0, true, 42.0);&lt;br /&gt;
    create_cvar(&amp;quot;amx_something2&amp;quot;, &amp;quot;2&amp;quot;, .description = &amp;quot;My description here&amp;quot;, .has_min = true, min_val = 1.0, .has_max = true, .max_val = 42.0);&lt;br /&gt;
    create_cvar(&amp;quot;amx_something3&amp;quot;, &amp;quot;3&amp;quot;, .has_min = true, min_val = 1.0);&lt;br /&gt;
    create_cvar(&amp;quot;amx_something4&amp;quot;, &amp;quot;4&amp;quot;, .has_max = true, max_val = 42.0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
''' Command '''&lt;br /&gt;
&lt;br /&gt;
The {{tt|amxx cvars}} shows now more informations about a cvar state.&lt;br /&gt;
Here an example of output:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
Managed cvars:&lt;br /&gt;
       NAME                     VALUE                    PLUGIN             HOOKED   MIN     MAX&lt;br /&gt;
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -&lt;br /&gt;
 [  1] amx_mode                 1                        admin.amxx         no       -       -&lt;br /&gt;
 [  2] amx_password_field       _pw                      admin.amxx         no       -       -&lt;br /&gt;
 [  3] amx_default_access       z                        admin.amxx         no       -       -&lt;br /&gt;
 [  4] amx_vote_ratio           0.02                     admin.amxx         no       -       -&lt;br /&gt;
 [  5] amx_something            something                test-hook.amxx     yes      -       -&lt;br /&gt;
 [  6] amx_leet                 42                       test-bounds.amxx   no       0.00    42.00&lt;br /&gt;
 ...&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It can show further details if you specify a cvar or index from the table: {{tt|amxx cvars &amp;lt;index or cvar name&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
amxx cvars 6&lt;br /&gt;
&lt;br /&gt;
Cvar details :&lt;br /&gt;
&lt;br /&gt;
 Cvar name   : amx_leet&lt;br /&gt;
 Value       : 42&lt;br /&gt;
 Def. value  : 1337&lt;br /&gt;
 Description :&lt;br /&gt;
 Flags       : FCVAR_EXTDLL&lt;br /&gt;
&lt;br /&gt;
 STATUS        PLUGIN                     INFOS&lt;br /&gt;
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -&lt;br /&gt;
 Registered    test-bounds.amxx           -&lt;br /&gt;
 Min value     test-bounds.amxx           0.000000&lt;br /&gt;
 Max value     test-bounds.amxx           42.000000&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''' Others '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_pcvar_bool|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_pcvar_bool|header=Returns an boolean value from a cvar via direct pointer access.|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns an boolean value from a cvar via direct pointer access.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pcvar     Pointer to cvar to retrieve value from&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Cvar value, converted to bool&lt;br /&gt;
 * @error           If an invalid cvar pointer is provided, an error will be&lt;br /&gt;
 *                  thrown.&lt;br /&gt;
 */&lt;br /&gt;
native bool:get_pcvar_bool(pcvar);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|set_pcvar_bool|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=set_pcvar_bool|header=Sets a boolean value to a cvar via direct pointer access.|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a boolean value to a cvar via direct pointer access.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pcvar     Pointer to cvar to set value of&lt;br /&gt;
 * @param num       Value to set cvar to&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid cvar pointer is provided, an error will be&lt;br /&gt;
 *                  thrown.&lt;br /&gt;
 */&lt;br /&gt;
native set_pcvar_bool(pcvar, bool:num);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== CellArray ===&lt;br /&gt;
&lt;br /&gt;
A bunch of natives have been added to complete the existing API. You are now able to:&lt;br /&gt;
* Clone an array&lt;br /&gt;
* Resize an array&lt;br /&gt;
* Find a value or string inside an array&lt;br /&gt;
* Control more precisely how the data is retrieved/saved&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|Arrays are heterogeneous. This means you can save different data types into a list. &amp;lt;br/&amp;gt;A good example is the Stack Structure API which is actually based on Array (internal library, that's it).|opt=full-border}}&lt;br /&gt;
{{alert|info|Note:|Initially the {{tt|reserved|bgcolor=none}} parameter in {{tt|ArrayCreate|bgcolor=none}} was intended to create blank entries that would immediately be usable with {{tt|ArrayGet/Set|bgcolor=white}} functions. &amp;lt;br /&amp;gt; This functionality was never working as intended, and can now be achieved using {{tt|ArrayResize|bgcolor=none}}.|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''' Cloning '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|ArrayClone|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=ArrayClone|header=Clones an array.|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Clones an array, returning a new handle with the same size and data.&lt;br /&gt;
 *&lt;br /&gt;
 * @param which         Array handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Handle to the cloned array on success, 0 otherwise&lt;br /&gt;
 * @error               If an invalid handle is provided an error will be&lt;br /&gt;
 *                      thrown.&lt;br /&gt;
 */&lt;br /&gt;
native Array:ArrayClone(Array:which);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=array_cloning_ex|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=array_cloning_ex|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    new Array:list = ArrayCreate();&lt;br /&gt;
&lt;br /&gt;
    ArrayPushCell(list, 1);&lt;br /&gt;
    ArrayPushCell(list, 2);&lt;br /&gt;
    ArrayPushCell(list, 3);&lt;br /&gt;
&lt;br /&gt;
    new Array:clone_list = ArrayClone(list);&lt;br /&gt;
&lt;br /&gt;
    //&lt;br /&gt;
&lt;br /&gt;
    ArrayDestroy(clone_list);&lt;br /&gt;
    ArrayDestroy(list);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
''' Resizing '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|ArrayResize|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=ArrayResize|header=Resizes an array.|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Resizes an array.&lt;br /&gt;
 *&lt;br /&gt;
 * @note If the size is smaller than the current array size the array is&lt;br /&gt;
 *       truncated and data lost.&lt;br /&gt;
 *&lt;br /&gt;
 * @param which         Array handle&lt;br /&gt;
 * @param newsize       New size&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error               If an invalid handle is provided or the resizing&lt;br /&gt;
 *                      operation runs out of memory, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native bool:ArrayResize(Array:which, newsize);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=array_resize_ex|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=array_resize_ex|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    new Array:list = ArrayCreate(.cellsize = 1, .reserved = 3);&lt;br /&gt;
&lt;br /&gt;
    ArrayPushCell(list, 1);&lt;br /&gt;
    ArrayPushCell(list, 2);&lt;br /&gt;
    ArrayPushCell(list, 3);&lt;br /&gt;
&lt;br /&gt;
    new const count = ArraySize(list);&lt;br /&gt;
&lt;br /&gt;
    ArrayResize( list, count + 1); // Add a new allocated and available slot&lt;br /&gt;
    ArraySetCell(list, count, 4);  // Notice you can use directly ArraySet&lt;br /&gt;
&lt;br /&gt;
    server_print(&amp;quot;Last value = %d, Cloned list size = %d&amp;quot;, ArrayGetCell(list, count), ArraySize(list)); // Should be 4.&lt;br /&gt;
&lt;br /&gt;
    ArrayDestroy(list);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
''' Finding a value '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|ArrayFindValue|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=ArrayFindValue|header=Searches through the array and returns the index of the first occurence of the specified value.|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Searches through the array and returns the index of the first occurence of&lt;br /&gt;
 * the specified value.&lt;br /&gt;
 *&lt;br /&gt;
 * @param which         Array handle&lt;br /&gt;
 * @param item          Value to search for&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Array index on success, -1 if the value can't be found&lt;br /&gt;
 * @error               If an invalid handle is provided an error will be&lt;br /&gt;
 *                      thrown.&lt;br /&gt;
 */&lt;br /&gt;
native ArrayFindValue(Array:which, any:item);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|ArrayFindString|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=ArrayFindString|header= Searches through the array and returns the index of the first occurence of the specified string.|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Searches through the array and returns the index of the first occurence of&lt;br /&gt;
 * the specified string.&lt;br /&gt;
 *&lt;br /&gt;
 * @param which         Array handle&lt;br /&gt;
 * @param item          String to search for&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Array index on success, -1 if the string can't be found&lt;br /&gt;
 * @error               Invalid handle.&lt;br /&gt;
 */&lt;br /&gt;
native ArrayFindString(Array:which, const item[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=array_find_ex|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=array_find_ex|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    new Array:list = ArrayCreate(.cellsize = 16);&lt;br /&gt;
&lt;br /&gt;
    ArrayPushString(list, &amp;quot;something&amp;quot;);&lt;br /&gt;
    ArrayPushString(list, &amp;quot;is&amp;quot;);&lt;br /&gt;
    ArrayPushCell(list, 42);&lt;br /&gt;
    ArrayPushString(list, &amp;quot;hidden&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    new index = ArrayFindValue(list, 42);&lt;br /&gt;
    server_print(&amp;quot;Cell index = %d&amp;quot;, index); // should be 2&lt;br /&gt;
&lt;br /&gt;
    index = ArrayFindString(list, &amp;quot;hidden&amp;quot;);&lt;br /&gt;
    server_print(&amp;quot;String index = %d&amp;quot;, index); // should be 3&lt;br /&gt;
&lt;br /&gt;
    ArrayDestroy(list);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''' Sorting '''&lt;br /&gt;
&lt;br /&gt;
Along two new {{tt|ArraySort}} and {{tt|SortADTArray}} natives, there is also a new {{tt|Sort_Random}} method.&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|ArraySortEx|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=ArraySortEx|header=A faster version of {{tt|ArraySort|bgcolor=none}}.|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * A faster version of ArraySort, the sorting algorithm then uses the custom&lt;br /&gt;
 * comparison function to sort the data.&lt;br /&gt;
 *&lt;br /&gt;
 * @note The advantage of this function is that the data of the elements being&lt;br /&gt;
 *       compared is directly passed to the function, instead of the item&lt;br /&gt;
 *       indexes that are passed by ArraySort. This removes the need for calling&lt;br /&gt;
 *       ArrayGet[Cell|String|Array] every time before being able to compare the&lt;br /&gt;
 *       elements.&lt;br /&gt;
 *&lt;br /&gt;
 * @note For Arrays with a cellsize of 1 (used for storing integers and floats),&lt;br /&gt;
 *       the function is called in the following manner:&lt;br /&gt;
 *&lt;br /&gt;
 * public MySortFunc(Array:array, elem1, elem2, const data[], data_size)&lt;br /&gt;
 *&lt;br /&gt;
 *   array           - Array handle in its current un-sorted state&lt;br /&gt;
 *   elem1, elem2    - Current element pair being compared&lt;br /&gt;
 *   data[]          - Extra data array passed to the sort func&lt;br /&gt;
 *   data_size       - Size of extra data&lt;br /&gt;
 *&lt;br /&gt;
 * @note For Arrays with a cellsize larger than 1 (used for storing arrays and&lt;br /&gt;
 *       strings), the function is called in the following manner:&lt;br /&gt;
 *&lt;br /&gt;
 * public MySortFunc(Array:array, elem1[], elem2[], const data[], data_size)&lt;br /&gt;
 *&lt;br /&gt;
 *   array               - Array handle in its current un-sorted state&lt;br /&gt;
 *   elem1[], elem2[]    - Current element pair being compared&lt;br /&gt;
 *   data[]              - Extra data array passed to the sort func&lt;br /&gt;
 *   data_size           - Size of extra data&lt;br /&gt;
 *&lt;br /&gt;
 *&lt;br /&gt;
 * @note The comparison function should return:&lt;br /&gt;
 *         -1 if elem1 should go before elem2&lt;br /&gt;
 *          0 if elem1 and elem2 are equal&lt;br /&gt;
 *          1 if elem1 should go after elem2&lt;br /&gt;
 *&lt;br /&gt;
 * @note All parameters after item2 are optional and do not need to be specified&lt;br /&gt;
 *       and used.&lt;br /&gt;
 * @note Unlike the sorting.inc version, the array passed to the callback is not&lt;br /&gt;
 *       in mid-sorted state.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array         Array handle&lt;br /&gt;
 * @param comparefunc   Callback function used for comparison&lt;br /&gt;
 * @param data          Extra data that is passed through to the callback&lt;br /&gt;
 * @param data_size     Size of extra data&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error               If an invalid handle or an invalid callback is provided&lt;br /&gt;
 *                      an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native ArraySortEx(Array:array, const comparefunc[], data[]=&amp;quot;&amp;quot;, data_size=0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|SortADTArray|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=SortADTArray|header=To sort directly with a sort method.|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sort an ADT Array. Specify the type as Integer, Float, or String.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array			Array Handle to sort&lt;br /&gt;
 * @param order			Sort order to use, same as other sorts.&lt;br /&gt;
 * @param type			Data type stored in the ADT Array&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native SortADTArray(Array:array, SortMethod:order, SortType:type);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
{{alert|info|Note:|{{tt|SortMethod|bgcolor=none}} has the following values:&lt;br /&gt;
* {{tt|Sort_Ascending}}&lt;br /&gt;
* {{tt|Sort_Descending}}&lt;br /&gt;
* {{tt|Sort_Random}}|opt=full-border}}&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' New params '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | parameter&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|ArrayGetArray|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|ArraySetArray|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|ArrayPushArray|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|size|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=new_size_param|header=Controls the number of elements to use.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * @param size          If not set, assumes the buffer size is equal to the&lt;br /&gt;
 *                      cellsize. Otherwise, the specified size is used.&lt;br /&gt;
 */&lt;br /&gt;
native ArrayGetArray(Array:which, item, any:output[], size = -1);&lt;br /&gt;
native ArraySetArray(Array:which, item, const any:input[], size =-1);&lt;br /&gt;
native ArrayPushArray(Array:which, const any:input[], size = -1);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|ArrayGetCell|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|ArraySetCell|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|achar|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|block|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=new_blockaschar_param|header=Specifies which block and retrieves a value as byte.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * @param block         If the array has a cellsize &amp;gt;1 this optionally specifies&lt;br /&gt;
 *                      which block to read from&lt;br /&gt;
 * @param asChar        If true reads the value as a byte instead of a cell&lt;br /&gt;
 */&lt;br /&gt;
native any:ArrayGetCell(Array:which, item, block = 0, bool:asChar = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== CellTrie ===&lt;br /&gt;
&lt;br /&gt;
The word &amp;quot;''Trie''&amp;quot; in this API is historical. As of AMX Mod X 1.9, tries have been internally replaced with hash tables, which have {{tt|O(1)|bgcolor=none}} insertion time instead of {{tt|O(n)|bgcolor=none}}. &amp;lt;br /&amp;gt;&lt;br /&gt;
As consequence, the API has been completed and you can now:&lt;br /&gt;
* Get a trie size&lt;br /&gt;
* Control more precisely the data on insertion/retrieval&lt;br /&gt;
* Iterate over a trie&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|Tries are heterogeneous. This means you can save different data types into a list.|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
''' Getting size '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|TrieGetSize|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=TrieGetSize|header=Returns the number of entries in a hash map.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns the number of entries in a hash map.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Map handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Number of elements in the hash map&lt;br /&gt;
 * @error           If an invalid handle is provided an error will be&lt;br /&gt;
 *                  thrown.&lt;br /&gt;
 */&lt;br /&gt;
native TrieGetSize(Trie:handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' Iterating '''&lt;br /&gt;
&lt;br /&gt;
There are two ways to iterate over a trie:&lt;br /&gt;
* ''Snapshots''&lt;br /&gt;
: As the name suggested, it will duplicate the whole set of keys (only) into a separate list. Any changes to the original list will not affect the snapshot. &amp;lt;br /&amp;gt; It's an expensive operation, but can be stored.&lt;br /&gt;
&lt;br /&gt;
:{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|TrieSnapshotCreate|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=TrieSnapshotCreate|header=Creates a snapshot of all keys in a hash map.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Creates a snapshot of all keys in a hash map. If the map is changed&lt;br /&gt;
 * afterwards,  the changes are not reflected in the snapshot.&lt;br /&gt;
 * Keys are not sorted.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Map handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return          New map snapshot handle, which must be freed via&lt;br /&gt;
 *                  TrieSnapshotDestroy()&lt;br /&gt;
 * @error           If an invalid handle is provided an error will be&lt;br /&gt;
 *                  thrown.&lt;br /&gt;
 */&lt;br /&gt;
native Snapshot:TrieSnapshotCreate(Trie:handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|TrieSnapshotLength|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=TrieSnapshotLength|header=Returns the number of keys in a map snapshot.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns the number of keys in a map snapshot. Note that this may be&lt;br /&gt;
 * different from the size of the map, since the map can change after the&lt;br /&gt;
 * snapshot of its keys was taken.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Map snapshot handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Number of keys&lt;br /&gt;
 * @error           If an invalid handle is provided an error will be&lt;br /&gt;
 *                  thrown.&lt;br /&gt;
 */&lt;br /&gt;
native TrieSnapshotLength(Snapshot:handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|TrieSnapshotGetKey|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=TrieSnapshotGetKey|header= Retrieves the key string of a given key in a map snapshot.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves the key string of a given key in a map snapshot.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Map snapshot handle&lt;br /&gt;
 * @param index     Key index (starting from 0)&lt;br /&gt;
 * @param buffer    String buffer&lt;br /&gt;
 * @param maxlength Maximum buffer length&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Number of bytes written to the buffer&lt;br /&gt;
 * @error           If an invalid handle is provided an error will be&lt;br /&gt;
 *                  thrown. or index out of range&lt;br /&gt;
 */&lt;br /&gt;
native TrieSnapshotGetKey(Snapshot:handle, index, buffer[], maxlength);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|TrieSnapshotDestroy|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=TrieSnapshotDestroy|header= Retrieves the key string of a given key in a map snapshot.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Destroys a map snapshot and frees its memory.&lt;br /&gt;
 *&lt;br /&gt;
 * @note The function automatically sets the variable passed to it to 0 to aid&lt;br /&gt;
 *       in preventing accidental usage after destroy.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Map snapshot handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return          1 on success, 0 if an invalid handle was passed in&lt;br /&gt;
 */&lt;br /&gt;
native TrieSnapshotDestroy(&amp;amp;Snapshot:handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
:{{alert|info|Note:|The keys are not sorted.|opt=full-border}}&lt;br /&gt;
:{{alert|success|Example:|{{hidden|id=trie_example_snap|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=trie_example_snap|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    new Trie:list = TrieCreate();&lt;br /&gt;
    {&lt;br /&gt;
        TrieSetString(list, &amp;quot;adventure&amp;quot;, &amp;quot;time!&amp;quot;);&lt;br /&gt;
        TrieSetString(list, &amp;quot;butterflies&amp;quot;, &amp;quot;bees&amp;quot;);&lt;br /&gt;
        TrieSetString(list, &amp;quot;egg&amp;quot;, &amp;quot;egg&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    new Snapshot:keys = TrieSnapshotCreate(list);&lt;br /&gt;
    {&lt;br /&gt;
        new const length = TrieSnapshotLength(keys);&lt;br /&gt;
        new key[32];&lt;br /&gt;
&lt;br /&gt;
        for (new const i = 0; i &amp;lt; length; ++i)&lt;br /&gt;
        {&lt;br /&gt;
            TrieSnapshotGetKey(keys, i, buffer, charmax(buffer));&lt;br /&gt;
            server_print(&amp;quot;buffer = %s&amp;quot;, buffer);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    TrieSnapshotDestroy(keys);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
* ''Iterator''&lt;br /&gt;
: A contrario, Iterators are designed to be short-lived and not stored, and creating them is very cheap. &amp;lt;br /&amp;gt; Reading data from an iterator is just as fast as reading directly from the map.&amp;lt;br /&amp;gt; This is useful if you just need to iterate (or eventually updating values of existing keys, which is allowed)&lt;br /&gt;
&lt;br /&gt;
:{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|TrieIterCreate|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=TrieIterCreate|header=Creates an iterator for a map.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Creates an iterator for a map. It provides iterative read-only access to the&lt;br /&gt;
 * maps contents.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Removing or adding keys to the underlying map will invalidate all its&lt;br /&gt;
 *       iterators. Updating values of existing keys is allowed and the changes&lt;br /&gt;
 *       will be immediately reflected in the iterator.&lt;br /&gt;
 * @note Iterators are designed to be short-lived and not stored, and creating&lt;br /&gt;
 *       them is very cheap. Reading data from an iterator is just as fast as&lt;br /&gt;
 *       reading directly from the map.&lt;br /&gt;
 * @note Just like in snapshots the keys are not sorted.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              New iterator handle, which must be freed via TrieIterDestroy().&lt;br /&gt;
 * @error               Invalid Handle&lt;br /&gt;
 */&lt;br /&gt;
native TrieIter:TrieIterCreate(Trie:handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|TrieIterEnded|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=TrieIterEnded|header= Returns if the iterator has reached its end and no more data can be read.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns if the iterator has reached its end and no more data can be read.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        Iterator handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True if iterator has reached the end, false otherwise&lt;br /&gt;
 * @error               Invalid Handle&lt;br /&gt;
 *                      Iterator has been closed (underlying map destroyed)&lt;br /&gt;
 *                      Iterator is outdated&lt;br /&gt;
 */&lt;br /&gt;
native bool:TrieIterEnded(TrieIter:handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|TrieIterNext|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=TrieIterNext|header=Advances the iterator to the next key/value pair if one is available.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Advances the iterator to the next key/value pair if one is available.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        Iterator handle&lt;br /&gt;
 *&lt;br /&gt;
 * @error               Invalid Handle&lt;br /&gt;
 *                      Iterator has been closed (underlying map destroyed)&lt;br /&gt;
 *                      Iterator is outdated&lt;br /&gt;
 */&lt;br /&gt;
native TrieIterNext(TrieIter:handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|TrieIterGetKey|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=TrieIterGetKey|header=Retrieves the key the iterator currently points to.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves the key the iterator currently points to.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        Iterator handle.&lt;br /&gt;
 * @param key           Buffer to store the current key in.&lt;br /&gt;
 * @param outputsize    Maximum size of string buffer.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Nnumber of bytes written to the buffer&lt;br /&gt;
 * @error               Invalid handle&lt;br /&gt;
 *                      Iterator has been closed (underlying map destroyed)&lt;br /&gt;
 *                      Iterator is outdated&lt;br /&gt;
 */&lt;br /&gt;
native TrieIterGetKey(TrieIter:handle, key[], outputsize);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|TrieIterGetSize|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=TrieIterGetSize|header=Retrieves the number of elements in the underlying map.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves the number of elements in the underlying map.&lt;br /&gt;
 *&lt;br /&gt;
 * @note When used on a valid iterator this is exactly the same as calling TrieGetSize on the map directly.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        Iterator handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Number of elements in the map&lt;br /&gt;
 * @error               Invalid handle&lt;br /&gt;
 *                      Iterator has been closed (underlying map destroyed)&lt;br /&gt;
 *                      Iterator is outdated&lt;br /&gt;
 */&lt;br /&gt;
native TrieIterGetSize(TrieIter:handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|TrieIterGetCell|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=TrieIterGetCell|header=Retrieves a value at the current position of the iterator.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves a value at the current position of the iterator.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        Iterator handle&lt;br /&gt;
 * @param value         Variable to store value in&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True on success, false if the iterator is empty or the current&lt;br /&gt;
 *                      value is an array or a string.&lt;br /&gt;
 * @error               Invalid handle&lt;br /&gt;
 *                      Iterator has been closed (underlying map destroyed)&lt;br /&gt;
 *                      Iterator is outdated&lt;br /&gt;
 */&lt;br /&gt;
native bool:TrieIterGetCell(TrieIter:handle, &amp;amp;any:value);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|TrieIterGetString|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=TrieIterGetString|header=Retrieves a string at the current position of the iterator.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves a string at the current position of the iterator.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        Iterator handle&lt;br /&gt;
 * @param buffer        Buffer to store the string in&lt;br /&gt;
 * @param outputsize    Maximum size of string buffer&lt;br /&gt;
 * @param size          Optional parameter to store the number of bytes written to the buffer.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True on success, false if the iterator is empty or the current value&lt;br /&gt;
 *                      is not a string.&lt;br /&gt;
 * @error               Invalid handle&lt;br /&gt;
 *                      Invalid buffer size&lt;br /&gt;
 *                      Iterator has been closed (underlying map destroyed)&lt;br /&gt;
 *                      Iterator is outdated&lt;br /&gt;
 */&lt;br /&gt;
native bool:TrieIterGetString(TrieIter:handle, buffer[], outputsize, &amp;amp;size = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|TrieIterGetArray|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=TrieIterGetArray|header=Retrieves an array at the current position of the iterator.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves an array at the current position of the iterator.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle        Iterator handle&lt;br /&gt;
 * @param buffer        Buffer to store the array&lt;br /&gt;
 * @param outputsize    Maximum size of buffer&lt;br /&gt;
 * @param size          Optional parameter to store the number of bytes written to the buffer&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True on success, false if the iterator is empty or the current&lt;br /&gt;
 *                      value is not an array.&lt;br /&gt;
 * @error               Invalid handle&lt;br /&gt;
 *                      Invalid buffer size&lt;br /&gt;
 *                      Iterator has been closed (underlying map destroyed)&lt;br /&gt;
 *                      Iterator is outdated&lt;br /&gt;
 */&lt;br /&gt;
native bool:TrieIterGetArray(TrieIter:handle, any:array[], outputsize, &amp;amp;size = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|TrieIterDestroy|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=TrieIterDestroy|header=Destroys an iterator handle.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Destroys an iterator handle.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Iterator handle.&lt;br /&gt;
 *&lt;br /&gt;
 * @return          True on success, false if the value was never set.&lt;br /&gt;
 */&lt;br /&gt;
native TrieIterDestroy(&amp;amp;TrieIter:handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
:{{alert|info|Note:|The keys are not sorted.|opt=full-border}}&lt;br /&gt;
:{{alert|success|Example:|{{hidden|id=trie_example_iter|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=trie_example_iter|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public plugin_init()&lt;br /&gt;
{&lt;br /&gt;
    new Trie:list = TrieCreate();&lt;br /&gt;
    {&lt;br /&gt;
        TrieSetString(list, &amp;quot;adventure&amp;quot;, &amp;quot;time!&amp;quot;);&lt;br /&gt;
        TrieSetString(list, &amp;quot;butterflies&amp;quot;, &amp;quot;bees&amp;quot;);&lt;br /&gt;
        TrieSetString(list, &amp;quot;hello&amp;quot;, &amp;quot;world!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    new TrieIter:iter = TrieIterCreate(list);&lt;br /&gt;
    {&lt;br /&gt;
        new key[32], key_length;&lt;br /&gt;
        new value[32], value_length;&lt;br /&gt;
&lt;br /&gt;
        while (!TrieIterEnded(iter))&lt;br /&gt;
        {&lt;br /&gt;
            key_length = TrieIterGetKey(iter, key, charsmax(key));&lt;br /&gt;
            TrieIterGetString(iter, value, charsmax(value), value_length);&lt;br /&gt;
&lt;br /&gt;
            server_print(&amp;quot;%s (%d) -&amp;gt; %s (%d)&amp;quot;, key, key_length, value, value_length);&lt;br /&gt;
&lt;br /&gt;
            // Should throw an error&lt;br /&gt;
            // TrieSetString(t, &amp;quot;monkey&amp;quot;, &amp;quot;island&amp;quot;);&lt;br /&gt;
            // TrieDeleteKey(t, &amp;quot;full&amp;quot;);&lt;br /&gt;
            // TrieClear(t);&lt;br /&gt;
&lt;br /&gt;
            TrieIterNext(iter);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    TrieIterDestroy(iter);&lt;br /&gt;
&lt;br /&gt;
    TrieDestroy(list);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
''' New params '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | parameter&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|TrieSetString|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|TrieSetArray|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|replace|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=trie_new_replace_param|header=Makes operation fail if key already set.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * @param replace   If false the operation will fail if the key is already set&lt;br /&gt;
 */&lt;br /&gt;
native TrieSetCell(Trie:handle, const key[], any:value, bool:replace = true);&lt;br /&gt;
native TrieSetString(Trie:handle, const key[], const value[], bool:replace = true);&lt;br /&gt;
native TrieSetArray(Trie:handle, const key[], const any:buffer[], size, bool:replace = true);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|TrieGetString|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|TrieGetArray|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|size|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=trie_new_size_param|header=Returns the number of bytes written in the buffer.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * @param size          Optional variable to store the number of cells written&lt;br /&gt;
 *                      to the array in&lt;br /&gt;
 */&lt;br /&gt;
native bool:TrieGetString(Trie:handle, const key[], output[], outputsize, &amp;amp;size = 0);&lt;br /&gt;
native bool:TrieGetArray(Trie:handle, const key[], any:output[], outputsize, &amp;amp;size = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Event ===&lt;br /&gt;
&lt;br /&gt;
''' New natives '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|register_event_ex|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=register_event_ex|header=Registers a function to be called on a given game event.&amp;lt;br /&amp;gt;A wrapper of {{tt|register_event|bgcolor=whit}} using flags as strings.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Registers a function to be called on a given game event.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Examples for event conditions:&lt;br /&gt;
 *       &amp;quot;2=c4&amp;quot; - Second parameter of message must be the string &amp;quot;c4&amp;quot;&lt;br /&gt;
 *       &amp;quot;3&amp;gt;10&amp;quot; - Third parameter of message must be greater than 10&lt;br /&gt;
 *       &amp;quot;3!4&amp;quot; - Third parameter of message must not be equal to 4&lt;br /&gt;
 *       &amp;quot;2&amp;amp;Buy&amp;quot; - Second parameter of message must contain &amp;quot;Buy&amp;quot; substring&lt;br /&gt;
 *       &amp;quot;2!Buy&amp;quot; - Second parameter of message must not equal &amp;quot;Buy&amp;quot;&lt;br /&gt;
 * @note Due to a long-standing bug that would break compatibility with older&lt;br /&gt;
 *       plugins, the client id should be checked for alive/dead state if using&lt;br /&gt;
 *       flags &amp;quot;d&amp;quot; or &amp;quot;e&amp;quot;.&lt;br /&gt;
 * @note If multiple conditions are specified for a single parameter, only one&lt;br /&gt;
 *       of them has to hold true for the event function to be called.&lt;br /&gt;
 *&lt;br /&gt;
 * @param event     Name of event that should be hooked&lt;br /&gt;
 * @param function  Name of callback function&lt;br /&gt;
 * @param flags     Flags used for filtering events (enum RegisterEventFlags); the valid flags are:&lt;br /&gt;
 *                    RegisterEvent_Global - Global event (sent to every client)&lt;br /&gt;
 *                    RegisterEvent_Single - Event sent to single client&lt;br /&gt;
 *                    RegisterEvent_OnceForMultiple - Call only once when repeated to multiple clients&lt;br /&gt;
 *                    RegisterEvent_OnlyDead - Call only if sent to dead client&lt;br /&gt;
 *                    RegisterEvent_OnlyAlive - Call only if sent to alive client&lt;br /&gt;
 *                    RegisterEvent_OnlyHuman - Call only if sent to human client (RegisterEvent_Single required)&lt;br /&gt;
 *                    RegisterEvent_OnlyBots - Call only if sent to bot (RegisterEvent_Single required)&lt;br /&gt;
 * @param cond      Condition string used for filtering events, built as:&lt;br /&gt;
 *                  &amp;quot;&amp;lt;argument number&amp;gt;&amp;lt;comparison operator&amp;gt;&amp;lt;value&amp;gt;&amp;quot;&lt;br /&gt;
 *                  Argument number is the argument position to be filtered&lt;br /&gt;
 *                  The comparison operator may be:&lt;br /&gt;
 *                    &amp;quot;=&amp;quot; for equality comparison (all argument types)&lt;br /&gt;
 *                    &amp;quot;!&amp;quot; for inequality comparison (all argument types)&lt;br /&gt;
 *                    &amp;quot;&amp;amp;&amp;quot; for bitwise and (int argument) or substring&lt;br /&gt;
 *                        comparison (string argument)&lt;br /&gt;
 *                    &amp;quot;&amp;lt;&amp;quot; for less than comparison (int/float arguments)&lt;br /&gt;
 *                    &amp;quot;&amp;gt;&amp;quot; for greater than comparison (int/float arguments)&lt;br /&gt;
 *                  The argument is compared to the specified value accordingly&lt;br /&gt;
 * @param ...       Any number of additional conditions&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Event handle&lt;br /&gt;
 * @error           If an invalid event name or callback function is provided,&lt;br /&gt;
 *                  an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native register_event_ex(const event[], const function[], RegisterEventFlags:flags, const cond[] = &amp;quot;&amp;quot;, ...);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|enable_event|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|disable_event|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=enable_event|header=Enables a function hook of a game event which has been previously registered with {{tt|register_event|bgcolor=white}} or {{tt|register_event_ex|bgcolor=white}}.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Enables a function hook of a game event which has been previously registered with register_event and register_event_ex().&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Value returned from register_event() or register_event_ex()&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid handle is provided, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native enable_event(handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=enable-disable_event|header=Disables a function hook of a game event which has been previously registered with {{tt|register_event|bgcolor=white}} or {{tt|register_event_ex|bgcolor=white}}.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Disables a function hook of a game event which has been previously registered with register_event and register_event_ex().&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Value returned from register_event() or register_event_ex()&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid handle is provided, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native disable_event(handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|enable_logevent|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|disable_logevent|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=enable_logevent|header=Enables a function hook of a game log event which has been previously registered with {{tt|register_logevent|bgcolor=white}}.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Enables a function hook of a game log event which has been previously registered with register_logevent().&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Value returned from register_logevent()&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid handle is provided, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native enable_logevent(handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=enable-disable_logevent|header=Disables a function hook of a game log event which has been previously registered with {{tt|register_logevent|bgcolor=white}}.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Disables a function hook of a game log event which has been previously registered with register_logevent().&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle    Value returned from register_logevent()&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid handle is provided, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native disable_logevent(handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' New flags '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | flags&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|register_event|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|&amp;quot;f&amp;quot;|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|&amp;quot;g&amp;quot;|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=register_event_flags|header=Call only if sent to human client (&amp;quot;b&amp;quot; flag required)&amp;lt;br /&amp;gt;Call only if sent to bot (&amp;quot;b&amp;quot; flag required).|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Registers a function to be called on a given game event.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Please consider using register_event_ex() instead which allows you to&lt;br /&gt;
 *       use named constants for flags instead of letters.&lt;br /&gt;
 * @note Examples for event conditions:&lt;br /&gt;
 *       &amp;quot;2=c4&amp;quot; - Second parameter of message must be the string &amp;quot;c4&amp;quot;&lt;br /&gt;
 *       &amp;quot;3&amp;gt;10&amp;quot; - Third parameter of message must be greater than 10&lt;br /&gt;
 *       &amp;quot;3!4&amp;quot; - Third parameter of message must not be equal to 4&lt;br /&gt;
 *       &amp;quot;2&amp;amp;Buy&amp;quot; - Second parameter of message must contain &amp;quot;Buy&amp;quot; substring&lt;br /&gt;
 *       &amp;quot;2!Buy&amp;quot; - Second parameter of message must not equal &amp;quot;Buy&amp;quot;&lt;br /&gt;
 * @note Due to a long-standing bug that would break compatibility with older&lt;br /&gt;
 *       plugins, the client id should be checked for alive/dead state if using&lt;br /&gt;
 *       flags &amp;quot;d&amp;quot; or &amp;quot;e&amp;quot;.&lt;br /&gt;
 * @note If multiple conditions are specified for a single parameter, only one&lt;br /&gt;
 *       of them has to hold true for the event function to be called.&lt;br /&gt;
 *&lt;br /&gt;
 * @param event     Name of event that should be hooked&lt;br /&gt;
 * @param function  Name of callback function&lt;br /&gt;
 * @param flags     Flags used for filtering events, the valid flags are:&lt;br /&gt;
 *                  &amp;quot;a&amp;quot; - Global event (sent to every client)&lt;br /&gt;
 *                  &amp;quot;b&amp;quot; - Event sent to single client&lt;br /&gt;
 *                  &amp;quot;c&amp;quot; - Call only once when repeated to multiple clients&lt;br /&gt;
 *                  &amp;quot;d&amp;quot; - Call only if sent to dead client&lt;br /&gt;
 *                  &amp;quot;e&amp;quot; - Call only if sent to alive client&lt;br /&gt;
 *                  &amp;quot;f&amp;quot; - Call only if sent to human client (&amp;quot;b&amp;quot; flag required)&lt;br /&gt;
 *                  &amp;quot;g&amp;quot; - Call only if sent to bot (&amp;quot;b&amp;quot; flag required)&lt;br /&gt;
 * @param cond      Condition string used for filtering events, built as:&lt;br /&gt;
 *                  &amp;quot;&amp;lt;argument number&amp;gt;&amp;lt;comparison operator&amp;gt;&amp;lt;value&amp;gt;&amp;quot;&lt;br /&gt;
 *                  Argument number is the argument position to be filtered&lt;br /&gt;
 *                  The comparison operator may be:&lt;br /&gt;
 *                    - &amp;quot;=&amp;quot; for equality comparison (all argument types)&lt;br /&gt;
 *                    - &amp;quot;!&amp;quot; for inequality comparison (all argument types)&lt;br /&gt;
 *                    - &amp;quot;&amp;amp;&amp;quot; for bitwise and (int argument) or substring&lt;br /&gt;
 *                      comparison (string argument)&lt;br /&gt;
 *                    - &amp;quot;&amp;lt;&amp;quot; for less than comparison (int/float arguments)&lt;br /&gt;
 *                    - &amp;quot;&amp;gt;&amp;quot; for greater than comparison (int/float arguments)&lt;br /&gt;
 *                  The argument is compared to the specified value accordingly&lt;br /&gt;
 * @param ...       Any number of additional conditions&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Event handle&lt;br /&gt;
 * @error           If an invalid event name or callback function is provided,&lt;br /&gt;
 *                  an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native register_event(const event[], const function[], const flags[], const cond[] = &amp;quot;&amp;quot;, ...);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== File ===&lt;br /&gt;
&lt;br /&gt;
'''Valve FileSystems '''&lt;br /&gt;
&lt;br /&gt;
Thanks to the [https://github.com/alliedmodders/hlsdk/blob/master/public/FileSystem.h IFileSystem] interface from HLSDK, we are now able to make more operations possible with files via Valve File System through Valve search paths (example: download directory). &amp;lt;br /&amp;gt;&lt;br /&gt;
This is handy when you want to deal with files which are not necessary existing directly in the game directory.&lt;br /&gt;
&lt;br /&gt;
Not all natives are concerned. This features some new natives and enhanced others existing ones with small quality of life changes.&lt;br /&gt;
&lt;br /&gt;
''' Valve Paths '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Path ID&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|GAME|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | All paths related to current mod, including fallback. Depending settings, it includes: {{tt|&amp;lt;gamedir&amp;gt;_lv|bgcolor=none}}/{{tt|_addon|bgcolor=none}}/{{tt|_language|bgcolor=none}}/{{tt|_hd|bgcolor=none}} and {{tt|&amp;lt;gamedir&amp;gt;|bgcolor=none}} itself.&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|GAMECONFIG|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | The default writable directory: {{tt|&amp;lt;gamedir&amp;gt;|bgcolor=none}}.&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|GAMEDOWNLOAD|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | The download directory: {{tt|&amp;lt;gamedir&amp;gt;_download|bgcolor=none}}.&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|GAME_FALLBACK|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | All paths related to fallback game, same as {{tt|GAME|bgcolor=none}} (example: {{tt|czero|bgcolor=none}} has {{tt|cstrike|bgcolor=none}} as fallback. Others mods have usually the default game {{tt|valve|bgcolor=none}}, including {{tt|cstrike|bgcolor=none}}).&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|DEFAULTGAME|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | All paths related to the default game which is ''valve'', same as {{tt|GAME|bgcolor=none}}.&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|BASE|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | The base path where server is installed.&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' Native Support '''&lt;br /&gt;
&lt;br /&gt;
Some natives supports partially Valve FS, where a path ID can't be provided and this will search in all paths instead.&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | parameter&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|delete_file|bgcolor=white}} {{tt|unlink|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|file_exists|bgcolor=white}} ''partially''&amp;lt;br /&amp;gt;{{tt|dir_exists|bgcolor=white}} ''partially''&amp;lt;br /&amp;gt;{{tt|file_size|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|fopen|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|mkdir|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|open_dir|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|use_valve_fs|bgcolor=white}} &amp;lt;br /&amp;gt;{{tt|valve_path_id|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=native_fs|header=Uses the Valve file system via a search path from gameinfo.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * @note Registered paths ID are (in priority order) :&lt;br /&gt;
 *         GAME           All paths related to current mod, including fallback&lt;br /&gt;
 *                        Depending settings, it includes: &amp;lt;gamedir&amp;gt;_lv/_addon/_&amp;lt;language&amp;gt;/_hd&lt;br /&gt;
 *                        and &amp;lt;gamedir&amp;gt; itself&lt;br /&gt;
 *         GAMECONFIG     The default writable directory (&amp;lt;gamedir&amp;gt;)&lt;br /&gt;
 *         GAMEDOWNLOAD   The download directory (&amp;lt;gamedir&amp;gt;_download)&lt;br /&gt;
 *         GAME_FALLBACK  All paths related to fallback game, same as GAME&lt;br /&gt;
 *         DEFAULTGAME    All paths related to the default game which is &amp;quot;valve&amp;quot;, same as GAME&lt;br /&gt;
 *         BASE           The base path where server is installed&lt;br /&gt;
 *&lt;br /&gt;
 *         Note that some paths are non-writable. It includes all &amp;lt;gamedir&amp;gt;_* (expect _download)&lt;br /&gt;
 *         and DEFAULTGAME. Any file inside a non-writable path will be ignored if you try to open&lt;br /&gt;
 *         it in writing mode.&lt;br /&gt;
 *&lt;br /&gt;
 * @param use_valve_fs  If true, the Valve file system will be used instead&lt;br /&gt;
 *                      This can be used to finred files existing in valve&lt;br /&gt;
 *                      search paths, rather than solely files existing directly&lt;br /&gt;
 *                      in the gamedir.&lt;br /&gt;
 * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Some natives are not adjusted because not exposed by Valve FS:&lt;br /&gt;
* {{tt|rename_file}}&lt;br /&gt;
* {{tt|rmdir}}&lt;br /&gt;
&lt;br /&gt;
''' New Natives '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|FileReadInt8|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|FileReadUint8|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|FileReadInt16|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|FileReadUint16|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|FileReadInt32|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=FileRead|header=Reads a single value from a file. &amp;lt;br /&amp;gt; More sane and better designed natives to read a single value (proper type, unsigned byte/short support and returns 1 or 0).|labelpos=left|content=&lt;br /&gt;
 &amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Reads a single int8 (byte) from a file. The returned value is sign-&lt;br /&gt;
 * extended to an int32.&lt;br /&gt;
 *&lt;br /&gt;
 * @param file          Handle to the file&lt;br /&gt;
 * @param data          Variable to store the data read&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True on success, false on failure&lt;br /&gt;
 */&lt;br /&gt;
native bool:FileReadInt8(file, &amp;amp;any:data);&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Reads a single uint8 (unsigned byte) from a file. The returned value is&lt;br /&gt;
 * zero-extended to an int32.&lt;br /&gt;
 *&lt;br /&gt;
 * @param file          Handle to the file&lt;br /&gt;
 * @param data          Variable to store the data read&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True on success, false on failure&lt;br /&gt;
 */&lt;br /&gt;
native bool:FileReadUint8(file, &amp;amp;any:data);&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Reads a single int16 (short) from a file. The value is sign-extended to&lt;br /&gt;
 * an int32.&lt;br /&gt;
 *&lt;br /&gt;
 * @param file          Handle to the file&lt;br /&gt;
 * @param data          Variable to store the data read&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True on success, false on failure&lt;br /&gt;
 */&lt;br /&gt;
native bool:FileReadInt16(file, &amp;amp;any:data);&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Reads a single unt16 (unsigned short) from a file. The value is zero-&lt;br /&gt;
 * extended to an int32.&lt;br /&gt;
 *&lt;br /&gt;
 * @param file          Handle to the file&lt;br /&gt;
 * @param data          Variable to store the data read&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True on success, false on failure&lt;br /&gt;
 */&lt;br /&gt;
native bool:FileReadUint16(file, &amp;amp;any:data);&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Reads a single int32 (int/cell) from a file.&lt;br /&gt;
 *&lt;br /&gt;
 * @param file          Handle to the file&lt;br /&gt;
 * @param data          Variable to store the data read&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True on success, false on failure&lt;br /&gt;
 */&lt;br /&gt;
native bool:FileReadInt32(file, &amp;amp;any:data);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|FileWriteInt8|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|FileWriteInt16|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|FileWriteInt32|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=FileWrite|header=Writes a single value from a file. &amp;lt;br /&amp;gt; More sane and better designed natives to write a single value (proper type, unsigned byte/short support and returns 1 or 0).|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Writes a single int8 (byte) to a file.&lt;br /&gt;
 *&lt;br /&gt;
 * @param file          Handle to the file&lt;br /&gt;
 * @param data          Data to write (truncated to an int8)&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True on success, false on failure&lt;br /&gt;
 */&lt;br /&gt;
native bool:FileWriteInt8(file, any:data);&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Writes a single int16 (short) to a file.&lt;br /&gt;
 *&lt;br /&gt;
 * @param file          Handle to the file&lt;br /&gt;
 * @param data          Data to write (truncated to an int16)&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True on success, false on failure&lt;br /&gt;
 */&lt;br /&gt;
native bool:FileWriteInt16(file, any:data);&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Writes a single int32 (int/cell) to a file.&lt;br /&gt;
 *&lt;br /&gt;
 * @param file          Handle to the file&lt;br /&gt;
 * @param data          Data to write&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True on success, false on failure&lt;br /&gt;
 */&lt;br /&gt;
native bool:FileWriteInt32(file, any:data);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|GetFileTime|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=GetFileTime|header=Returns a file timestamp as a unix timestamp. |labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File time modes for use with GetFileTime().&lt;br /&gt;
 */&lt;br /&gt;
enum FileTimeType&lt;br /&gt;
{&lt;br /&gt;
    FileTime_LastAccess,    /* Last access (not available on FAT) */&lt;br /&gt;
    FileTime_Created,       /* Creation (not available on FAT) */&lt;br /&gt;
    FileTime_LastChange,    /* Last modification */&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Returns a file timestamp as a unix timestamp.&lt;br /&gt;
 *&lt;br /&gt;
 * @param file          File name&lt;br /&gt;
 * @param tmode         Time mode, see FileTime_* constants&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Returns a file timestamp as a unix timestamp&lt;br /&gt;
 */&lt;br /&gt;
native GetFileTime(const file[], FileTimeType:tmode);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|SetFilePermissions|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=SetFilePermissions|header=Changes a file or directories permissions.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Changes a file or directories permissions.&lt;br /&gt;
 *&lt;br /&gt;
 * @param path          Path to the file&lt;br /&gt;
 * @param mode          Permissions to set, see FPERM_* constants&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True on success, false otherwise&lt;br /&gt;
 */&lt;br /&gt;
native bool:SetFilePermissions(const path[], mode);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
'''New params'''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | parameter&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|fputs|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|null_term|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=fputs|header=True to append NULL terminator, false otherwise.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Writes a line of text to a text file.&lt;br /&gt;
 *&lt;br /&gt;
 * @param file          Handle to the file&lt;br /&gt;
 * @param text          String to write&lt;br /&gt;
 * @param null_term     True to append NULL terminator, false otherwise&lt;br /&gt;
 *&lt;br /&gt;
 * @return              0 on success, -1 otherwise&lt;br /&gt;
 */&lt;br /&gt;
native fputs(file, const text[], bool:null_term = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|mkdir|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|mode |bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=mkdir|header=Permissions (default is o=rx,g=rx,u=rwx). &amp;lt;br /&amp;gt;Note that folders must have the execute bit set on Linux. &amp;lt;br /&amp;gt;On Windows, the mode is ignored.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Creates a directory.&lt;br /&gt;
 *&lt;br /&gt;
 * @param path          Path to create&lt;br /&gt;
 * @param mode          Permissions (default is o=rx,g=rx,u=rwx).  Note that folders must have&lt;br /&gt;
 *                      the execute bit set on Linux.  On Windows, the mode is ignored.&lt;br /&gt;
 * @param use_valve_fs  If true, the Valve file system will be used instead&lt;br /&gt;
 *                      This can be used to create folders in the game's&lt;br /&gt;
 *                      Valve search paths, rather than directly in the gamedir.&lt;br /&gt;
 * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for default&lt;br /&gt;
 *                      In this case, mode is ignored&lt;br /&gt;
 *&lt;br /&gt;
 * @return              0 on success, -1 otherwise&lt;br /&gt;
 */&lt;br /&gt;
native mkdir(const dirname[], mode = FPERM_DIR_DEFAULT, bool:use_valve_fs = false, const valve_path_id[] = &amp;quot;GAMECONFIG&amp;quot;);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|open_dir|bgcolor=white}} &amp;lt;br /&amp;gt; {{tt|next_file|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|type|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=open_dir-next_file|header=Optional variable to store the file type.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Opens a directory/folder for contents enumeration.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Directories are closed with close_dir().&lt;br /&gt;
 *&lt;br /&gt;
 * @param dir           Path to open.&lt;br /&gt;
 * @param firstfile     String buffer to hold first file name&lt;br /&gt;
 * @param length        Maximum size of the string buffer&lt;br /&gt;
 * @param type          Optional variable to store the file type&lt;br /&gt;
 * @param use_valve_fs  If true, the Valve file system will be used instead.&lt;br /&gt;
 *                      This can be used to find files existing in any of&lt;br /&gt;
 *                      the Valve search paths, rather than solely files&lt;br /&gt;
 *                      existing directly in the gamedir.&lt;br /&gt;
 * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Handle to the directory, 0 otherwise&lt;br /&gt;
 */&lt;br /&gt;
native open_dir(dir[], firstfile[], length, &amp;amp;FileType:type = FileType_Unknown, bool:use_valve_fs = false, const valve_path_id[] = &amp;quot;GAME&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Reads the next directory entry as a local filename.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Contents of buffers are undefined when returning false.&lt;br /&gt;
 * @note Both the '.' and '..' automatic directory entries will be retrieved for Windows and Linux.&lt;br /&gt;
 *&lt;br /&gt;
 * @param dirh          Handle to a directory&lt;br /&gt;
 * @param buffer        String buffer to hold directory name&lt;br /&gt;
 * @param length        Maximum size of string buffer&lt;br /&gt;
 * @param type          Optional variable to store the file type. FileType_* constants&lt;br /&gt;
 *&lt;br /&gt;
 * @return              1 on success, 0 if there are no more files to read.&lt;br /&gt;
 */&lt;br /&gt;
native next_file(dirh, buffer[], length, &amp;amp;FileType:type = FileType_Unknown);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' Others '''&lt;br /&gt;
&lt;br /&gt;
There are as well some minor additions or changes:&lt;br /&gt;
&lt;br /&gt;
* Added a new define {{tt|PLATFORM_MAX_PATH}} {{hidden|id=platform_max_path|labelonly=yes}} to represent a maximum path length.&lt;br /&gt;
{{hidden|id=platform_max_path|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Maximum path length.&lt;br /&gt;
 */&lt;br /&gt;
#define PLATFORM_MAX_PATH  256&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
* Added {{tt|any:}} tag to some natives.&lt;br /&gt;
* {{tt|read_dir}}: {{tt|outlen|bgcolor=none}} parameter is now optional.&lt;br /&gt;
* {{tt|read_file}}: {{tt|txtlen|bgcolor=none}} parameter is now optional. Adjusted as well buffer to 2048 to match buffer size in {{tt|write_file|bgcolor=none}}.&lt;br /&gt;
* {{tt|file_size}}: Fixed potential issue with old compiled plugin which doesn't have the flag parameter. Added {{tt|FSOPT_*|bgcolor=none}} {{hidden|id=fsopt_constants|labelonly=yes}} constants as well for use with this flag parameter.&lt;br /&gt;
{{hidden|id=fsopt_constants|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Options for use with file_size() flag parameter.&lt;br /&gt;
 */&lt;br /&gt;
#define FSOPT_BYTES_COUNT  0  /* Returns the file size in number of bytes */&lt;br /&gt;
#define FSOPT_LINES_COUNT  1  /* Returns how many lines there are in this file */&lt;br /&gt;
#define FSOPT_END_WITH_LF  2  /* Returns whether the last line is '\n' */&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== General ===&lt;br /&gt;
&lt;br /&gt;
''' Constant '''&lt;br /&gt;
&lt;br /&gt;
* {{tt|DMG_GRENADE}} (Counter-Strike only)&lt;br /&gt;
* Three missing {{tt|SVC_}} messages ({{pr|amxx|223}})&lt;br /&gt;
** {{tt|SVC_RESOURCELOCATION}}&lt;br /&gt;
** {{tt|SVC_SENDCVARVALUE}}&lt;br /&gt;
** {{tt|SVC_SENDCVARVALUE2}}&lt;br /&gt;
* Client statistics:&lt;br /&gt;
** {{tt|STATSX_KILLS}}&lt;br /&gt;
** {{tt|STATSX_DEATHS}}&lt;br /&gt;
** {{tt|STATSX_HEADSHOTS}}&lt;br /&gt;
** {{tt|STATSX_TEAMKILLS}}&lt;br /&gt;
** {{tt|STATSX_SHOTS}}&lt;br /&gt;
** {{tt|STATSX_HITS}}&lt;br /&gt;
** {{tt|STATSX_DAMAGE}}&lt;br /&gt;
** {{tt|STATSX_RANK}}&lt;br /&gt;
** {{tt|STATSX_MAX_STATS}}&lt;br /&gt;
* Objective based statistics for CS only:&lt;br /&gt;
** {{tt|STATSX_TOTAL_DEFUSIONS}}&lt;br /&gt;
** {{tt|STATSX_BOMBS_DEFUSED}}&lt;br /&gt;
** {{tt|STATSX_BOMBS_PLANTED}}&lt;br /&gt;
** {{tt|STATSX_BOMB_EXPLOSIONS}}&lt;br /&gt;
** {{tt|STATSX_MAX_OBJECTIVE}}&lt;br /&gt;
* Client statistics for DoD only:&lt;br /&gt;
** {{tt|DODX_KILLS}}&lt;br /&gt;
** {{tt|DODX_DEATHS}}&lt;br /&gt;
** {{tt|DODX_HEADSHOTS}}&lt;br /&gt;
** {{tt|DODX_TEAMKILLS}}&lt;br /&gt;
** {{tt|DODX_SHOTS}}&lt;br /&gt;
** {{tt|DODX_HITS}}&lt;br /&gt;
** {{tt|DODX_DAMAGE}}&lt;br /&gt;
** {{tt|DODX_POINTS}}&lt;br /&gt;
** {{tt|DODX_RANK}}&lt;br /&gt;
** {{tt|DODX_MAX_STATS}}&lt;br /&gt;
&lt;br /&gt;
''' Forward '''&lt;br /&gt;
&lt;br /&gt;
* Added {{tt|FP_VAL_BYREF}} to pass values by reference in forwards.&lt;br /&gt;
* {{tt|ExecuteForward}} can now be called without the need to create variable for returned value.&lt;br /&gt;
&lt;br /&gt;
''' Others '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|has_map_ent_class|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=has_map_ent_class|header=Returns if a map contains at least one entity with the provided class name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns if a map contains at least one entity with the provided class name.&lt;br /&gt;
 *&lt;br /&gt;
 * @param classname     Entity classname to match&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True if an entity is found, false otherwise&lt;br /&gt;
 */&lt;br /&gt;
native bool:has_map_ent_class(const classname[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|engine_changelevel|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=engine_changelevel|header=Changes the map.&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|This has the same behavior as using the &amp;quot;changelevel&amp;quot; server command, but will also trigger the {{tt|server_changelevel|bgcolor=white}} forward in AMXX plugins.&amp;lt;br /&amp;gt;&lt;br /&gt;
It will also notify any Metamod plugins that are hooking the {{tt|pfnChangeLevel|bgcolor=white}} function.|opt=full-border}}&lt;br /&gt;
 |labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Changes the map.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  This calls the pfnChangelLevel engine function.&lt;br /&gt;
 * @note  This has the same behavior as using the &amp;quot;changelevel&amp;quot; server command,&lt;br /&gt;
 *        but will also trigger the server_changelevel() forward in AMXX&lt;br /&gt;
 *        plugins. It will also notify any Metamod plugins that are hooking&lt;br /&gt;
 *        the pfnChangeLevel function.&lt;br /&gt;
 *&lt;br /&gt;
 * @param map   Map name to change to&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native engine_changelevel(const map[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|RequestFrame|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=RequestFrame|header=Creates a single use hook for the next frame.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Creates a single use hook for the next frame.&lt;br /&gt;
 *&lt;br /&gt;
 * @param callback      Function to be executed on the next frame.&lt;br /&gt;
 * @param data          Optional data to be passed to the callback function.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                Callback function prototype:&lt;br /&gt;
 *                          public function(data)&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native RequestFrame(const callback[], any:data = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Stock&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|set_task_ex|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=set_task_ex|header=Calls a function after a specified time has elapsed.&lt;br /&gt;
&lt;br /&gt;
 {{alert|info|Note:|Similar to {{tt|set_task|bgcolor=white}} but it allows you to use named constants for flags instead of letters.|opt=full-border}}&lt;br /&gt;
 |labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * SetTaskFlags constants for set_task_ex()&lt;br /&gt;
 */&lt;br /&gt;
enum SetTaskFlags (&amp;lt;&amp;lt;= 1)&lt;br /&gt;
{&lt;br /&gt;
    SetTask_Once = 0,          // None; execute callback after the specified amount of time (Default)&lt;br /&gt;
    SetTask_RepeatTimes = 1,   // Repeat timer a set amount of times&lt;br /&gt;
    SetTask_Repeat,            // Loop indefinitely until timer is stopped&lt;br /&gt;
    SetTask_AfterMapStart,     // Time interval is treated as absolute time after map start&lt;br /&gt;
    SetTask_BeforeMapChange    // Time interval is treated as absolute time before map change&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Calls a function after a specified time has elapsed.&lt;br /&gt;
 *&lt;br /&gt;
 * @param time          Time interval to assign&lt;br /&gt;
 * @param function      Function to execute&lt;br /&gt;
 * @param id            Task id to assign&lt;br /&gt;
 * @param parameter     Data to pass through to callback&lt;br /&gt;
 * @param len           Size of data&lt;br /&gt;
 * @param flags         Optional flags (enum SetTaskFlags); valid flags are:&lt;br /&gt;
 *                        SetTask_Once - Execute callback once (Default)&lt;br /&gt;
 *                        SetTask_RepeatTimes - repeat timer a set amount of times&lt;br /&gt;
 *                        SetTask_Repeat - loop indefinitely until timer is stopped&lt;br /&gt;
 *                        SetTask_AfterMapStart - time interval is treated as absolute&lt;br /&gt;
 *                            time after map start&lt;br /&gt;
 *                        SetTask_BeforeMapChange - time interval is treated as absolute&lt;br /&gt;
 *                            time before map change&lt;br /&gt;
 * @param repeat        If the SetTask_RepeatTimes flag is set, the task will be repeated this&lt;br /&gt;
 *                      many times&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error               If an invalid callback function is provided, an error is&lt;br /&gt;
 *                      thrown.&lt;br /&gt;
 */&lt;br /&gt;
stock set_task_ex(Float:time, const function[], id = 0, const any:parameter[] = &amp;quot;&amp;quot;, len = 0, SetTaskFlags:flags = SetTask_Once, repeat = 0)&lt;br /&gt;
{&lt;br /&gt;
    new strFlags[2]; // There should never be a need to set more than 1 flag&lt;br /&gt;
    get_flags(_:flags, strFlags, charsmax(strFlags));&lt;br /&gt;
    set_task(time, function, id, parameter, len, strFlags, repeat);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' XS '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Stock&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|xs_vec_len_2d|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=xs_vec_len_2d|header=Computes the length of a 2D vector.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Computes the length of a 2D vector.&lt;br /&gt;
 *&lt;br /&gt;
 * @param vec           The vector to compute the length of.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              The length of the input vector.&lt;br /&gt;
 */&lt;br /&gt;
stock Float:xs_vec_len_2d(const Float:vec[])&lt;br /&gt;
{&lt;br /&gt;
    return xs_sqrt(vec[0]*vec[0] + vec[1]*vec[1]);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|xs_vec_distance|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=xs_vec_distance|header=Computes the distance between two vectors (points).|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Computes the distance between two vectors (points).&lt;br /&gt;
 *&lt;br /&gt;
 * @param vec1          First vector.&lt;br /&gt;
 * @param vec2          Second vector.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              The distance between two vectors.&lt;br /&gt;
 */&lt;br /&gt;
stock Float:xs_vec_distance(const Float:vec1[], const Float:vec2[])&lt;br /&gt;
{&lt;br /&gt;
    return xs_sqrt((vec1[0]-vec2[0]) * (vec1[0]-vec2[0]) +&lt;br /&gt;
                   (vec1[1]-vec2[1]) * (vec1[1]-vec2[1]) +&lt;br /&gt;
                   (vec1[2]-vec2[2]) * (vec1[2]-vec2[2]));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|xs_vec_distance_2d|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=xs_vec_distance_2d|header=Computes the distance between two 2D vectors (points).|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Computes the distance between two 2D vectors (points).&lt;br /&gt;
 * &lt;br /&gt;
 * @param vec1          First vector.&lt;br /&gt;
 * @param vec2          Second vector.&lt;br /&gt;
 * &lt;br /&gt;
 * @return              The distance between two vectors.&lt;br /&gt;
 */&lt;br /&gt;
stock Float:xs_vec_distance_2d(const Float:vec1[], const Float:vec2[])&lt;br /&gt;
{&lt;br /&gt;
    return xs_sqrt((vec1[0]-vec2[0]) * (vec1[0]-vec2[0]) +&lt;br /&gt;
                   (vec1[1]-vec2[1]) * (vec1[1]-vec2[1]));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|xs_vec_add_scaled|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=xs_vec_add_scaled|header=Adds the second vector scaled by a scalar to the first.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Adds the second vector scaled by a scalar to the first.&lt;br /&gt;
 *&lt;br /&gt;
 * @param in1           Vector to add to.&lt;br /&gt;
 * @param in2           Vector to scale and add.&lt;br /&gt;
 * @param scalar        Scalar to scale the second vector with.&lt;br /&gt;
 * @param out           The output vector. Can be one of the input vectors.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
stock xs_vec_add_scaled(const Float:in1[], const Float:in2[], Float:scalar, Float:out[])&lt;br /&gt;
{&lt;br /&gt;
    out[0] = in1[0] + in2[0] * scalar;&lt;br /&gt;
    out[1] = in1[1] + in2[1] * scalar;&lt;br /&gt;
    out[2] = in1[2] + in2[2] * scalar;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|xs_vec_sub_scaled|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=xs_vec_sub_scaled|header=Subtracts the second vector scaled by a scalar from the first one.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Subtracts the second vector scaled by a scalar from the first one.&lt;br /&gt;
 *&lt;br /&gt;
 * @param in1           Vector to subtract from.&lt;br /&gt;
 * @param in2           Vector to scale and subtract.&lt;br /&gt;
 * @param scalar        Scalar to scale the second vector with.&lt;br /&gt;
 * @param out           The output vector. Can be one of the input vectors.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
stock xs_vec_sub_scaled(const Float:in1[], const Float:in2[], Float:scalar, Float:out[])&lt;br /&gt;
{&lt;br /&gt;
    out[0] = in1[0] - in2[0] * scalar;&lt;br /&gt;
    out[1] = in1[1] - in2[1] * scalar;&lt;br /&gt;
    out[2] = in1[2] - in2[2] * scalar;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== Menu ===&lt;br /&gt;
&lt;br /&gt;
''' Timeout '''&lt;br /&gt;
&lt;br /&gt;
Timeout is now added to newmenus, working similar to those of {{tt|show_menu}}.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a menu is acted upon after the specified timeout has run out it will pass a new {{tt|MENU_TIMEOUT}} status code into the menu handler. &amp;lt;br /&amp;gt;&lt;br /&gt;
Actions are: &lt;br /&gt;
* player disconnect&lt;br /&gt;
* selecting an item, &lt;br /&gt;
* cancelling/destroying the menu in the plugin, &lt;br /&gt;
* sending a different menu or using {{tt|get_user_menu}} on a player with an open menu.&lt;br /&gt;
&lt;br /&gt;
Just like with the old menus timeouts are not actively polled, and {{tt|MENU_TIMEOUT}} is not guaranteed to fire directly after the time has run out. &amp;lt;br /&amp;gt;&lt;br /&gt;
Also {{tt|get_user_menu}} will detect timeouts and reset the menu flags, which is why it also has to trigger the callback.&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|An example is available at {{pr|amxx|21}}.|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | parameter&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|menu_display|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|time|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=menu_display|header=If &amp;gt;=0 menu will timeout after this many seconds.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Displays a menu to one client.  This should never be called from a handler &lt;br /&gt;
 * when the item is less than 0 (i.e. calling this from a cancelled menu will &lt;br /&gt;
 * result in an error).&lt;br /&gt;
 *&lt;br /&gt;
 * Starting with 1.8.3 this allows to specify a menu timeout similar to the &lt;br /&gt;
 * show_menu native. If the menu exists on the client past the timeout *any* &lt;br /&gt;
 * further action will send the MENU_TIMEOUT status code to the menu handler.&lt;br /&gt;
 * That includes actions which would otherwise send MENU_EXIT, such as the&lt;br /&gt;
 * client selecting an item or disconnecting and calling menu_cancel or &lt;br /&gt;
 * menu_destroy on a live menu.&lt;br /&gt;
 *&lt;br /&gt;
 * @param id			Client index.&lt;br /&gt;
 * @param menu			Menu resource identifier.&lt;br /&gt;
 * @param page			Page to start from (starting from 0).&lt;br /&gt;
 * @param time			If &amp;gt;=0 menu will timeout after this many seconds&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error				Invalid menu resource or client index.&lt;br /&gt;
 */&lt;br /&gt;
native menu_display(id, menu, page=0, time=-1);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' New native &amp;amp; stock '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|menu_addblank2|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=menu_addblank2|header=Adds a blank line to a menu, always shifting the numbering down.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|This fixes an unexpected behavior with the original ones when slot param is set to 1|opt=full-border}}&lt;br /&gt;
|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Adds a blank line to a menu, always shifting the numbering down.&lt;br /&gt;
 * &lt;br /&gt;
 * This will add a special item to create a blank line. It will affect the menu&lt;br /&gt;
 * item count and pagination. These items can be modified later but will ignore &lt;br /&gt;
 * access and item callback results.&lt;br /&gt;
 * &lt;br /&gt;
 * Only available in 1.8.3 and above.&lt;br /&gt;
 * &lt;br /&gt;
 * @param menu          Menu resource identifier.&lt;br /&gt;
 * &lt;br /&gt;
 * @return              1 on success, 0 on failure.&lt;br /&gt;
 * @error               Invalid menu resource.&lt;br /&gt;
 *                      Too many items on non-paginated menu (max is 10)&lt;br /&gt;
 */&lt;br /&gt;
native menu_addblank2( menu );&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Stock&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|reset_menu|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=reset_menu|header=Resets the client's menu.&lt;br /&gt;
|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Resets the client's menu.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This is a wrapper around show_menu() for the sake of readability.&lt;br /&gt;
 *&lt;br /&gt;
 * @param index     Client to reset menu of, 0 to reset all clients&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
stock reset_menu(index)&lt;br /&gt;
{&lt;br /&gt;
    show_menu(index, 0, &amp;quot;&amp;quot;, 0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' New properties '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Property&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|MEXIT_FORCE|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | Forces a proper exit button on unpaginated menus&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|MPROP_SHOWPAGE|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | Whether to show the page number in menu title&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|MEXIT_FORCE|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | Function to be called on Back and Next&lt;br /&gt;
&lt;br /&gt;
Prototype of callback:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
Called when parsing is halted.&lt;br /&gt;
&lt;br /&gt;
@param id        Playeer's index&lt;br /&gt;
@param status    Either MENU_BACK or MENU_MORE&lt;br /&gt;
&lt;br /&gt;
public function(id, status);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
{{alert|info|Note:|An example is available in the {{tt|testsuite}} directory, see [https://github.com/alliedmodders/amxmodx/blob/master/plugins/testsuite/menu_page_callback_test.sma menu_page_callback_test.sma].|opt=full-border}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' Others '''&lt;br /&gt;
&lt;br /&gt;
* {{tt|menu_item_getinfo}}'s arguments are now optional&lt;br /&gt;
* {{tt|show_menu]}} native is allowed to send empty text&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Message ===&lt;br /&gt;
&lt;br /&gt;
''' New natives '''&lt;br /&gt;
&lt;br /&gt;
The float version of {{tt|message_begin}}, {{tt|write_angle}}, {{tt|write_coord_f}}, {{tt|emessage_begin}}, {{tt|ewrite_coord}} and {{tt|ewrite_angle}}:&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|message_begin_f|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|write_angle_f|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|write_coord_f|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=message_begin_f|header=Marks the beginning of a client message.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Marks the beginning of a client message.&lt;br /&gt;
 *&lt;br /&gt;
 * @note You may generate menus, smoke, shockwaves, thunderlights,&lt;br /&gt;
 *       intermission and many other messages.&lt;br /&gt;
 * @note For a list of HL game events, visit https://wiki.alliedmods.net/Half-Life_1_Game_Events&lt;br /&gt;
 * @note For a list of HL engine messages, visit https://wiki.alliedmods.net/Half-Life_1_Engine_Messages&lt;br /&gt;
 * @note You may also refer to the messages_const.inc file for examples.&lt;br /&gt;
 * @note This function is the same as message_begin(), but the origin&lt;br /&gt;
 *       argument accepts only float values in this one.&lt;br /&gt;
 * @note Each message starts with a message_begin() or message_begin_f() function&lt;br /&gt;
 *       and ends with message_end(). The specific message arguments go in between&lt;br /&gt;
 *       these two by using the write_*() functions found in messages.inc.&lt;br /&gt;
 *&lt;br /&gt;
 * @param dest        Destination type (see MSG_* constants in messages_const.inc)&lt;br /&gt;
 * @param msg_type    Message id&lt;br /&gt;
 * @param origin      Message origin&lt;br /&gt;
 * @param player      Client index receiving the message or 0 for all clients&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error             If an invalid message id is specified or an invalid number&lt;br /&gt;
 *                    of parameters is passed, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native message_begin_f(dest, msg_type, const Float:origin[3] = {0.0,0.0,0.0}, player = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=write_angle_f|header=Writes an angle entry to a message using a float value.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Writes an angle entry to a message using a float value.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This function should only be used in between a message_begin()&lt;br /&gt;
 *       or message_begin_f() and a message_end() function. Trying to use&lt;br /&gt;
 *       it outside of these functions will crash the server immediately.&lt;br /&gt;
 *&lt;br /&gt;
 * @param x           Angle to write&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native write_angle_f(Float:x);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=write_coord_f|header=Writes a coordinate entry to a message using a float value.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Writes a coordinate entry to a message using a float value.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This function should only be used in between a message_begin()&lt;br /&gt;
 *       or message_begin_f() and a message_end() function. Trying to use&lt;br /&gt;
 *       it outside of these functions will crash the server immediately.&lt;br /&gt;
 *&lt;br /&gt;
 * @param x           Coordinate to write&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native write_coord_f(Float:x);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|zmessage_begin_f|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|ewrite_coord_f|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|ewrite_angle_f|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=emessage_begin_f|header=Marks the beginning of a client message.|labelpos=left|content=&lt;br /&gt;
/**&lt;br /&gt;
 * Marks the beginning of a client message.&lt;br /&gt;
 *&lt;br /&gt;
 * @note You may generate menus, smoke, shockwaves, thunderlights,&lt;br /&gt;
 *       intermission and many other messages.&lt;br /&gt;
 * @note For a list of HL game events, visit https://wiki.alliedmods.net/Half-Life_1_Game_Events&lt;br /&gt;
 * @note For a list of HL engine messages, visit https://wiki.alliedmods.net/Half-Life_1_Engine_Messages&lt;br /&gt;
 * @note You may also refer to the messages_const.inc file for examples.&lt;br /&gt;
 * @note This function is the same as message_begin_f(), except that the messages&lt;br /&gt;
 *       sent with this one are also sent to all other AMXX and Metamod plugins.&lt;br /&gt;
 *       This means that if you send one of these messages, other plugins will&lt;br /&gt;
 *       be notified of that message, which was previously impossible.&lt;br /&gt;
 * @note BE CAREFUL! Using this incorrectly, or not for its intended purpose,&lt;br /&gt;
 *       could cause infinite recursion or something just as bad!&lt;br /&gt;
 * @note This function is the same as emessage_begin(), but the origin&lt;br /&gt;
 *       argument accepts only float values in this one.&lt;br /&gt;
 * @note Each message starts with a emessage_begin() or emessage_begin_f() function&lt;br /&gt;
 *       and ends with emessage_end(). The specific message arguments go in between&lt;br /&gt;
 *       these two by using the ewrite_*() functions found in messages.inc.&lt;br /&gt;
 *&lt;br /&gt;
 * @param dest        Destination type (see MSG_* constants in messages_const.inc)&lt;br /&gt;
 * @param msg_type    Message id&lt;br /&gt;
 * @param origin      Message origin&lt;br /&gt;
 * @param player      Client index receiving the message or 0 for all clients&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error             If an invalid message id is specified or an invalid number&lt;br /&gt;
 *                    of parameters is passed, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native emessage_begin_f(dest, msg_type, const Float:origin[3] = {0.0,0.0,0.0}, player = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=ewrite_coord_f|header=Writes a coordinate entry to a message using a float value.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Writes a coordinate entry to a message using a float value.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This function should only be used in between a emessage_begin()&lt;br /&gt;
 *       or emessage_begin_f() and a emessage_end() function. Trying to use&lt;br /&gt;
 *       it outside of these functions will crash the server immediately.&lt;br /&gt;
 *&lt;br /&gt;
 * @param x           Coordinate to write&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native ewrite_coord_f(Float:x);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=ewrite_angle_f|header=Writes an angle entry to a message using a float value.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Writes an angle entry to a message using a float value.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This function should only be used in between a emessage_begin()&lt;br /&gt;
 *       or emessage_begin_f() and a emessage_end() function. Trying to use&lt;br /&gt;
 *       it outside of these functions will crash the server immediately.&lt;br /&gt;
 *&lt;br /&gt;
 * @param x           Angle to write&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native ewrite_angle_f(Float:x);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
 {| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|client_print_color|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=client_print_color|header=Sends colored chat messages to clients.&lt;br /&gt;
 {{alert|info|Note:|Counter-strike only.|opt=full-border}}|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sends colored chat messages to clients.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This only works in Counter-Strike 1.6 and Condition Zero.&lt;br /&gt;
 * @note The colors can be modified inside of the format string using special&lt;br /&gt;
 *       characters. These characters can be included using the escape character&lt;br /&gt;
 *          green           x04   ; use location color from this point forward&lt;br /&gt;
 *          red/blue/grey   x03   ; use team color from this point forward&lt;br /&gt;
 *          red/blue/grey   x02   ; use team color to the end of the client name&lt;br /&gt;
 *                                ; This only works at the start of the string,&lt;br /&gt;
 *                                ; and precludes using other control characters&lt;br /&gt;
 *          default         x01   ; use default color from this point forward&lt;br /&gt;
 * @note The team color is defined by the sender's index. Alternatively, a&lt;br /&gt;
 *       specific team color can be enforced using the print_team_* constants in&lt;br /&gt;
 *       amxconst.inc&lt;br /&gt;
 * @note Usage examples:&lt;br /&gt;
 *       client_print_color(id, print_team_red, &amp;quot;^4Green ^3Red ^1Default&amp;quot;)&lt;br /&gt;
 *       client_print_color(id, id2, &amp;quot;^4Green ^3id2's team color, ^1Default&amp;quot;)&lt;br /&gt;
 * @note Including colors in ML can be done using the same escaping method:&lt;br /&gt;
 *       EXAMPLE_ML_KEY = ^4Green ^3Team color ^1Default&lt;br /&gt;
 * @note This functions return value behaves differently depending on what is&lt;br /&gt;
 *       used as the client index: If 0 is specified, then the function will&lt;br /&gt;
 *       return 0 if nothing has been sent (no client connected). If either a&lt;br /&gt;
 *       single client is specified, or there is at least one client connected,&lt;br /&gt;
 *       the number of printed characters will refer to the message that is sent&lt;br /&gt;
 *       last, to the client with the highest index.&lt;br /&gt;
 *&lt;br /&gt;
 * @param index     Client index, use 0 to display to all clients&lt;br /&gt;
 * @param sender    Client index used as the message sender&lt;br /&gt;
 * @param fmt       Formatting rules&lt;br /&gt;
 * @param ...       Variable number of formatting parameters&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Number of printed characters&lt;br /&gt;
 * @error           If a single client is specified and the index is not within&lt;br /&gt;
 *                  the range of 1 to MaxClients, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native client_print_color(index, sender, const message[], any:...);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|set_dhudmessage|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|show_dhudmessage|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=set_dhudmessage|header= Sets display parameters for director hudmessages.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets display parameters for director hudmessages.&lt;br /&gt;
 *&lt;br /&gt;
 * @note For the hudmessage coordinates x and y, -1.0 will center the message&lt;br /&gt;
 *       on the respective axis.&lt;br /&gt;
 * @note These parameters stay until the next call to set_dhudmessage overwrites&lt;br /&gt;
 *       them. Multiple calls to show_dhudmessage will therefore re-use the same&lt;br /&gt;
 *       parameters. The parameters are not stored per-plugin, so other plugins&lt;br /&gt;
 *       can overwrite them.&lt;br /&gt;
 *&lt;br /&gt;
 * @param red           Red component of hudmessage color&lt;br /&gt;
 * @param green         Green component of hudmessage color&lt;br /&gt;
 * @param blue          Blue component of hudmessage color&lt;br /&gt;
 * @param x             Location of the message on the x axis in percent&lt;br /&gt;
 * @param y             Location of the message on the y axis in percent&lt;br /&gt;
 * @param effects       Display effect&lt;br /&gt;
 * @param fxtime        Duration of the effect&lt;br /&gt;
 * @param holdtime      Time the message stays on screen&lt;br /&gt;
 * @param fadeintime    Time it takes the message to fully appear (fade-in)&lt;br /&gt;
 * @param fadeouttime   Time it takes the message to fully disappear (fade-out)&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native set_dhudmessage(red = 200, green = 100, blue = 0, Float:x = -1.0, Float:y = 0.35, effects = 0, Float:fxtime = 6.0, Float:holdtime = 12.0, Float:fadeintime = 0.1, Float:fadeouttime = 0.2);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=show_dhudmessage|header=Displays a director message on the client HUD.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Displays a director message on the client HUD.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Use set_dhudmessage to define how the message should look on screen.&lt;br /&gt;
 * @note Unlike the classic HUD message, which is channel-based, director&lt;br /&gt;
 *       messages are stack-based. You can have up to 8 messages displaying at&lt;br /&gt;
 *       once. If more are added, they will be overwritten in the order they were&lt;br /&gt;
 *       sent. There is no way to clear a specific message.&lt;br /&gt;
 * @note The message has a maximum length of 128 characters which this function&lt;br /&gt;
 *       will automatically enforce.&lt;br /&gt;
 * @note This functions return value behaves differently depending on what is&lt;br /&gt;
 *       used as the client index: If 0 is specified, then the function will&lt;br /&gt;
 *       return 0 if nothing has been sent (no client connected). If either a&lt;br /&gt;
 *       single client is specified, or there is at least one client connected,&lt;br /&gt;
 *       the number of printed characters will refer to the message that is sent&lt;br /&gt;
 *       last, to the client with the highest index.&lt;br /&gt;
 *&lt;br /&gt;
 * @param index     Client index, use 0 to display to all clients&lt;br /&gt;
 * @param message   Formatting rules&lt;br /&gt;
 * @param ...       Variable number of formatting parameters&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Number of printed characters&lt;br /&gt;
 * @error           If a single client is specified and the index is not within&lt;br /&gt;
 *                  the range of 1 to MaxClients, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native show_dhudmessage(index, const message[], any:...);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|elog_message|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=elog_message|header=Logs a message hookable by plugins to the current server log file.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Logs a message hookable by plugins to the current server log file.&lt;br /&gt;
 *&lt;br /&gt;
 * @note The log will include a timestamp with the message.&lt;br /&gt;
 * @note The message can be hooked using &amp;quot;register_logevent&amp;quot;.&lt;br /&gt;
 *&lt;br /&gt;
 * @param string    Formatting rules&lt;br /&gt;
 * @param ...       Variable number of formatting parameters&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Number of printed characters&lt;br /&gt;
 */&lt;br /&gt;
native elog_message(const message[], any:...);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Stock&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|client_printex|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=client_printex|header=Sends a predefined text message to player.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sends a predefined text message to player.&lt;br /&gt;
 * Predefined texts are default game messages which will be translated&lt;br /&gt;
 * to player's game language, e.g. #Game_join_ct.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Set index to 0 to send text globally.&lt;br /&gt;
 *&lt;br /&gt;
 * @note There does not necessarily have to be a total of 6 arguments.&lt;br /&gt;
 *       It will depend if message takes arguments, e.g.:&lt;br /&gt;
 *         client_printex(id, print_chat, &amp;quot;#Game_join_ct&amp;quot;, &amp;quot;Pimp Daddy&amp;quot;)&lt;br /&gt;
 *         client_printex(id, print_chat, &amp;quot;1&amp;quot;, &amp;quot;#Game_radio&amp;quot;, &amp;quot;Pimp Daddy&amp;quot;, &amp;quot;Hello world!&amp;quot;)&lt;br /&gt;
 *&lt;br /&gt;
 * @param index         Index of the player, use 0 to send to all players.&lt;br /&gt;
 * @param type          The message destination. See print_* constants.&lt;br /&gt;
 * @param msg_name      The custom or predefined message to send.&lt;br /&gt;
 * @param msg_param1    Optional message argument.&lt;br /&gt;
 * @param msg_param2    Optional message argument.&lt;br /&gt;
 * @param msg_param3    Optional message argument.&lt;br /&gt;
 * @param msg_param4    Optional message argument.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
stock client_printex(index, type, const msg_name[], const msg_param1[] = &amp;quot;&amp;quot;, const msg_param2[] = &amp;quot;&amp;quot;, const msg_param3[] = &amp;quot;&amp;quot;, const msg_param4[] = &amp;quot;&amp;quot;)&lt;br /&gt;
{&lt;br /&gt;
    new ch = msg_name[0];&lt;br /&gt;
&lt;br /&gt;
    // If not a predefined message, we don't care about it and forward directly to client_print.&lt;br /&gt;
    // Special case for radio message. msg_name is an index, msg_param1 #Game_radio*, etc. Checking index should be enough.&lt;br /&gt;
    if (ch != '#' &amp;amp;&amp;amp; (type != print_radio || !strtol(msg_name)))&lt;br /&gt;
    {&lt;br /&gt;
        return client_print(index, type, msg_name, msg_param1, msg_param2, msg_param3, msg_param4);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Even if message starts with '#', we should check its length for safety.&lt;br /&gt;
    new length = strlen(msg_name);&lt;br /&gt;
&lt;br /&gt;
    // If string is larger than expected, we forward to client_print which will cut message properly.&lt;br /&gt;
    // This means also this can't be a predefined game message.&lt;br /&gt;
    //   Max console length: 128 = \n (126) + \0 (127)&lt;br /&gt;
    //   Max SayText length: 192 = \n (190) + \0 (191)&lt;br /&gt;
    if ((length &amp;gt; 126 &amp;amp;&amp;amp; (print_notify &amp;lt;= type &amp;lt;= print_console)) &lt;br /&gt;
    || ( length &amp;gt; 190 &amp;amp;&amp;amp; (print_chat   &amp;lt;= type &amp;lt;= print_radio)))&lt;br /&gt;
    {&lt;br /&gt;
        return client_print(index, type, msg_name, msg_param1, msg_param2, msg_param3, msg_param4);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    static msgTextMsg; &lt;br /&gt;
    if (!msgTextMsg) &lt;br /&gt;
    { &lt;br /&gt;
        msgTextMsg = get_user_msgid(&amp;quot;TextMsg&amp;quot;); &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    message_begin(index &amp;gt; 0 ? MSG_ONE_UNRELIABLE : MSG_BROADCAST, msgTextMsg, {0,0,0}, index);&lt;br /&gt;
    write_byte(type);&lt;br /&gt;
    write_string(msg_name);&lt;br /&gt;
    if (msg_param1[0]) { write_string(msg_param1); }&lt;br /&gt;
    if (msg_param2[0]) { write_string(msg_param2); }&lt;br /&gt;
    if (msg_param3[0]) { write_string(msg_param3); }&lt;br /&gt;
    if (msg_param4[0]) { write_string(msg_param4); }&lt;br /&gt;
    message_end();&lt;br /&gt;
    &lt;br /&gt;
    return 1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' Others '''&lt;br /&gt;
&lt;br /&gt;
* Added {{tt|MSG_INIT}} support in {{tt|message_begin}} native&lt;br /&gt;
* Set {{tt|set_hudmessage}} default channel to {{tt|-1}} to reflect auto-channeling support&lt;br /&gt;
&lt;br /&gt;
=== String ===&lt;br /&gt;
&lt;br /&gt;
* Constants and stocks from {{tt|string.inc}} have been moved in their own files {{tt|string_const.inc}} and {{tt|string_stocks.inc}}.&lt;br /&gt;
* {{tt|strlen}} has been moved from {{tt|core.inc}} to {{tt|string.inc}}.&lt;br /&gt;
* {{tt|strbreak}} is now replaced by a backwards compatibility stock.&lt;br /&gt;
&lt;br /&gt;
''' Conversion '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|strtol|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=strtol|header=Parses the {{tt|string|bgcolor=white}} interpreting its content as an integral number of the specified  {{tt|base|bgcolor=white}}, which is returned as integer value. &amp;lt;br /&amp;gt;The function also sets the value of {{tt|endPos|bgcolor=white}} to point to the position of the first character after the number.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Parses the 'string' interpreting its content as an integral number of the specified 'base', &lt;br /&gt;
 * which is returned as integer value. The function also sets the value of 'endPos' to point &lt;br /&gt;
 * to the position of the first character after the number.&lt;br /&gt;
 * &lt;br /&gt;
 * This is the same as C++ strtol function with a difference on second param.&lt;br /&gt;
 * &lt;br /&gt;
 * The function first discards as many whitespace characters as necessary until the first &lt;br /&gt;
 * non-whitespace character is found. Then, starting from this character, takes as many &lt;br /&gt;
 * characters as possible that are valid following a syntax that depends on the 'base' parameter,&lt;br /&gt;
 * and interprets them as a numerical value. Finally, a position of the first character following&lt;br /&gt;
 * the integer representation in 'string' is stored in 'endPos'.&lt;br /&gt;
 * &lt;br /&gt;
 * If the value of 'base' is zero, the syntax expected is similar to that of integer constants, &lt;br /&gt;
 * which is formed by a succession of :&lt;br /&gt;
 *    An optional sign character (+ or -)&lt;br /&gt;
 *    An optional prefix indicating octal or hexadecimal base (&amp;quot;0&amp;quot; or &amp;quot;0x&amp;quot;/&amp;quot;0X&amp;quot; respectively)&lt;br /&gt;
 *    A sequence of decimal digits (if no base prefix was specified) or either octal or hexadecimal digits if a specific prefix is present&lt;br /&gt;
 *&lt;br /&gt;
 * If the 'base' value is between 2 and 36, the format expected for the integral number is a succession &lt;br /&gt;
 * of any of the valid digits and/or letters needed to represent integers of the specified radix &lt;br /&gt;
 * (starting from '0' and up to 'z'/'Z' for radix 36). The sequence may optionally be preceded by &lt;br /&gt;
 * a sign (either + or -) and, if base is 16, an optional &amp;quot;0x&amp;quot; or &amp;quot;0X&amp;quot; prefix.&lt;br /&gt;
 *&lt;br /&gt;
 * If the first sequence of non-whitespace characters in 'string' is not a valid integral number&lt;br /&gt;
 * as defined above, or if no such sequence exists because either 'string' is empty or it contains&lt;br /&gt;
 * only whitespace characters, no conversion is performed.&lt;br /&gt;
 *&lt;br /&gt;
 * @param string    The string to parse.&lt;br /&gt;
 * @param endPos    The position of the first character following the number.&lt;br /&gt;
 *                  On success and when containing only numbers, position is at the end of string, meaning equal to 'string' length.&lt;br /&gt;
 *                  On failure, position is sets always to 0.&lt;br /&gt;
 * @param base      The numerical base (radix) that determines the valid characters and their interpretation.&lt;br /&gt;
 *                  If this is 0, the base used is determined by the format in the sequence.&lt;br /&gt;
 * @return          On success, the function returns the converted integral number as integer value.&lt;br /&gt;
 *                  If no valid conversion could be performed, a zero value is returned.&lt;br /&gt;
 *                  If the value read is out of the range of representable values by a cell, &lt;br /&gt;
 *                  the function returns 'cellmin' or 'cellmax'.&lt;br /&gt;
 */&lt;br /&gt;
native strtol(const string[], &amp;amp;endPos = 0, base = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|strtof|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=strtof|header=Parses the {{tt|string|bgcolor=white}} interpreting its content as an floating point number and returns its value as a float. &amp;lt;br /&amp;gt;The function also sets the value of {{tt|endPos|bgcolor=white}} to point to the position of the first character after the number.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Parses the 'string' interpreting its content as an floating point number and returns its value as a float.&lt;br /&gt;
 * The function also sets the value of 'endPos' to point to the position of the first character after the number.&lt;br /&gt;
 * &lt;br /&gt;
 * This is the same as C++ strtod function with a difference on second param.&lt;br /&gt;
 * &lt;br /&gt;
 * The function first discards as many whitespace characters as necessary until the first &lt;br /&gt;
 * non-whitespace character is found. Then, starting from this character, takes as many &lt;br /&gt;
 * characters as possible that are valid and interprets them as a numerical value. &lt;br /&gt;
 * Finally, a position of the first character following the float representation in 'string' &lt;br /&gt;
 * is stored in 'endPos'.&lt;br /&gt;
 * &lt;br /&gt;
 * If the first sequence of non-whitespace characters in 'string' is not a valid float number&lt;br /&gt;
 * as defined above, or if no such sequence exists because either 'string' is empty or it contains&lt;br /&gt;
 * only whitespace characters, no conversion is performed.&lt;br /&gt;
 *&lt;br /&gt;
 * @param string    The string to parse.&lt;br /&gt;
 * @param endPos    The position of the first character following the number.&lt;br /&gt;
 *                  On success and when containing only numbers, position is at the end of string, meaning equal to 'string' length.&lt;br /&gt;
 *                  On failure, position is sets always to 0.&lt;br /&gt;
 * @return          On success, the function returns the converted floating point number as float value.&lt;br /&gt;
 *                  If no valid conversion could be performed, a zero value is returned.&lt;br /&gt;
 */&lt;br /&gt;
native Float:strtof(const string[], &amp;amp;endPos = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' Format specifier '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Specifier&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|%b|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | Binary digits in the value&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|%n|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | Requires a client index. Expands to a string containing the player's name. &amp;lt;br /&amp;gt;If the client index is 0, the string will be: {{tt|Console}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|%N|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | Requires a client index. Expands to {{tt|1&amp;lt;2&amp;gt;&amp;lt;3&amp;gt;&amp;lt;4&amp;gt;}} where {{tt|1}} is the player's name, {{tt|2}} is the player's userid, {{tt|3}} is the player's SteamID, and {{tt|4}} the player's team name. &amp;lt;br /&amp;gt;If the client index is 0, the string will be: {{tt|Console&amp;lt;0&amp;gt;&amp;lt;Console&amp;gt;&amp;lt;Console&amp;gt;}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|%l|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | Translates a phrase from a key. Similar to {{tt|%L}} with the difference it will use the client's index set internally by the function.&amp;lt;br /&amp;gt;This is only allowed in functions which act directly on one or more clients.&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|To complement this, a new {{hidden|id=SetGlobalTransTarget|labelonly=yes}} {{tt|SetGlobalTransTarget|bgcolor=white}} native to set the current index has been added.&amp;lt;br /&amp;gt;&lt;br /&gt;
This is useful to be used before with natives which are not player-oriented&amp;quot;, like a bunch of {{tt|formatex|bgcolor=whitet}}.|opt=full-border}}&lt;br /&gt;
{{hidden|id=SetGlobalTransTarget|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets the global language target.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This is useful for creating functions&lt;br /&gt;
 *       that will be compatible with the %l format specifier. Note that invalid&lt;br /&gt;
 *       indexes can be specified but the error will occur during translation,&lt;br /&gt;
 *       not during this function call.&lt;br /&gt;
 *&lt;br /&gt;
 * @param client    Client index or LANG_SERVER&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native SetGlobalTransTarget(client);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=trans-l|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=trans-l|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
client_print(index, print_chat, &amp;quot;%L&amp;quot;, index, &amp;quot;EGG&amp;quot;);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
can be now&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
client_print(index, print_chat, &amp;quot;%l&amp;quot;, &amp;quot;EGG&amp;quot;);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' Formatting '''&lt;br /&gt;
&lt;br /&gt;
* {{tt|set_fail_state}} has now the ability to format a text.&lt;br /&gt;
* A new native for simple inline formatting:&lt;br /&gt;
:{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|fmt|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=fmt|header=Formats and returns a string according to the AMX Mod X format rules.&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|This should only be used for simple inline formatting like in the above example. &amp;lt;br /&amp;gt;Avoid using this function to store strings into variables as an additional copying step is required.|opt=full-border}}&lt;br /&gt;
{{alert|info|Note:|The buffer size is defined by {{tt|MAX_FMT_LENGTH}}.|opt=full-border}}&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=menu_additem-ex|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=menu_additem-ex|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
menu_additem(menu, fmt(&amp;quot;My first %s&amp;quot;, &amp;quot;item&amp;quot;))&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Formats and returns a string according to the AMX Mod X format rules&lt;br /&gt;
 * (see documentation).&lt;br /&gt;
 *&lt;br /&gt;
 * @note Example: menu_additem(menu, fmt(&amp;quot;My first %s&amp;quot;, &amp;quot;item&amp;quot;)).&lt;br /&gt;
 * @note This should only be used for simple inline formatting like in the above example.&lt;br /&gt;
 *       Avoid using this function to store strings into variables as an additional&lt;br /&gt;
 *       copying step is required.&lt;br /&gt;
 * @note The buffer size is defined by MAX_FMT_LENGTH.&lt;br /&gt;
 *&lt;br /&gt;
 * @param format        Formatting rules.&lt;br /&gt;
 * @param ...           Variable number of format parameters.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Formatted string&lt;br /&gt;
 */&lt;br /&gt;
native [MAX_FMT_LENGTH]fmt(const format[], any:...);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' Others '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|strtok2|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=strtok2|header=Breaks a string in two by token.&lt;br /&gt;
 &lt;br /&gt;
{{alert|info|Note:|This function has been added due to {{tt|strtok}} being buggy in some situations.|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
 |labelpos=left|content=&lt;br /&gt;
 {{alert|info|Trim flags:|{{hidden|id=trim-flags|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=trim-flags|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Below are the trim flags for strtok2&lt;br /&gt;
 *&lt;br /&gt;
 * You can specify how the left and right buffers will&lt;br /&gt;
 * be trimmed by strtok2. LTRIM trims spaces from the&lt;br /&gt;
 * left side. RTRIM trims from the right side.&lt;br /&gt;
 *&lt;br /&gt;
 * The defines TRIM_INNER, TRIM_OUTER and TRIM_FULL are&lt;br /&gt;
 * shorthands for commonly used flag combinations.&lt;br /&gt;
 *&lt;br /&gt;
 * When the initial string is trimmed, using TRIM_INNER&lt;br /&gt;
 * for all subsequent strtok2 calls will ensure that left&lt;br /&gt;
 * and right are always trimmed from both sides.&lt;br /&gt;
 *&lt;br /&gt;
 * Examples:&lt;br /&gt;
 * str1[] = &amp;quot;  This is  *  some text  &amp;quot;&lt;br /&gt;
 * strtok2(str1, left, 24, right, 24, '*', TRIM_FULL)&lt;br /&gt;
 *  left will be &amp;quot;This is&amp;quot;, right will be &amp;quot;some text&amp;quot;&lt;br /&gt;
 *&lt;br /&gt;
 * str2[] = &amp;quot;  Here is  |  an  | example  &amp;quot;&lt;br /&gt;
 * trim(str2)&lt;br /&gt;
 * strtok2(str2, left, 24, right, 24, '|', TRIM_INNER)&lt;br /&gt;
 *  left will be &amp;quot;Here is&amp;quot;, right will be &amp;quot;an  | example&amp;quot;&lt;br /&gt;
 * strtok2(right, left, 24, right, 24, '|', TRIM_INNER)&lt;br /&gt;
 *  left will be &amp;quot;an&amp;quot;, right will be &amp;quot;example&amp;quot;&lt;br /&gt;
 *&lt;br /&gt;
 * str3[] = &amp;quot;  One  -  more  &amp;quot;&lt;br /&gt;
 * strtok2(str3, left, 24, right, 24, '-', TRIM_OUTER)&lt;br /&gt;
 *  left will be &amp;quot;One  &amp;quot;, right will be &amp;quot;  more&amp;quot;&lt;br /&gt;
 *&lt;br /&gt;
 * str4[] = &amp;quot;  Final  .  example  &amp;quot;&lt;br /&gt;
 * strtok2(str4, left, 24, right, 24, '.', LTRIM_LEFT|LTRIM_RIGHT)&lt;br /&gt;
 *  left will be &amp;quot;Final  &amp;quot;, right will be &amp;quot;example  &amp;quot;&lt;br /&gt;
*/&lt;br /&gt;
#define LTRIM_LEFT (1&amp;lt;&amp;lt;0)&lt;br /&gt;
#define RTRIM_LEFT (1&amp;lt;&amp;lt;1)&lt;br /&gt;
#define LTRIM_RIGHT (1&amp;lt;&amp;lt;2)&lt;br /&gt;
#define RTRIM_RIGHT (1&amp;lt;&amp;lt;3)&lt;br /&gt;
&lt;br /&gt;
#define TRIM_INNER RTRIM_LEFT|LTRIM_RIGHT&lt;br /&gt;
#define TRIM_OUTER LTRIM_LEFT|RTRIM_RIGHT&lt;br /&gt;
#define TRIM_FULL TRIM_OUTER|TRIM_INNER&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Breaks a string in two by token.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Only available in 1.8.3 and above.&lt;br /&gt;
 *&lt;br /&gt;
 * @param text			String to tokenize&lt;br /&gt;
 * @param left			Buffer to store left half&lt;br /&gt;
 * @param llen			Size of left buffer&lt;br /&gt;
 * @param right			Buffer to store right half&lt;br /&gt;
 * @param rlen			Size of right buffer&lt;br /&gt;
 * @param token			Token to split by&lt;br /&gt;
 * @param trim			Flags for trimming behavior, see above&lt;br /&gt;
 *&lt;br /&gt;
 * @return				Returns position of token in string if found, &lt;br /&gt;
 *						-1 if token was not found&lt;br /&gt;
 */&lt;br /&gt;
native strtok2(const text[], left[], const llen, right[], const rlen, const token = ' ', const trim = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Stock&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|explode_string|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=explode_string|header=Breaks a string into pieces and stores each piece into an array of buffers.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Breaks a string into pieces and stores each piece into an array of buffers.&lt;br /&gt;
 *&lt;br /&gt;
 * @param text              The string to split.&lt;br /&gt;
 * @param split             The string to use as a split delimiter.&lt;br /&gt;
 * @param buffers           An array of string buffers (2D array).&lt;br /&gt;
 * @param maxStrings        Number of string buffers (first dimension size).&lt;br /&gt;
 * @param maxStringLength   Maximum length of each string buffer.&lt;br /&gt;
 * @param copyRemainder     False (default) discard excess pieces, true to ignore&lt;br /&gt;
 *                          delimiters after last piece.&lt;br /&gt;
 * @return                  Number of strings retrieved.&lt;br /&gt;
 */&lt;br /&gt;
stock explode_string(const text[], const split[], buffers[][], maxStrings, maxStringLength, bool:copyRemainder = false)&lt;br /&gt;
{&lt;br /&gt;
    new reloc_idx, idx, total;&lt;br /&gt;
&lt;br /&gt;
    if (maxStrings &amp;lt; 1 || !split[0])&lt;br /&gt;
    {&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    while ((idx = split_string(text[reloc_idx], split, buffers[total], maxStringLength)) != -1)&lt;br /&gt;
    {&lt;br /&gt;
        reloc_idx += idx;&lt;br /&gt;
        if (++total == maxStrings)&lt;br /&gt;
        {&lt;br /&gt;
            if (copyRemainder)&lt;br /&gt;
            {&lt;br /&gt;
                copy(buffers[total-1], maxStringLength, text[reloc_idx-idx]);&lt;br /&gt;
            }&lt;br /&gt;
            return total;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    copy(buffers[total++], maxStringLength, text[reloc_idx]);&lt;br /&gt;
&lt;br /&gt;
    return total;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|implode_strings|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=implode_strings|header=Joins an array of strings into one string, with a {{tt|join|bgcolor=white}} string inserted in between each given string.&amp;lt;br /&amp;gt;This function complements {{tt|explode_string|bgcolor=white}}.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Joins an array of strings into one string, with a &amp;quot;join&amp;quot; string inserted in&lt;br /&gt;
 * between each given string.  This function complements ExplodeString.&lt;br /&gt;
 *&lt;br /&gt;
 * @param strings       An array of strings.&lt;br /&gt;
 * @param numStrings    Number of strings in the array.&lt;br /&gt;
 * @param join          The join string to insert between each string.&lt;br /&gt;
 * @param buffer        Output buffer to write the joined string to.&lt;br /&gt;
 * @param maxLength     Maximum length of the output buffer.&lt;br /&gt;
 * @return              Number of bytes written to the output buffer.&lt;br /&gt;
 */&lt;br /&gt;
stock implode_strings(const strings[][], numStrings, const join[], buffer[], maxLength)&lt;br /&gt;
{&lt;br /&gt;
    new total, length, part_length;&lt;br /&gt;
    new join_length = strlen(join);&lt;br /&gt;
&lt;br /&gt;
    for (new i=0; i&amp;lt;numStrings; i++)&lt;br /&gt;
    {&lt;br /&gt;
        length = copy(buffer[total], maxLength-total, strings[i]);&lt;br /&gt;
        total += length;&lt;br /&gt;
&lt;br /&gt;
        if (length &amp;lt; part_length)&lt;br /&gt;
        {&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (i != numStrings - 1)&lt;br /&gt;
        {&lt;br /&gt;
            length = copy(buffer[total], maxLength-total, join);&lt;br /&gt;
            total += length;&lt;br /&gt;
&lt;br /&gt;
            if (length &amp;lt; join_length)&lt;br /&gt;
            {&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return total;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' UTF-8 '''&lt;br /&gt;
&lt;br /&gt;
An effort has been made to provide UTF-8 safety for formatting-capable functions.&lt;br /&gt;
This includes precision with {{tt|%s}} e.g. {{tt|%.12s}}.&lt;br /&gt;
&lt;br /&gt;
Few specific functions have been updated as well:&lt;br /&gt;
&lt;br /&gt;
* {{tt|console_print}}&lt;br /&gt;
* {{tt|client_print}}, {{tt|client_print_color}}&lt;br /&gt;
* {{tt|get_user_name}}&lt;br /&gt;
* {{tt|get_concmd}}, {{tt|get_clcmd}}, {{tt|get_srvcmd}}&lt;br /&gt;
* {{tt|get_cvar_string}}, {{tt|get_pcvar_string}}&lt;br /&gt;
* {{tt|format_time}}&lt;br /&gt;
* {{tt|read_data}}&lt;br /&gt;
* {{tt|get_localinfo}}&lt;br /&gt;
* {{tt|read_argv}}, {{tt|read_args}}&lt;br /&gt;
* {{tt|read_logdata}}, {{tt|read_logargv}}&lt;br /&gt;
* {{tt|get_module}}&lt;br /&gt;
* {{tt|read_file}}&lt;br /&gt;
* {{tt|fgets}}&lt;br /&gt;
* {{tt|ReadPackString}}&lt;br /&gt;
* {{tt|ArrayGetString}}&lt;br /&gt;
* {{tt|TrieGetString}}&lt;br /&gt;
* {{tt|strtok}}, {{tt|strtok2}}&lt;br /&gt;
* {{tt|strbreak}}&lt;br /&gt;
* {{tt|isdigit}}, {{tt|isalnum}}, {{tt|isspace}}, {{tt|isalpha}}&lt;br /&gt;
&lt;br /&gt;
UTF-8 support has been added in the following functions:&lt;br /&gt;
&lt;br /&gt;
* {{tt|containi}}&lt;br /&gt;
* {{tt|strfind}} (with ignorecase set)&lt;br /&gt;
* {{tt|strcmp}} (with ignorecase set)&lt;br /&gt;
* {{tt|strncmp}} (with ignorecase set)&lt;br /&gt;
* {{tt|equali}}&lt;br /&gt;
* {{tt|replace_string}} (with ignorecase set)&lt;br /&gt;
* {{tt|replace_stringex}} (with ignorecase set)&lt;br /&gt;
* {{tt|get_players}} (with name and ignorecase flags set)&lt;br /&gt;
* {{tt|find_player}} (with name and ignorecase flags set)&lt;br /&gt;
&lt;br /&gt;
New natives have been added:&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|is_char_upper|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|is_char_lower|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|is_char_mb|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=is_char_upper|header=Returns whether an alphabetic character is uppercase.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns whether an alphabetic character is uppercase.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Only available in 1.8.3 and above.&lt;br /&gt;
 * @note Multi-byte characters will always return false.&lt;br /&gt;
 *&lt;br /&gt;
 * @param ch			Character to test.&lt;br /&gt;
 * @return				True if character is uppercase, otherwise false.&lt;br /&gt;
 */&lt;br /&gt;
native bool:is_char_upper(ch);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=is_char_lower|header=Returns whether an alphabetic character is lowercase.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns whether an alphabetic character is lowercase.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Only available in 1.8.3 and above.&lt;br /&gt;
 * @note Multi-byte characters will always return false.&lt;br /&gt;
 *&lt;br /&gt;
 * @param ch			Character to test.&lt;br /&gt;
 * @return				True if character is lowercase, otherwise false.&lt;br /&gt;
 */&lt;br /&gt;
native bool:is_char_lower(ch);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=is_char_mb|header=Returns if a character is multi-byte or not.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns if a character is multi-byte or not.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Only available in 1.8.3 and above.&lt;br /&gt;
 *&lt;br /&gt;
 * @param ch			Character to test.&lt;br /&gt;
 * @return				0 for a normal 7-bit ASCII character,&lt;br /&gt;
 *						otherwise number of bytes in multi-byte character.&lt;br /&gt;
 */&lt;br /&gt;
native is_char_mb(ch);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|is_string_category|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=is_string_category|header=Checks if the input string conforms to the category specified by the flags.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Checks if the input string conforms to the category specified by the flags.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This function can be used to check if the code points in a string are part&lt;br /&gt;
 *       of a category. Valid flags are part of the UTF8C_* list of defines.&lt;br /&gt;
 *       The category for a code point is defined as part of the entry in&lt;br /&gt;
 *       UnicodeData.txt, the data file for the Unicode code point database.&lt;br /&gt;
 * @note Flags parameter must be a combination of UTF8C_* flags or a single UTF8C_IS* flag.&lt;br /&gt;
 *       In order to main backwards compatibility with POSIX functions like `isdigit`&lt;br /&gt;
 *       and `isspace`, compatibility flags have been provided. Note, however, that&lt;br /&gt;
 *       the result is only guaranteed to be correct for code points in the Basic&lt;br /&gt;
 *       Latin range, between U+0000 and 0+007F. Combining a compatibility flag with&lt;br /&gt;
 *       a regular category flag will result in undefined behavior.&lt;br /&gt;
 * @note The function is greedy. This means it will try to match as many code&lt;br /&gt;
 *       points with the matching category flags as possible and return the offset in&lt;br /&gt;
 *       the input in bytes.&lt;br /&gt;
 *&lt;br /&gt;
 * @param input         The string to check&lt;br /&gt;
 * @param input_size    Size of the string, use 1 to check one character regardless its size&lt;br /&gt;
 * @param flags         Requested category, see UTF8C_* flags&lt;br /&gt;
 * @param output_size   Number of bytes in the input that conform to the specified&lt;br /&gt;
 *                      category flags&lt;br /&gt;
 * @return              True if the whole input of `input_size` conforms to the specified&lt;br /&gt;
 *                      category flags, false otherwise&lt;br /&gt;
 */&lt;br /&gt;
native bool:is_string_category(const input[], input_size, flags, &amp;amp;output_size = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_char_bytes|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_char_bytes|header=Returns the number of bytes a character is using.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/** &lt;br /&gt;
 * Returns the number of bytes a character is using.  This is&lt;br /&gt;
 * for multi-byte characters (UTF-8).  For normal ASCII characters,&lt;br /&gt;
 * this will return 1.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Only available in 1.8.3 and above.&lt;br /&gt;
 *&lt;br /&gt;
 * @param source		Source input string.&lt;br /&gt;
 * @return				Number of bytes the current character uses.&lt;br /&gt;
 */&lt;br /&gt;
native get_char_bytes(const source[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|mb_strotolower|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|mb_strtoupper|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|mb_ucfirst|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|mb_strtotitle|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=mb_strotolower|header=Performs a multi-byte safe (UTF-8) conversion of all chars in string to lower case.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Performs a multi-byte safe (UTF-8) conversion of all chars in string to lower case.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Although most code points can be converted in-place, there are notable&lt;br /&gt;
 *       exceptions and the final length can vary.&lt;br /&gt;
 * @note Case mapping is not reversible. That is, toUpper(toLower(x)) != toLower(toUpper(x)).&lt;br /&gt;
 *&lt;br /&gt;
 * @param string		The string to convert.&lt;br /&gt;
 * @param maxlength		Optional size of the buffer. If 0, the length of the original string&lt;br /&gt;
 *                      will be used instead.&lt;br /&gt;
 *&lt;br /&gt;
 * @return				Number of bytes written.&lt;br /&gt;
 */&lt;br /&gt;
native mb_strtolower(string[], maxlength = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=mb_strtoupper|header=Performs a multi-byte safe (UTF-8) conversion of all chars in string to upper case.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Performs a multi-byte safe (UTF-8) conversion of all chars in string to upper case.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Although most code points can be converted in-place, there are notable&lt;br /&gt;
 *       exceptions and the final length can vary.&lt;br /&gt;
 * @note Case mapping is not reversible. That is, toUpper(toLower(x)) != toLower(toUpper(x)).&lt;br /&gt;
 *&lt;br /&gt;
 * @param string		The string to convert.&lt;br /&gt;
 * @param maxlength		Optional size of the buffer. If 0, the length of the original string&lt;br /&gt;
 *                      will be used instead.&lt;br /&gt;
 *&lt;br /&gt;
 * @return				Number of bytes written.&lt;br /&gt;
 */&lt;br /&gt;
native mb_strtoupper(string[], maxlength = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=mb_ucfirst|header=Performs a multi-byte safe (UTF-8) conversion of a string's first character to upper case.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Performs a multi-byte safe (UTF-8) conversion of a string's first character to upper case.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Although most code points can be converted in-place, there are notable&lt;br /&gt;
 *       exceptions and the final length can vary.&lt;br /&gt;
 *&lt;br /&gt;
 * @param string		The string to convert.&lt;br /&gt;
 * @param maxlength		Optional size of the buffer. If 0, the length of the original string&lt;br /&gt;
 *                      will be used instead.&lt;br /&gt;
 *&lt;br /&gt;
 * @return				Number of bytes written.&lt;br /&gt;
 */&lt;br /&gt;
native mb_ucfirst(string[], maxlength = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=mb_strtotitle|header=Performs a multi-byte safe (UTF-8) conversion of all chars in string to title case.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Performs a multi-byte safe (UTF-8) conversion of all chars in string to title case.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Although most code points can be converted in-place, there are notable&lt;br /&gt;
 *       exceptions and the final length can vary.&lt;br /&gt;
 * @note Any type of punctuation can break up a word, even if this is&lt;br /&gt;
 *       not grammatically valid. This happens because the titlecasing algorithm&lt;br /&gt;
 *       does not and cannot take grammar rules into account.&lt;br /&gt;
 * @note Examples:&lt;br /&gt;
 *         The running man                      | The Running Man&lt;br /&gt;
 *	       NATO Alliance                        | Nato Alliance&lt;br /&gt;
 *	       You're amazing at building libraries | You'Re Amazing At Building Libraries&lt;br /&gt;
 *&lt;br /&gt;
 * @param string		The string to convert.&lt;br /&gt;
 * @param maxlength		Optional size of the buffer. If 0, the length of the original string&lt;br /&gt;
 *                      will be used instead.&lt;br /&gt;
 *&lt;br /&gt;
 * @return				Number of bytes written.&lt;br /&gt;
 */&lt;br /&gt;
native mb_strtotitle(string[], maxlength = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|replace_string|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|replace_stringex|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=replace_string|header=Given a string, replaces all occurrences of a search string with a replacement string.&lt;br /&gt;
 &lt;br /&gt;
{{alert|info|Note:|Similar to {{tt|replace_all|bgcolor=white}} stock, but implemented as native and with different algorithm.&amp;lt;br /&amp;gt;&lt;br /&gt;
This native doesn't error on bad buffer size and will smartly cut off the string in a way that pushes old data out.|opt=full-border}}&lt;br /&gt;
 |labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Given a string, replaces all occurrences of a search string with a &lt;br /&gt;
 * replacement string.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Similar to replace_all() stock, but implemented as native and &lt;br /&gt;
 *       with different algorithm. This native doesn't error on bad &lt;br /&gt;
 *       buffer size and will smartly cut off the string in a way &lt;br /&gt;
 *       that pushes old data out.&lt;br /&gt;
 *	&lt;br /&gt;
 * @note Only available in 1.8.3 and above.&lt;br /&gt;
 * @note This supports multi-byte characters (UTF-8) on case insensitive comparison.&lt;br /&gt;
 *&lt;br /&gt;
 * @param text			String to perform search and replacements on.&lt;br /&gt;
 * @param maxlength		Maximum length of the string buffer.&lt;br /&gt;
 * @param search		String to search for.&lt;br /&gt;
 * @param replace		String to replace the search string with.&lt;br /&gt;
 * @param caseSensitive	If true (default), search is case sensitive.&lt;br /&gt;
 *&lt;br /&gt;
 * @return				Number of replacements that were performed.&lt;br /&gt;
 */&lt;br /&gt;
native replace_string(text[], maxlength, const search[], const replace[], bool:caseSensitive = true);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=replace_string|header=Given a string, replaces the first occurrence of a search string with a replacement string.&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|Similar to {{tt|replace|bgcolor=white}} native, but implemented as native and with different algorithm.&amp;lt;br /&amp;gt;&lt;br /&gt;
This native doesn't error on bad buffer size and will smartly cut off the string in a way that pushes old data out.|opt=full-border}}&lt;br /&gt;
 |labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Given a string, replaces the first occurrence of a search string with a &lt;br /&gt;
 * replacement string.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Similar to replace() native, but implemented with more options and &lt;br /&gt;
 *       with different algorithm. This native doesn't error on bad &lt;br /&gt;
 *       buffer size and will smartly cut off the string in a way &lt;br /&gt;
 *       that pushes old data out.&lt;br /&gt;
 *	&lt;br /&gt;
 * @note Only available in 1.8.3 and above.&lt;br /&gt;
 * @note This supports multi-byte characters (UTF-8) on case insensitive comparison.&lt;br /&gt;
 *&lt;br /&gt;
 * @param text			String to perform search and replacements on.&lt;br /&gt;
 * @param maxlength		Maximum length of the string buffer.&lt;br /&gt;
 * @param search		String to search for.&lt;br /&gt;
 * @param replace		String to replace the search string with.&lt;br /&gt;
 * @param searchLen		If higher than -1, its value will be used instead of&lt;br /&gt;
 *						a strlen() call on the search parameter.&lt;br /&gt;
 * @param replaceLen	If higher than -1, its value will be used instead of&lt;br /&gt;
 *						a strlen() call on the replace parameter.&lt;br /&gt;
 * @param caseSensitive	If true (default), search is case sensitive.&lt;br /&gt;
 *&lt;br /&gt;
 * @return				Index into the buffer (relative to the start) from where&lt;br /&gt;
 *						the last replacement ended, or -1 if no replacements were&lt;br /&gt;
 *						made.&lt;br /&gt;
 */&lt;br /&gt;
native replace_stringex(text[], maxlength, const search[], const replace[], searchLen = -1, replaceLen = -1, bool:caseSensitive = true);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|strncmp|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=strncmp|header=Compares two strings parts lexographically.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Compares two strings parts lexographically.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Only available in 1.8.3 and above.&lt;br /&gt;
 * @note This supports multi-byte characters (UTF-8) on case insensitive comparison.&lt;br /&gt;
 *&lt;br /&gt;
 * @param string1		First string (left).&lt;br /&gt;
 * @param string2		Second string (right).&lt;br /&gt;
 * @param num			Number of characters to compare.&lt;br /&gt;
 * @param ignorecase	If true, comparison is case insensitive.&lt;br /&gt;
 *						If false (default), comparison is case sensitive.&lt;br /&gt;
 * @return				-1 if string1 &amp;lt; string2&lt;br /&gt;
 *						0 if string1 == string2&lt;br /&gt;
 *						1 if string1 &amp;gt; string2&lt;br /&gt;
 */&lt;br /&gt;
native strncmp(const string1[], const string2[], num, bool:ignorecase = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
New stocks:&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Stock&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|char_to_upper|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=char_to_upper|header=Returns an uppercase character to a lowercase character.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns an uppercase character to a lowercase character.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Only available in 1.8.3 and above.&lt;br /&gt;
 *&lt;br /&gt;
 * @param chr           Characer to convert.&lt;br /&gt;
 * @return              Lowercase character on success,&lt;br /&gt;
 *                      no change on failure.&lt;br /&gt;
 */&lt;br /&gt;
stock char_to_upper(chr)&lt;br /&gt;
{&lt;br /&gt;
    if (is_char_lower(chr))&lt;br /&gt;
    {&lt;br /&gt;
        return (chr &amp;amp; ~(1&amp;lt;&amp;lt;5));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return chr;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|char_to_lower|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=char_to_lower|header=Returns a lowercase character to an uppercase character.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns a lowercase character to an uppercase character.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Only available in 1.8.3 and above.&lt;br /&gt;
 *&lt;br /&gt;
 * @param chr           Characer to convert.&lt;br /&gt;
 * @return              Uppercase character on success,&lt;br /&gt;
 *                      no change on failure.&lt;br /&gt;
 */&lt;br /&gt;
stock char_to_lower(chr)&lt;br /&gt;
{&lt;br /&gt;
    if (is_char_upper(chr))&lt;br /&gt;
    {&lt;br /&gt;
        return (chr | (1&amp;lt;&amp;lt;5));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return chr;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
== Existing module APIs additions ==&lt;br /&gt;
&lt;br /&gt;
=== AMXX SDK ===&lt;br /&gt;
&lt;br /&gt;
the following functions have been added:&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Function&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|MF_SetAmxStringUTF8Char}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | Sets UTF-8 string from char* input&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|MF_SetAmxStringUTF8Cell}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | Sets UTF-8 string from cell* input&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|MF_GetAmxStringNull}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | Gets string with {{tt|NULL_STRING}} support&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|MF_GetAmxVectorNull}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | Gets a vector with {{tt|NULL_VECTOR}} support&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|MF_GetConfigManager}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | Gets the config manager for use with gamedata files&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|MF_LoadAmxScriptEx}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | Saner version of {{tt|MF_LoadAmxScript}} which explicits error max length&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=== CStrike ===&lt;br /&gt;
&lt;br /&gt;
All hardcoded game datas are now moved to its own gamedata file located in {{tt|data/gamedata/modules.games/game.cstrike.txt}}.&amp;lt;br /&amp;gt;&lt;br /&gt;
See [[AMX_Mod_X_1.9_Release_Notes#Gamedata]] for more information.&lt;br /&gt;
&lt;br /&gt;
''' Constant '''&lt;br /&gt;
&lt;br /&gt;
Numerous constants from the game have added. See the [https://github.com/alliedmodders/amxmodx/blob/master/plugins/include/cstrike_const.inc cstrike_const.inc].&lt;br /&gt;
&lt;br /&gt;
Additionally for two natives:&lt;br /&gt;
* {{tt|CS_NORESET}} constant for use with {{tt|cs_set_user_team}} for skipping the model reset&lt;br /&gt;
* {{tt|TRAIN_*}} {{hidden|id=constants_cs|labelonly=yes}} constants for use with {{tt|cs_get_user_driving}}&lt;br /&gt;
&lt;br /&gt;
{{hidden|id=constants_cs|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Train status values&lt;br /&gt;
 */&lt;br /&gt;
#define TRAIN_ACTIVE  0x80&lt;br /&gt;
#define TRAIN_NEW     0xc0&lt;br /&gt;
&lt;br /&gt;
#define TRAIN_OFF     0x00&lt;br /&gt;
#define TRAIN_NEUTRAL 0x01&lt;br /&gt;
#define TRAIN_SLOW    0x02&lt;br /&gt;
#define TRAIN_MEDIUM  0x03&lt;br /&gt;
#define TRAIN_FAST    0x04&lt;br /&gt;
#define TRAIN_BACK    0x05&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''' Entity '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|cs_create_entity|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=cs_create_entity|header=Creates an entity using Counter-Strike's custom CreateNamedEntity wrapper.&lt;br /&gt;
 &lt;br /&gt;
{{alert|info|Note:|Unlike other mods CS keeps track of entities using a custom hashtable.&amp;lt;br /&amp;gt;&lt;br /&gt;
This function adds entities to this hashtable, providing benefits over the default CreateNamedEntity (used by {{tt|create_entity|bgcolor=white}} for example):&lt;br /&gt;
* Storing entities in a hashtable allows CS to improve classname lookup	performance compared to functions like FindEntityByString (used by {{tt|find_ent_by_class|bgcolor=white}} for example) that usually have to loop through all entities incrementally.&lt;br /&gt;
* As CS exclusively uses the hashtable for classname lookup, entities created using the default engine functions will not be found by the game. &amp;lt;br /&amp;gt;For example &amp;quot;weaponbox&amp;quot; entities are supposed to be automatically cleaned up on round restart but are not considered if they have not been added to the hashtable.|opt=full-border}}&lt;br /&gt;
 |labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Creates an entity using Counter-Strike's custom CreateNamedEntity wrapper.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Unlike other mods CS keeps track of entities using a custom hashtable.&lt;br /&gt;
 *       This function adds entities to this hashtable, providing benefits over&lt;br /&gt;
 *       the default CreateNamedEntity (used by create_entity() for example):&lt;br /&gt;
 *       - Storing entities in a hashtable allows CS to improve classname lookup&lt;br /&gt;
 *         performance compared to functions like FindEntityByString (used by&lt;br /&gt;
 *         find_ent_by_class() for example) that usually have to loop&lt;br /&gt;
 *         through all entities incrementally.&lt;br /&gt;
 *       - As CS exclusively uses the hashtable for classname lookup, entities&lt;br /&gt;
 *         created using the default engine functions will not be found by the&lt;br /&gt;
 *         game. For example &amp;quot;weaponbox&amp;quot; entities are supposed to be&lt;br /&gt;
 *         automatically cleaned up on round restart but are not considered if&lt;br /&gt;
 *         they have not been added to the hashtable.&lt;br /&gt;
 * @note The faster hashtable lookup can be utilized with cs_find_ent_by_class()&lt;br /&gt;
 * @note When creating an entity the classname has to be valid in the mod, as&lt;br /&gt;
 *       the engine needs to link the entity to an existing class internally.&lt;br /&gt;
 *       The classname string that is stored in the entvar struct&lt;br /&gt;
 *       (EV_SZ_classname) is separate from this association and can later be&lt;br /&gt;
 *       freely changed to serve other purposes.&lt;br /&gt;
 *&lt;br /&gt;
 * @param classname     Entity class name&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Index of the created entity (&amp;gt; 0), 0 otherwise&lt;br /&gt;
 */&lt;br /&gt;
native cs_create_entity(const classname[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|cs_find_ent_by_class|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|cs_find_ent_by_owner|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=cs_find_ent_by_class|header=Finds an entity in the world using Counter-Strike's custom FindEntityByString wrapper.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Finds an entity in the world using Counter-Strike's custom FindEntityByString&lt;br /&gt;
 * wrapper.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Unlike other mods CS keeps track of entities using a custom hashtable.&lt;br /&gt;
 *       This function utilizes the hasthable and allows for considerably faster&lt;br /&gt;
 *       classname lookup compared to the default FindEntityByString (used by&lt;br /&gt;
 *       find_ent_by_class() for example).&lt;br /&gt;
 * @note This exclusively considers entities in the hashtable, created by the&lt;br /&gt;
 *       game itself, using cs_create_entity(), or added via cs_set_ent_class().&lt;br /&gt;
 *&lt;br /&gt;
 * @param start_index   Entity index to start searching from. -1 to start from&lt;br /&gt;
 *                      the first entity&lt;br /&gt;
 * @param classname     Classname to search for&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Entity index &amp;gt; 0 if found, 0 otherwise&lt;br /&gt;
 */&lt;br /&gt;
native cs_find_ent_by_class(start_index, const classname[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=cs_find_ent_by_owner|header=Finds an entity in the world using Counter-Strike's custom FindEntityByString wrapper, matching by owner. |labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Finds an entity in the world using Counter-Strike's custom FindEntityByString&lt;br /&gt;
 * wrapper, matching by owner.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Unlike other mods CS keeps track of entities using a custom hashtable.&lt;br /&gt;
 *       This function utilizes the hasthable and allows for considerably faster&lt;br /&gt;
 *       classname lookup compared to the default FindEntityByString (used by&lt;br /&gt;
 *       find_ent_by_owner() for example).&lt;br /&gt;
 * @note This exclusively considers entities in the hashtable, created by the&lt;br /&gt;
 *       game itself, using cs_create_entity(), or added via cs_set_ent_class().&lt;br /&gt;
 *&lt;br /&gt;
 * @param start_index   Entity index to start searching from. -1 to start from&lt;br /&gt;
 *                      the first entity&lt;br /&gt;
 * @param classname     Classname to search for&lt;br /&gt;
 * @param owner         Entity index to search for entity's owner&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Entity index &amp;gt; 0 if found, 0 otherwise&lt;br /&gt;
 */&lt;br /&gt;
native cs_find_ent_by_owner(start_index, const classname[], owner);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{alert|info|Note:|Those functions utilize the hasthable and allows for considerably faster classname lookup compared to the default FindEntityByString (used by {{tt|find_ent_by_class|bgcolor=white}} for example).&amp;lt;br /&amp;gt;&lt;br /&gt;
 This exclusively considers entities in the hashtable, created by the game itself, using {{tt|cs_create_entity|bgcolor=white}}, or added via {{tt|cs_set_ent_class|bgcolor=white}}).|opt=full-border}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|cs_set_ent_class|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=cs_set_ent_class|header=Sets a custom classname of an entity.&lt;br /&gt;
 &lt;br /&gt;
 {{alert|info|Note:|This function adds or updates the classname in the hasthable as well.&amp;lt;br /&amp;gt;This is useful for use with {{tt|cs_find_ent_by_class|bgcolor=white}} and {{tt|cs_find_ent_by_owner|bgcolor=white}}.|opt=full-border}}&lt;br /&gt;
 |labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a custom classname of an entity.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Unlike other mods CS keeps track of entities using a custom hashtable.&lt;br /&gt;
 *       This function adds or updates the classname in the hasthable as well.&lt;br /&gt;
 *       This is useful for use with cs_find_ent_by_class() and cs_find_ent_by_owner().&lt;br /&gt;
 *&lt;br /&gt;
 * @param index         Entity index&lt;br /&gt;
 * @param classname     Classname to update for&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native cs_set_ent_class(index, const classname[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' Buying '''&lt;br /&gt;
&lt;br /&gt;
You can now easily detect when an item is being purchased.&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Forward&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|CS_OnBuyAttempt|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=CS_OnBuyAttempt|header=Called when a client attempts to purchase an item.&lt;br /&gt;
 &lt;br /&gt;
{{alert|info|Note:|This is called immediately when the client issues a buy command.&amp;lt;br/&amp;gt;The game has not yet checked if the client can actually buy the weapon.|opt=full-border}}&lt;br /&gt;
 &lt;br /&gt;
 |labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Called when a client attempts to purchase an item.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This is called immediately when the client issues a buy command. The&lt;br /&gt;
 *       game has not yet checked if the client can actually buy the weapon.&lt;br /&gt;
 * @note For a list of possible item ids see the CSI_* constants.&lt;br /&gt;
 *&lt;br /&gt;
 * @param index     Client index&lt;br /&gt;
 * @param item      Item id&lt;br /&gt;
 *&lt;br /&gt;
 * @return          PLUGIN_CONTINUE to let the buy attempt continue&lt;br /&gt;
 *                  PLUGIN_HANDLED to block the buy attempt&lt;br /&gt;
 */&lt;br /&gt;
forward CS_OnBuyAttempt(index, item);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|CS_OnBuy|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=CS_OnBuy|header=Called when a client purchases an item.&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|This is called right before the user receives the item and before the money is deducted from their cash reserves.|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
 |labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Called when a client purchases an item.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This is called right before the user receives the item and before the&lt;br /&gt;
 *       money is deducted from their cash reserves.&lt;br /&gt;
 * @note For a list of possible item ids see the CSI_* constants.&lt;br /&gt;
 *&lt;br /&gt;
 * @param index     Client index&lt;br /&gt;
 * @param item      Item id&lt;br /&gt;
 *&lt;br /&gt;
 * @return          PLUGIN_CONTINUE to let the buy continue&lt;br /&gt;
 *                  PLUGIN_HANDLED to block the buy&lt;br /&gt;
 */&lt;br /&gt;
forward CS_OnBuy(index, item);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|For a list of possible item ids see the {{tt|CSI_*}} {{hidden|id=csi_|labelonly=yes}} constants|opt=full-border}}&lt;br /&gt;
{{hidden|id=csi_|contentonly=yes|content=&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Constants used for the CS_OnBuy() and CS_OnBuyAttempt() forwards.&lt;br /&gt;
 *&lt;br /&gt;
 * @note While these mostly overlap with the CSW_* constants the CSI_* constants&lt;br /&gt;
 *       contain custom AMXX values that do not correspond to any real value in&lt;br /&gt;
 *       the game. The CSI_* constants should therefore be used for consistency.&lt;br /&gt;
 */&lt;br /&gt;
#define CSI_NONE                CSW_NONE&lt;br /&gt;
#define CSI_P228                CSW_P228&lt;br /&gt;
#define CSI_GLOCK               CSW_GLOCK  // Unused by game, See CSI_GLOCK18.&lt;br /&gt;
#define CSI_SCOUT               CSW_SCOUT&lt;br /&gt;
#define CSI_HEGRENADE           CSW_HEGRENADE&lt;br /&gt;
#define CSI_XM1014              CSW_XM1014&lt;br /&gt;
#define CSI_C4                  CSW_C4&lt;br /&gt;
#define CSI_MAC10               CSW_MAC10&lt;br /&gt;
#define CSI_AUG                 CSW_AUG&lt;br /&gt;
#define CSI_SMOKEGRENADE        CSW_SMOKEGRENADE&lt;br /&gt;
#define CSI_ELITE               CSW_ELITE&lt;br /&gt;
#define CSI_FIVESEVEN           CSW_FIVESEVEN&lt;br /&gt;
#define CSI_UMP45               CSW_UMP45&lt;br /&gt;
#define CSI_SG550               CSW_SG550&lt;br /&gt;
#define CSI_GALIL               CSW_GALIL&lt;br /&gt;
#define CSI_FAMAS               CSW_FAMAS&lt;br /&gt;
#define CSI_USP                 CSW_USP&lt;br /&gt;
#define CSI_GLOCK18             CSW_GLOCK18&lt;br /&gt;
#define CSI_P228                 CSW_AWP&lt;br /&gt;
#define CSI_MP5NAVY             CSW_MP5NAVY&lt;br /&gt;
#define CSI_M249                CSW_M249&lt;br /&gt;
#define CSI_M3                  CSW_M3&lt;br /&gt;
#define CSI_M4A1                CSW_M4A1&lt;br /&gt;
#define CSI_TMP                 CSW_TMP&lt;br /&gt;
#define CSI_G3SG1               CSW_G3SG1&lt;br /&gt;
#define CSI_FLASHBANG           CSW_FLASHBANG&lt;br /&gt;
#define CSI_DEAGLE              CSW_DEAGLE&lt;br /&gt;
#define CSI_SG552               CSW_SG552&lt;br /&gt;
#define CSI_AK47                CSW_AK47&lt;br /&gt;
#define CSI_KNIFE               CSW_KNIFE&lt;br /&gt;
#define CSI_P90                 CSW_P90&lt;br /&gt;
#define CSI_SHIELDGUN           CSW_SHIELDGUN   // The real CS value, use CSI_SHELD instead.&lt;br /&gt;
#define CSI_VEST                CSW_VEST        // Custom&lt;br /&gt;
#define CSI_VESTHELM            CSW_VESTHELM    // Custom&lt;br /&gt;
#define CSI_DEFUSER             33              // Custom&lt;br /&gt;
#define CSI_NVGS                34              // Custom&lt;br /&gt;
#define CSI_SHIELD              35              // Custom - The value passed by the forward, more convenient for plugins.&lt;br /&gt;
#define CSI_PRIAMMO             36              // Custom&lt;br /&gt;
#define CSI_SECAMMO             37              // Custom&lt;br /&gt;
#define CSI_MAX_COUNT           38&lt;br /&gt;
#define CSI_LAST_WEAPON         CSW_LAST_WEAPON&lt;br /&gt;
&lt;br /&gt;
#define CSI_ALL_WEAPONS         CSW_ALL_WEAPONS&lt;br /&gt;
#define CSI_ALL_PISTOLS         CSW_ALL_PISTOLS&lt;br /&gt;
#define CSI_ALL_SHOTGUNS        CSW_ALL_SHOTGUNS&lt;br /&gt;
#define CSI_ALL_SMGS            CSW_ALL_SMGS&lt;br /&gt;
#define CSI_ALL_RIFLES          CSW_ALL_RIFLES&lt;br /&gt;
#define CSI_ALL_SNIPERRIFLES    CSW_ALL_SNIPERRIFLES&lt;br /&gt;
#define CSI_ALL_MACHINEGUNS     CSW_ALL_MACHINEGUNS&lt;br /&gt;
#define CSI_ALL_GRENADES        CSW_ALL_GRENADES&lt;br /&gt;
#define CSI_ALL_ARMORS          CSW_ALL_ARMORS&lt;br /&gt;
#define CSI_ALL_GUNS            CSW_ALL_GUNS&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=array_cloning_ex|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=array_cloning_ex|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
#include &amp;lt;cstrike&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public CS_OnBuyAttempt(index, item)&lt;br /&gt;
{&lt;br /&gt;
    if (item == CSI_AWP)&lt;br /&gt;
    {&lt;br /&gt;
        client_print(index, print_chat, &amp;quot;You tried to buy an AWP.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        return PLUGIN_HANDLED; // &amp;lt;-- Use this to block a buying&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public CS_OnBuy(index, item)&lt;br /&gt;
{&lt;br /&gt;
    if (item == CSI_DEAGLE)&lt;br /&gt;
    {&lt;br /&gt;
        client_print(index, print_chat, &amp;quot;You just bought a deagle and you're about to receive it.&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
''' Items info '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|cs_get_user_weapon_entity|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=cs_get_user_weapon_entity|header=Returns active weapon entity.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns active weapon entity.&lt;br /&gt;
 *&lt;br /&gt;
 * @param playerIndex   Player index&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Weapon entity index on success or 0 if there is no active weapon&lt;br /&gt;
 * @error               If the client index is not within the range of 1 to&lt;br /&gt;
 *                      maxClients, or the client is not connected, an error will be&lt;br /&gt;
 *                      thrown.&lt;br /&gt;
 */&lt;br /&gt;
native cs_get_user_weapon_entity(playerIndex);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|cs_get_user_weapon|bgcolor=white}} &lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=cs_get_user_weapon_entity|header=Returns weapon index of the active weapon.&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|More reliable than {{tt|get_user_weapon|bgcolor=white}}.|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns weapon index of the active weapon.&lt;br /&gt;
 *&lt;br /&gt;
 * @note More reliable than get_user_weapon.&lt;br /&gt;
 *&lt;br /&gt;
 * @param playerIndex   Player index&lt;br /&gt;
 * @param clip          Optional variable to store clip ammo to&lt;br /&gt;
 * @param ammo          Optional variable to store backpack ammo to&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Weapon index on success or 0 if there is no active weapon&lt;br /&gt;
 * @error               If the client index is not within the range of 1 to&lt;br /&gt;
 *                      maxClients, or the client is not connected, an error will be&lt;br /&gt;
 *                      thrown.&lt;br /&gt;
 */&lt;br /&gt;
native cs_get_user_weapon(playerIndex, &amp;amp;clip = 0, &amp;amp;ammo = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|cs_get_item_id|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=cs_get_item_id|header=Returns the item id associated with an item name and its aliases.&lt;br /&gt;
 &lt;br /&gt;
{{alert|info|Note:|The item name is case sensitive an can be with or without {{tt|weapon_|bgcolor=white}} and {{tt|item_|bgcolor=white}} prefixes. This can be a command alias as well.&amp;lt;br /&amp;gt;&lt;br /&gt;
Values examples: {{tt|ak47|bgcolor=white}}, {{tt|weapon_ak47|bgcolor=white}}, {{tt|kevlar|bgcolor=white}}, {{tt|item_kevlar|bgcolor=white}}, {{tt|vest|bgcolor=white}}, {{tt|bullpup|bgcolor=white}}, ...|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
 |labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns the item id associated with an item name and its aliases.&lt;br /&gt;
 *&lt;br /&gt;
 * @note The item name is case sensitive an can be with or without &lt;br /&gt;
 *       weapon_ and item_ prefixes. This can be a command alias as well.&lt;br /&gt;
 *       Values examples: ak47, weapon_ak47, kevlar, item_kevlar, vest, bullpup, ...&lt;br /&gt;
 *&lt;br /&gt;
 * @param name          Alias or classname&lt;br /&gt;
 * @param classid       If item is a weapon, variable to store the associated &lt;br /&gt;
 *                      weapon class id in (CS_WEAPONCLASS_* constants)&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Item id (CSI_* constants)&lt;br /&gt;
 */&lt;br /&gt;
native any:cs_get_item_id(const name[], &amp;amp;CsWeaponClassType:classid = CS_WEAPONCLASS_NONE);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|cs_get_translated_item_alias|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=cs_get_translated_item_alias|header=Returns an item name associated with a command alias.&lt;br /&gt;
 &lt;br /&gt;
{{alert|info|Note:|The alias is case sensitive.|opt=full-border}}&lt;br /&gt;
{{alert|info|Note:|If not an alias to a weapon, buffer will be set with the original alias.|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
 |labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns an item name associated with a command alias.&lt;br /&gt;
 *&lt;br /&gt;
 * @note The alias is case sensitive.&lt;br /&gt;
 * @note If not an alias to a weapon, buffer will be set with the original alias.&lt;br /&gt;
 *&lt;br /&gt;
 * @param alias         Alias name&lt;br /&gt;
 * @param itemname      Buffer to store item name to&lt;br /&gt;
 * @param maxlength     Maximum buffer size&lt;br /&gt;
 *&lt;br /&gt;
 * @return              True if alias is translated, false otherwise&lt;br /&gt;
 */&lt;br /&gt;
native bool:cs_get_translated_item_alias(const alias[], itemname[], maxlength);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|cs_get_item_alias|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=cs_get_item_alias|header=Returns the alias name associated with an item index.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns the alias name associated with an item index.&lt;br /&gt;
 *&lt;br /&gt;
 * @param itemid          Item id (CSI_* constants)&lt;br /&gt;
 * @param name            Buffer to store alias name to&lt;br /&gt;
 * @param name_maxlen     Maximum buffer size&lt;br /&gt;
 * @param altname         Optional buffer to store if available alternative alias name to&lt;br /&gt;
 * @param altname_maxlen  Maximum buffer size&lt;br /&gt;
 *&lt;br /&gt;
 * @return                True if alias is found, false otherwise&lt;br /&gt;
 */&lt;br /&gt;
native bool:cs_get_item_alias(itemid, name[], name_maxlen, altname[] = &amp;quot;&amp;quot;, altname_maxlen = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|cs_get_weapon_info|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=cs_get_weapon_info|header=Returns some information about a weapon.&lt;br /&gt;
 &lt;br /&gt;
{{alert|info|Note:|The alias is case sensitive.|opt=full-border}}&lt;br /&gt;
{{alert|info|Note:|If not an alias to a weapon, buffer will be set with the original alias.|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
 |labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Weapon info types for use with cs_get_weapon_info().&lt;br /&gt;
 */&lt;br /&gt;
enum CsWeaponInfo&lt;br /&gt;
{&lt;br /&gt;
	CS_WEAPONINFO_COST          = 0,&lt;br /&gt;
	CS_WEAPONINFO_CLIP_COST     = 1,&lt;br /&gt;
	CS_WEAPONINFO_BUY_CLIP_SIZE = 2,&lt;br /&gt;
	CS_WEAPONINFO_GUN_CLIP_SIZE = 3,&lt;br /&gt;
	CS_WEAPONINFO_MAX_ROUNDS    = 4,&lt;br /&gt;
	CS_WEAPONINFO_AMMO_TYPE     = 5,&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Returns some information about a weapon.&lt;br /&gt;
 *&lt;br /&gt;
 * @param weapon_id     Weapon id, see CSW_* constants&lt;br /&gt;
 * @param type          Info type, see CS_WEAPONINFO_* constants&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Weapon information value&lt;br /&gt;
 * @error               If weapon_id and type are out of bound, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native any:cs_get_weapon_info(weapon_id, CsWeaponInfo:type);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Stock&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|cs_get_weapon_class|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=cs_get_weapon_class|header=Returns a weapon class id associated with a weapon id.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns a weapon class id associated with a weapon id.&lt;br /&gt;
 *&lt;br /&gt;
 * @param weapon_id     Weapon id (CSI_* constants)&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Weapon class id (CS_WEAPONCLASS_* constants)&lt;br /&gt;
 */&lt;br /&gt;
stock CsWeaponClassType:cs_get_weapon_class(weapon_id)&lt;br /&gt;
{&lt;br /&gt;
	new CsWeaponClassType:type = CS_WEAPONCLASS_NONE;&lt;br /&gt;
&lt;br /&gt;
	if (cs_is_valid_itemid(weapon_id, .weapon_only = true) || weapon_id == CSI_SHIELD)&lt;br /&gt;
	{&lt;br /&gt;
		switch (weapon_id)&lt;br /&gt;
		{&lt;br /&gt;
			case CSI_SHIELDGUN, CSI_SHIELD: &lt;br /&gt;
			{&lt;br /&gt;
				type = CS_WEAPONCLASS_PISTOL;&lt;br /&gt;
			}&lt;br /&gt;
			case CSI_KNIFE: &lt;br /&gt;
			{&lt;br /&gt;
				type = CS_WEAPONCLASS_KNIFE;&lt;br /&gt;
			}&lt;br /&gt;
			default:&lt;br /&gt;
			{&lt;br /&gt;
				new const bits = (1 &amp;lt;&amp;lt; weapon_id);&lt;br /&gt;
&lt;br /&gt;
				if(bits &amp;amp; CSI_ALL_PISTOLS)&lt;br /&gt;
				{&lt;br /&gt;
					type = CS_WEAPONCLASS_PISTOL;&lt;br /&gt;
				}&lt;br /&gt;
				else if(bits &amp;amp; CSI_ALL_GRENADES)&lt;br /&gt;
				{&lt;br /&gt;
					type = CS_WEAPONCLASS_GRENADE;&lt;br /&gt;
				}&lt;br /&gt;
				else if(bits &amp;amp; CSI_ALL_SMGS)&lt;br /&gt;
				{&lt;br /&gt;
					type = CS_WEAPONCLASS_SUBMACHINEGUN;&lt;br /&gt;
				}&lt;br /&gt;
				else if(bits &amp;amp; CSI_ALL_SHOTGUNS)&lt;br /&gt;
				{&lt;br /&gt;
					type = CS_WEAPONCLASS_SHOTGUN;&lt;br /&gt;
				}&lt;br /&gt;
				else if(bits &amp;amp; CSI_ALL_MACHINEGUNS)&lt;br /&gt;
				{&lt;br /&gt;
					type = CS_WEAPONCLASS_MACHINEGUN;&lt;br /&gt;
				}&lt;br /&gt;
				else if(bits &amp;amp; CSI_ALL_RIFLES)&lt;br /&gt;
				{&lt;br /&gt;
					type = CS_WEAPONCLASS_RIFLE;&lt;br /&gt;
				}&lt;br /&gt;
				else if(bits &amp;amp; CSI_ALL_SNIPERRIFLES)&lt;br /&gt;
				{&lt;br /&gt;
					type = CS_WEAPONCLASS_SNIPERRIFLE;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return type;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|cs_is_valid_itemid|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=cs_is_valid_itemid|header=Checks whether an item id is not out of bounds.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Checks whether an item id is not out of bounds.&lt;br /&gt;
 *&lt;br /&gt;
 * @param id           Item id (CSI_* constants) &lt;br /&gt;
 * @param weapon_only  If true, only the real weapon ids will be checked,&lt;br /&gt;
 *                     including shield as well &lt;br /&gt;
 *&lt;br /&gt;
 * @return             True if item id is valid, false otherwise&lt;br /&gt;
 */&lt;br /&gt;
stock bool:cs_is_valid_itemid(id, bool:weapon_only = false)&lt;br /&gt;
{&lt;br /&gt;
	if (id &amp;lt;= CSI_NONE)&lt;br /&gt;
	{&lt;br /&gt;
		return false;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (id &amp;gt; CSI_LAST_WEAPON &amp;amp;&amp;amp; id != CSI_SHIELDGUN &amp;amp;&amp;amp; weapon_only)&lt;br /&gt;
	{&lt;br /&gt;
		return false;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (id &amp;gt;= CSI_MAX_COUNT)&lt;br /&gt;
	{&lt;br /&gt;
		return false;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' New params '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Forward&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Parameter&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|cs_set_user_deaths|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|scoreboard|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=CS_OnBuyAttempt|header=If true the scoreboard will be updated to reflect the new value.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets client's deaths.&lt;br /&gt;
 *&lt;br /&gt;
 * @param index         Client index&lt;br /&gt;
 * @param newdeaths     New value to set&lt;br /&gt;
 * @param scoreboard    If true the scoreboard will be updated to reflect the new value.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error               If the client index is not within the range of 1 to&lt;br /&gt;
 *                      MaxClients, or the client is not connected, an error&lt;br /&gt;
 *                      will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native cs_set_user_deaths(index, newdeaths, bool:scoreboard = true);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|cs_get_armoury_type|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|cs_set_armoury_type|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|count|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=cs_getset_armoury_type|header=Optional variable to store in the number of times that an item can be retrieved from the same entity before being hidden.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns the armoury entity's weapon id.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Not all weapon ids are supported by Counter-Strike, an armoury entity&lt;br /&gt;
 *       can not be a pistol, a knife or a bomb for exmaple. The full list is:&lt;br /&gt;
 *          CSW_SCOUT, CSW_HEGRENADE, CSW_XM1014, CSW_MAC10, CSW_AUG,&lt;br /&gt;
 *          CSW_SMOKEGRENADE, CSW_AWP, CSW_MP5NAVY, CSW_M249, CSW_M3, CSW_M4A1,&lt;br /&gt;
 *          CSW_TMP, CSW_G3SG1, CSW_VEST, CSW_VESTHELM, CSW_FLASHBANG,&lt;br /&gt;
 *          CSW_SG552, CSW_AK47, CSW_P90&lt;br /&gt;
 *&lt;br /&gt;
 * @param index     Armoury entity index&lt;br /&gt;
 * @param count     Optional variable to store in the number of times that an item can be retrieved  &lt;br /&gt;
 *                  from the same entity before being hidden&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Weapon id&lt;br /&gt;
 * @error           If a non-armoury entity is provided, an error will be&lt;br /&gt;
 *                  thrown.&lt;br /&gt;
 */&lt;br /&gt;
native cs_get_armoury_type(index, &amp;amp;count = 1);&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Sets the amoury entity type.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Not all weapon ids are supported by Counter-Strike, an armoury entity&lt;br /&gt;
 *       can not be a pistol, a knife or a bomb for exmaple. The full list is:&lt;br /&gt;
 *          CSW_SCOUT, CSW_HEGRENADE, CSW_XM1014, CSW_MAC10, CSW_AUG,&lt;br /&gt;
 *          CSW_SMOKEGRENADE, CSW_AWP, CSW_MP5NAVY, CSW_M249, CSW_M3, CSW_M4A1,&lt;br /&gt;
 *          CSW_TMP, CSW_G3SG1, CSW_VEST, CSW_VESTHELM, CSW_FLASHBANG,&lt;br /&gt;
 *          CSW_SG552, CSW_AK47, CSW_P90&lt;br /&gt;
 * @note This does not update the entity model.&lt;br /&gt;
 * @note On restart, entity is always unhidden and the count is restored (this can not be below 1).&lt;br /&gt;
 *&lt;br /&gt;
 * @param index     Armoury entity index&lt;br /&gt;
 * @param type      Weapon id&lt;br /&gt;
 * @param count     Number of times that an item can be retrieved from &lt;br /&gt;
 *                  the same entity before being hidden&lt;br /&gt;
 *                  If zero, the entity is hidden&lt;br /&gt;
 *                  If below zero, nothing is set&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If a non-armoury entity is provided, an error will be&lt;br /&gt;
 *                  thrown.&lt;br /&gt;
 */&lt;br /&gt;
native cs_set_armoury_type(index, type, count = -1);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|cs_set_user_model|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|update_index|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=cs_set_user_model|header= If true, the modelindex is updated as well.&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|Updating modelindex is useful for custom models which don't have the same structure as the default ones (hitbox, etc..).&amp;lt;br /&amp;gt;Model must be precached before|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
 |labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets the client's player model.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This is not a one-time set. The CStrike module will remember the&lt;br /&gt;
 *       selected model and try to prevent attempts at changing the player&lt;br /&gt;
 *       model, or immediately re-apply it if necessary.&lt;br /&gt;
 * @note Updating modelindex is useful for custom models which don't have &lt;br /&gt;
 *       the same structure as the default ones (hitbox, etc..). Model must &lt;br /&gt;
 *       be precached before.&lt;br /&gt;
 *&lt;br /&gt;
 * @param index           Client index&lt;br /&gt;
 * @param model           Model name&lt;br /&gt;
 * @param update_index    If true, the modelindex is updated as well&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error                 If the client index is not within the range of 1 to&lt;br /&gt;
 *                        MaxClients, the client is not connected, the provided&lt;br /&gt;
 *                        model is empty, or if modeindex is updated and the &lt;br /&gt;
 *                        provided model is not precached, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native cs_set_user_model(index, const model[], bool:update_index = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' Others '''&lt;br /&gt;
&lt;br /&gt;
* Hostage natives will work now with {{tt|monster_scientist}} entity (alias of {{tt|hostage_entity}})&lt;br /&gt;
* {{tt|cs_get_user_armor}} {{armortype}} parameter is now optional&lt;br /&gt;
* {{tt|cs_set_weapon_silen}} {{draw_animation}} has a new value of 2 which follows game behavior to properly draw the animation&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Engine ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''' Entity '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|entity_intersects|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=entity_intersects|header=Returns if two entities bounding boxes intersect by comparing their absolute minimum and maximum origins.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns if two entities bounding boxes intersect by comparing their absolute&lt;br /&gt;
 * minimum and maximum origins.&lt;br /&gt;
 *&lt;br /&gt;
 * @param entity    Entity index 1&lt;br /&gt;
 * @param other     Entity index 2&lt;br /&gt;
 *&lt;br /&gt;
 * @return          True if entities intersect, false otherwise&lt;br /&gt;
 * @error           If an invalid entity index is provided, an error will be&lt;br /&gt;
 *                  thrown.&lt;br /&gt;
 */&lt;br /&gt;
native bool:entity_intersects(entity, other);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|set_ent_rendering|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=set_ent_rendering|header=Sets rendering options of an entity.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets rendering options of an entity.&lt;br /&gt;
 *&lt;br /&gt;
 * @note For a list of valid rendering effects see the kRenderFx* constants in&lt;br /&gt;
 *       amxconst.inc&lt;br /&gt;
 * @note For a list of valid rendering modes see the kRender* constants in&lt;br /&gt;
 *       amxconst.inc&lt;br /&gt;
 * @note Rendering amount has different meanings depending on the rendering&lt;br /&gt;
 *       effect and mode used on the entity.&lt;br /&gt;
 *&lt;br /&gt;
 * @param index     Entity index&lt;br /&gt;
 * @param fx        Rendering effect&lt;br /&gt;
 * @param r         Red component of rendering color&lt;br /&gt;
 * @param g         Green component of rendering color&lt;br /&gt;
 * @param b         Blue component of rendering color&lt;br /&gt;
 * @param render    Rendering mode&lt;br /&gt;
 * @param amount    Rendering amount&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid entity index is provided, an error will be&lt;br /&gt;
 *                  thrown.&lt;br /&gt;
 */&lt;br /&gt;
native set_ent_rendering(index, fx = kRenderFxNone, r = 0, g = 0, b = 0, render = kRenderNormal, amount = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''' Hook '''&lt;br /&gt;
&lt;br /&gt;
You can now unregister hooks from: {{tt|register_impulse}}, {{tt|register_think}} and {{tt|register_touch}}.&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Forward&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|unregister_impulse|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=unregister_impulse|header=Removes a previously registered impulse hook.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Removes a previously registered impulse hook.&lt;br /&gt;
 *&lt;br /&gt;
 * @param registerid    Impulse forward id&lt;br /&gt;
 *&lt;br /&gt;
 * @return              1 on success, 0 if nothing was removed&lt;br /&gt;
 */&lt;br /&gt;
native unregister_impulse(registerid);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|unregister_think|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=unregister_think|header=Removes a previously registered think hook.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Removes a previously registered think hook.&lt;br /&gt;
 *&lt;br /&gt;
 * @param registerid    Think forward id&lt;br /&gt;
 *&lt;br /&gt;
 * @return              1 on success, 0 if nothing was removed&lt;br /&gt;
 */&lt;br /&gt;
native unregister_think(registerid);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|unregister_touch|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=unregister_touch|header=Removes a previously registered touch hook.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Removes a previously registered touch hook.&lt;br /&gt;
 *&lt;br /&gt;
 * @param registerid    Touch forward id&lt;br /&gt;
 *&lt;br /&gt;
 * @return              1 on success, 0 if nothing was removed&lt;br /&gt;
 */&lt;br /&gt;
native unregister_touch(registerid);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''' Miscellaneous '''&lt;br /&gt;
&lt;br /&gt;
* {{tt|is_visible}} is now working on player.&lt;br /&gt;
* {{tt|set_ent_rendering}} is new working on non-players entities.&lt;br /&gt;
* {{tt|get_info_keybuffer}} can now retrieve local key buffer (i.e. using {{tt|-1}}).&lt;br /&gt;
* {{tt|trace_hull}} gets a new {{tt|end}} destination parameter to make it useful.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''' Safer Natives '''&lt;br /&gt;
&lt;br /&gt;
Safer natives which returns {{tt|-1}} if not entity found instead of {{tt|0}}0 which is a valid value (worldspawn).&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_global_edict2|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_global_edict2|header=Safe version of {{tt|get_global_edict}}.&amp;lt;br /&amp;gt;Returns a edict type value from the server globals.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns a edict type value from the server globals.&lt;br /&gt;
 *&lt;br /&gt;
 * @note For a list of valid edict type entries, see the GL_* constants in&lt;br /&gt;
 *       engine_const.inc under the &amp;quot;Edict&amp;quot; section.&lt;br /&gt;
 * @note This native returns -1 as a safe error value if the edict retrieved is&lt;br /&gt;
 *       an invalid entity. Otherwise it is identical to get_global_edict().&lt;br /&gt;
 *&lt;br /&gt;
 * @param variable  Entry to retrieve from&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Value of specified entry&lt;br /&gt;
 * @error           If an invalid entry is provided, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native get_global_edict2(variable);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
  |-&lt;br /&gt;
  | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|entity_get_edict2|bgcolor=white}}&lt;br /&gt;
  | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=entity_get_edict2|header=Safe version of {{tt|entity_get_edict}}.&amp;lt;br /&amp;gt;Returns an edict type value from an entities entvar struct.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns an edict type value from an entities entvar struct.&lt;br /&gt;
 *&lt;br /&gt;
 * @note For a list of valid edict type entries, see the EV_ENT_* constants in&lt;br /&gt;
 *       engine_const.inc&lt;br /&gt;
 * @note This native returns -1 as a safe error value if the edict retrieved&lt;br /&gt;
 *       from the entvar is an invalid entity. Otherwise it is identical to&lt;br /&gt;
 *       entity_get_edict().&lt;br /&gt;
 *&lt;br /&gt;
 * @param iIndex    Entity index&lt;br /&gt;
 * @param iKey      Entry to retrieve from&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Entity index in specified entry, -1 if the edict in the&lt;br /&gt;
 *                  entvar is not a valid entity or an invalid entry was&lt;br /&gt;
 *                  specified&lt;br /&gt;
 * @error           If an invalid entity index is provided, an error will be&lt;br /&gt;
 *                  thrown.&lt;br /&gt;
 */&lt;br /&gt;
native entity_get_edict2(iIndex, iKey);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''' Usercmd '''&lt;br /&gt;
&lt;br /&gt;
* {{tt|get_usercmd}} and {{tt|set_usercmd}} are now working and can be used in {{tt|client_cmdStart}} forward.&lt;br /&gt;
&lt;br /&gt;
:{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Forward&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|client_cmdStart|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=client_cmdStart|header=Called for CmdStart() on a client.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Called for CmdStart() on a client.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Use [get|set]_usercmd() to read and modify information in the usercmd&lt;br /&gt;
 *       struct.&lt;br /&gt;
 *&lt;br /&gt;
 * @param id    Client index&lt;br /&gt;
 *&lt;br /&gt;
 * @return      PLUGIN_CONTINUE to ignore, PLUGIN_HANDLED or higher to block&lt;br /&gt;
 */&lt;br /&gt;
forward client_cmdStart(id);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fakemeta ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''' KVD '''&lt;br /&gt;
&lt;br /&gt;
This allows the creation of new KVD structures that can be used with Hamsandwich ({{tt|Ham_Keyvalue}}).&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|create_kvd|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|free_kvd|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=create_kvd|header=Creates a {{tt|KeyValueData}} handle.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Creates a KeyValueData handle.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Handles should be freed using free_kvd().&lt;br /&gt;
 *&lt;br /&gt;
 * @return		New KeyValueData handle&lt;br /&gt;
 */&lt;br /&gt;
native create_kvd();&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=free_kvd|header=Frees a {{tt|KeyValueData}} handle.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Frees a KeyValueData handle.&lt;br /&gt;
 *&lt;br /&gt;
 * @param kvd_handle	KeyValueData handle&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native free_kvd(kvd_handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''' Entity's Private Data (gamedata)'''&lt;br /&gt;
&lt;br /&gt;
This is now possible to manage value from an entity's private data based off a class and member name.&amp;lt;br /&amp;gt;&lt;br /&gt;
The related gamedata files are located in {{tt|data/gamedata/common.games/entities.games}} directory.&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=get_gamerules_int-ex|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=get_gamerules_int-ex|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
foo()&lt;br /&gt;
{&lt;br /&gt;
    new const item = get_ent_data_entity(&amp;quot;CBasePlayer&amp;quot;, &amp;quot;m_pActiveItem&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_ent_data|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|set_ent_data|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_ent_data|header=Retrieves an integer value from an entity's private data based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves an integer value from an entity's private data based off a class&lt;br /&gt;
 * and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Unlike the [get|set]_pdata_* natives that require compiling the class&lt;br /&gt;
 *       member offset into the plugin, this native instead retrieves the&lt;br /&gt;
 *       necessary offset from the AMXX gamedata files at runtime, based on the&lt;br /&gt;
 *       provided class and member name.&lt;br /&gt;
 * @note This native is safer than [get|set]_pdata_* as it can perform stricter&lt;br /&gt;
 *       offset and typing checks.&lt;br /&gt;
 * @note This native is used to access the following (C++/engine) data types:&lt;br /&gt;
 *       integer, boolean, short, character, pointer, structure, class,&lt;br /&gt;
 *       stringint and function. Unsigned variants (if applicable) are supported&lt;br /&gt;
 *       and will be converted automatically.&lt;br /&gt;
 *&lt;br /&gt;
 * @param entity    Entity index&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param element   Element to retrieve (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Integer value&lt;br /&gt;
 * @error           If an invalid entity is provided, either class or member is&lt;br /&gt;
 *                  empty, no offset is found or an invalid offset is retrieved,&lt;br /&gt;
 *                  or the data type does not match, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native any:get_ent_data(entity, const class[], const member[], element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=set_ent_data|header=Sets an integer value to an entity's private data based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets an integer value to an entity's private data based off a class&lt;br /&gt;
 * and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Unlike the [get|set]_pdata_* natives that require compiling the class&lt;br /&gt;
 *       member offset into the plugin, this native instead retrieves the&lt;br /&gt;
 *       necessary offset from the AMXX gamedata files at runtime, based on the&lt;br /&gt;
 *       provided class and member name.&lt;br /&gt;
 * @note This native is safer than [get|set]_pdata_* as it can perform stricter&lt;br /&gt;
 *       offset and typing checks.&lt;br /&gt;
 * @note This native is used to access the following (C++/engine) data types:&lt;br /&gt;
 *       integer, boolean, short, character, pointer, stringint and function.&lt;br /&gt;
 *       Unsigned variants (if applicable) are supported and will be converted&lt;br /&gt;
 *       automatically.&lt;br /&gt;
 *&lt;br /&gt;
 * @param entity    Entity index&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param value     Value to set&lt;br /&gt;
 * @param element   Element to set (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid entity is provided, either class or member is&lt;br /&gt;
 *                  empty, no offset is found or an invalid offset is retrieved,&lt;br /&gt;
 *                  or the data type does not match, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native set_ent_data(entity, const class[], const member[], any:value, element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_ent_data_float|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|set_ent_data_float|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_ent_data_float|header=Retrieves an float value from an entity's private data based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves a float value from an entity's private data based off a class&lt;br /&gt;
 * and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Unlike the [get|set]_pdata_* natives that require compiling the class&lt;br /&gt;
 *       member offset into the plugin, this native instead retrieves the&lt;br /&gt;
 *       necessary offset from the AMXX gamedata files at runtime, based on the&lt;br /&gt;
 *       provided class and member name.&lt;br /&gt;
 * @note This native is safer than [get|set]_pdata_* as it can perform stricter&lt;br /&gt;
 *       offset and typing checks.&lt;br /&gt;
 *&lt;br /&gt;
 * @param entity    Entity index&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param element   Element to retrieve (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Float value&lt;br /&gt;
 * @error           If an invalid entity is provided, either class or member is&lt;br /&gt;
 *                  empty, no offset is found or an invalid offset is retrieved,&lt;br /&gt;
 *                  or the data type does not match, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native Float:get_ent_data_float(entity, const class[], const member[], element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=set_ent_data_float|header=Sets an float value to an entity's private data based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a float value to an entity's private data based off a class&lt;br /&gt;
 * and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Unlike the [get|set]_pdata_* natives that require compiling the class&lt;br /&gt;
 *       member offset into the plugin, this native instead retrieves the&lt;br /&gt;
 *       necessary offset from the AMXX gamedata files at runtime, based on the&lt;br /&gt;
 *       provided class and member name.&lt;br /&gt;
 * @note This native is safer than [get|set]_pdata_* as it can perform stricter&lt;br /&gt;
 *       offset and typing checks.&lt;br /&gt;
 *&lt;br /&gt;
 * @param entity    Entity index&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param value     Value to set&lt;br /&gt;
 * @param element   Element to set (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid entity is provided, either class or member is&lt;br /&gt;
 *                  empty, no offset is found or an invalid offset is retrieved,&lt;br /&gt;
 *                  or the data type does not match, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native set_ent_data_float(entity, const class[], const member[], Float:value, element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_ent_data_vector|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|set_ent_data_vector|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_ent_data_vector|header=Retrieves a vector from an entity's private data based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves a vector from an entity's private data based off a class and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Unlike the [get|set]_pdata_* natives that require compiling the class&lt;br /&gt;
 *       member offset into the plugin, this native instead retrieves the&lt;br /&gt;
 *       necessary offset from the AMXX gamedata files at runtime, based on the&lt;br /&gt;
 *       provided class and member name.&lt;br /&gt;
 * @note This native is safer than [get|set]_pdata_* as it can perform stricter&lt;br /&gt;
 *       offset and typing checks.&lt;br /&gt;
 *&lt;br /&gt;
 * @param entity    Entity index&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param value     Vector buffer to store data in&lt;br /&gt;
 * @param element   Element to retrieve (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid entity is provided, either class or member is&lt;br /&gt;
 *                  empty, no offset is found or an invalid offset is retrieved,&lt;br /&gt;
 *                  or the data type does not match, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native get_ent_data_vector(entity, const class[], const member[], Float:value[3], element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=set_ent_data_vector|header=Sets a vector to an entity's private data based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a vector to an entity's private data based off a class and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Unlike the [get|set]_pdata_* natives that require compiling the class&lt;br /&gt;
 *       member offset into the plugin, this native instead retrieves the&lt;br /&gt;
 *       necessary offset from the AMXX gamedata files at runtime, based on the&lt;br /&gt;
 *       provided class and member name.&lt;br /&gt;
 * @note This native is safer than [get|set]_pdata_* as it can perform stricter&lt;br /&gt;
 *       offset and typing checks.&lt;br /&gt;
 *&lt;br /&gt;
 * @param entity    Entity index&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param value     Vector to set&lt;br /&gt;
 * @param element   Element to set (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid entity is provided, either class or member is&lt;br /&gt;
 *                  empty, no offset is found or an invalid offset is retrieved,&lt;br /&gt;
 *                  or the data type does not match, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native set_ent_data_vector(entity, const class[], const member[], Float:value[3], element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_ent_data_entity|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|set_ent_data_entity|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_ent_data_entity|header=Retrieves an entity index from an entity's private data based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves an entity index from an entity's private data based off a class&lt;br /&gt;
 * and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Unlike the [get|set]_pdata_* natives that require compiling the class&lt;br /&gt;
 *       member offset into the plugin, this native instead retrieves the&lt;br /&gt;
 *       necessary offset from the AMXX gamedata files at runtime, based on the&lt;br /&gt;
 *       provided class and member name.&lt;br /&gt;
 * @note This native is safer than [get|set]_pdata_* as it can perform stricter&lt;br /&gt;
 *       offset and typing checks.&lt;br /&gt;
 * @note This native is used to access the following (C++/engine) data types:&lt;br /&gt;
 *       classptr, entvars, edict and ehandle.&lt;br /&gt;
 *&lt;br /&gt;
 * @param entity    Entity index&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param element   Element to retrieve (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Entity index if found, -1 otherwise&lt;br /&gt;
 * @error           If an invalid entity is provided, either class or member is&lt;br /&gt;
 *                  empty, no offset is found or an invalid offset is retrieved,&lt;br /&gt;
 *                  or the data type does not match, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native get_ent_data_entity(entity, const class[], const member[], element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=set_ent_data_entity|header=Sets an entity index to an entity's private data based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets an entity index to an entity's private data based off a class&lt;br /&gt;
 * and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Unlike the [get|set]_pdata_* natives that require compiling the class&lt;br /&gt;
 *       member offset into the plugin, this native instead retrieves the&lt;br /&gt;
 *       necessary offset from the AMXX gamedata files at runtime, based on the&lt;br /&gt;
 *       provided class and member name.&lt;br /&gt;
 * @note This native is safer than [get|set]_pdata_* as it can perform stricter&lt;br /&gt;
 *       offset and typing checks.&lt;br /&gt;
 * @note This native is used to access the following (C++/engine) data types:&lt;br /&gt;
 *       classptr, entvars, edict and ehandle.&lt;br /&gt;
 * @note Pass -1 as value to act as C++ NULL.&lt;br /&gt;
 *&lt;br /&gt;
 * @param entity    Entity index&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param value     Entity index to set&lt;br /&gt;
 * @param element   Element to set (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If an invalid entity or value is provided, either class or member&lt;br /&gt;
 *                  is empty, no offset is found or an invalid offset is retrieved,&lt;br /&gt;
 *                  or the data type does not match, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native set_ent_data_entity(entity, const class[], const member[], value, element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_ent_data_string|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|set_ent_data_string|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_ent_data_string|header=Retrieves a string from an entity's private data based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves a string from an entity's private data based off a class and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Unlike the [get|set]_pdata_* natives that require compiling the class&lt;br /&gt;
 *       member offset into the plugin, this native instead retrieves the&lt;br /&gt;
 *       necessary offset from the AMXX gamedata files at runtime, based on the&lt;br /&gt;
 *       provided class and member name.&lt;br /&gt;
 * @note This native is safer than [get|set]_pdata_* as it can perform stricter&lt;br /&gt;
 *       offset and typing checks.&lt;br /&gt;
 * @note This native is used to access the following (C++/engine) data types:&lt;br /&gt;
 *       string, stringptr.&lt;br /&gt;
 *&lt;br /&gt;
 * @param entity    Entity index&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param value     Buffer to store data in&lt;br /&gt;
 * @param maxlen    Maximum size of the buffer&lt;br /&gt;
 * @param element   Element to retrieve (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Number of cells written to buffer&lt;br /&gt;
 * @error           If an invalid entity is provided, either class or member is&lt;br /&gt;
 *                  empty, no offset is found or an invalid offset is retrieved,&lt;br /&gt;
 *                  or the data type does not match, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native get_ent_data_string(entity, const class[], const member[], value[], maxlen, element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=set_ent_data_string|header=Sets a string to an entity's private data based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a string to an entity's private data based off a class and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Unlike the [get|set]_pdata_* natives that require compiling the class&lt;br /&gt;
 *       member offset into the plugin, this native instead retrieves the&lt;br /&gt;
 *       necessary offset from the AMXX gamedata files at runtime, based on the&lt;br /&gt;
 *       provided class and member name.&lt;br /&gt;
 * @note This native is safer than [get|set]_pdata_* as it can perform stricter&lt;br /&gt;
 *       offset and typing checks.&lt;br /&gt;
 * @note This native is used to access the following (C++/engine) data types:&lt;br /&gt;
 *       string, stringptr.&lt;br /&gt;
 *&lt;br /&gt;
 * @param entity    Entity index&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param value     String to set&lt;br /&gt;
 * @param element   Element to set (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Number of cells written to buffer&lt;br /&gt;
 * @error           If an invalid entity is provided, either class or member is&lt;br /&gt;
 *                  empty, no offset is found or an invalid offset is retrieved,&lt;br /&gt;
 *                  or the data type does not match, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native set_ent_data_string(entity, const class[], const member[], const value[], element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_ent_data_size|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_ent_data_size|header=Retrieves the size of array of n entity class member.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves the size of array of n entity class member.&lt;br /&gt;
 *&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Size of array (in elements), otherwise 1 if member is not an array&lt;br /&gt;
 * @error           If either class or member is empty, no offset is found or an invalid&lt;br /&gt;
 *                  offset is retrieved, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native get_ent_data_size(const class[], const member[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|find_ent_data_info|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=find_ent_data_info|header=Finds a offset based off an entity class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Finds a offset based off an entity class and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param type      Optional variable to store member type in (FIELD_* constants)&lt;br /&gt;
 * @param arraysize Optional variable to store array size in, if member is an array&lt;br /&gt;
 * @param unsigned  Optional variable to store whether member is unsigned (short and char types only)&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Class member offset&lt;br /&gt;
 * @error           If either class or member is empty, no offset is found or an invalid&lt;br /&gt;
 *                  offset is retrieved, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native find_ent_data_info(const class[], const member[], &amp;amp;FieldType:type = FIELD_NONE, &amp;amp;arraysize = 0, &amp;amp;bool:unsigned = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''' Entity's Private Data '''&lt;br /&gt;
&lt;br /&gt;
While it's encouraged to use the new natives based off gamedata, this completes the list with new data types supported: edict, bool, byte, short and ehandle.&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_pdata_ent|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|set_pdata_ent|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_pdata_ent|header=Tries to retrieve an edict pointer from an entity's private data.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Tries to retrieve an edict pointer from an entity's private data.&lt;br /&gt;
 *&lt;br /&gt;
 * This function is byte-addressable.  Unlike get_pdata_int() which searches in byte increments of 4,&lt;br /&gt;
 * get_pdata_ent searches in increments of 1.&lt;br /&gt;
 *&lt;br /&gt;
 * _linuxdiff value is what to add to the _offset for linux servers.&lt;br /&gt;
 * _macdiff value is what to add to the _offset for os x servers.&lt;br /&gt;
 *&lt;br /&gt;
 * A log error is thrown on invalid _index and _Offset.&lt;br /&gt;
 *&lt;br /&gt;
 * @param _index		Entity index.&lt;br /&gt;
 * @param _offset		Offset to search.&lt;br /&gt;
 * @param _linuxdiff	Linux difference.&lt;br /&gt;
 * @param _macdiff		Mac OS X difference.&lt;br /&gt;
 * @return				-2 if an invalid entity was found.&lt;br /&gt;
 *						-1 if an empty entity was found.&lt;br /&gt;
 * 						Otherwise, an entity index is returned.&lt;br /&gt;
 */&lt;br /&gt;
native get_pdata_ent(_index, _offset, _linuxdiff = 20, _macdiff = 20);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=set_pdata_ent|header=Sets an edict pointer to an entity's private data.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets an edict pointer to an entity's private data.&lt;br /&gt;
 *&lt;br /&gt;
 * This function is byte-addressable.  Unlike set_pdata_int() which searches in byte increments of 4,&lt;br /&gt;
 * set_pdata_ent searches in increments of 1.&lt;br /&gt;
 *&lt;br /&gt;
 * _linuxdiff value is what to add to the _offset for linux servers.&lt;br /&gt;
 * _macdiff value is what to add to the _offset for os x servers.&lt;br /&gt;
 *&lt;br /&gt;
 * A log error is thrown on invalid _index and _offset.&lt;br /&gt;
 *&lt;br /&gt;
 * @param _index        Entity index.&lt;br /&gt;
 * @param _offset       Offset to search.&lt;br /&gt;
 * @param _value        Value to set.&lt;br /&gt;
 * @param _linuxdiff    Linux difference.&lt;br /&gt;
 * @param _macdiff      Mac OS X difference.&lt;br /&gt;
 * @return              1 on success.&lt;br /&gt;
 */&lt;br /&gt;
native set_pdata_ent(_index, _offset, _value, _linuxdiff = 20, _macdiff = 20);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_pdata_bool|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|set_pdata_bool|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_pdata_bool|header=Returns a boolean from an entity's private data.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns a boolean from an entity's private data.&lt;br /&gt;
 *&lt;br /&gt;
 * This function is byte-addressable. Unlike get_pdata_int() which searches in byte increments of 4,&lt;br /&gt;
 * get_pdata_bool searches in increments of 1.&lt;br /&gt;
 *&lt;br /&gt;
 * _linuxdiff value is what to add to the _offset for linux servers.&lt;br /&gt;
 * _macdiff value is what to add to the _offset for os x servers.&lt;br /&gt;
 *&lt;br /&gt;
 * A log error is thrown on invalid _index and _offset.&lt;br /&gt;
 *&lt;br /&gt;
 * @param _index        Entity index.&lt;br /&gt;
 * @param _offset       Offset to search.&lt;br /&gt;
 * @param _linuxdiff    Linux difference.&lt;br /&gt;
 * @param _macdiff      Mac OS X difference.&lt;br /&gt;
 * @return              An boolean value is returned.&lt;br /&gt;
 */&lt;br /&gt;
native bool:get_pdata_bool(_index, _offset, _linuxdiff = 20, _macdiff = 20);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=set_pdata_bool|header=Sets a boolean to an entity's private data.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a boolean to an entity's private data.&lt;br /&gt;
 *&lt;br /&gt;
 * This function is byte-addressable. Unlike set_pdata_int() which searches in byte increments of 4,&lt;br /&gt;
 * set_pdata_bool searches in increments of 1.&lt;br /&gt;
 *&lt;br /&gt;
 * _linuxdiff value is what to add to the _offset for linux servers.&lt;br /&gt;
 * _macdiff value is what to add to the _offset for os x servers.&lt;br /&gt;
 *&lt;br /&gt;
 * A log error is thrown on invalid _index and _offset.&lt;br /&gt;
 *&lt;br /&gt;
 * @param _index        Entity index.&lt;br /&gt;
 * @param _offset       Offset to search.&lt;br /&gt;
 * @param _value        Value to set.&lt;br /&gt;
 * @param _linuxdiff    Linux difference.&lt;br /&gt;
 * @param _macdiff      Mac OS X difference.&lt;br /&gt;
 * @return              1 on success.&lt;br /&gt;
 */&lt;br /&gt;
native set_pdata_bool(_index, _offset, bool:_value, _linuxdiff = 20, _macdiff = 20);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_pdata_byte|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|set_pdata_byte|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_pdata_byte|header=Returns a byte value from an entity's private data.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns a byte value from an entity's private data.&lt;br /&gt;
 *&lt;br /&gt;
 * This function is byte-addressable. Unlike get_pdata_int() which searches in byte increments of 4,&lt;br /&gt;
 * get_pdata_byte searches in increments of 1.&lt;br /&gt;
 *&lt;br /&gt;
 * _linuxdiff value is what to add to the _offset for linux servers.&lt;br /&gt;
 * _macdiff value is what to add to the _offset for os x servers.&lt;br /&gt;
 *&lt;br /&gt;
 * A log error is thrown on invalid _index and _offset.&lt;br /&gt;
 *&lt;br /&gt;
 * @param _index        Entity index.&lt;br /&gt;
 * @param _offset       Offset to search.&lt;br /&gt;
 * @param _linuxdiff    Linux difference.&lt;br /&gt;
 * @param _macdiff      Mac OS X difference.&lt;br /&gt;
 * @return              A byte value is returned.&lt;br /&gt;
 */&lt;br /&gt;
native get_pdata_byte(_index, _offset, _linuxdiff = 20, _macdiff = 20);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=set_pdata_byte|header=Sets a byte value to an entity's private data.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a byte value to an entity's private data.&lt;br /&gt;
 *&lt;br /&gt;
 * This function is byte-addressable. Unlike set_pdata_int() which searches in byte increments of 4,&lt;br /&gt;
 * set_pdata_byte searches in increments of 1.&lt;br /&gt;
 *&lt;br /&gt;
 * _linuxdiff value is what to add to the _offset for linux servers.&lt;br /&gt;
 * _macdiff value is what to add to the _offset for os x servers.&lt;br /&gt;
 *&lt;br /&gt;
 * A log error is thrown on invalid _index and _offset.&lt;br /&gt;
 *&lt;br /&gt;
 * @param _index        Entity index.&lt;br /&gt;
 * @param _offset       Offset to search.&lt;br /&gt;
 * @param _value        Value to set.&lt;br /&gt;
 * @param _linuxdiff    Linux difference.&lt;br /&gt;
 * @param _macdiff      Mac OS X difference.&lt;br /&gt;
 * @return              1 on success.&lt;br /&gt;
 */&lt;br /&gt;
native set_pdata_byte(_index, _offset, _value, _linuxdiff = 20, _macdiff = 20);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_pdata_short|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|set_pdata_short|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_pdata_short|header=Returns a short value from an entity's private data.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns a short value from an entity's private data.&lt;br /&gt;
 *&lt;br /&gt;
 * This function is byte-addressable. Unlike get_pdata_int() which searches in byte increments of 4,&lt;br /&gt;
 * get_pdata_short searches in increments of 1.&lt;br /&gt;
 *&lt;br /&gt;
 * _linuxdiff value is what to add to the _offset for linux servers.&lt;br /&gt;
 * _macdiff value is what to add to the _offset for os x servers.&lt;br /&gt;
 *&lt;br /&gt;
 * A log error is thrown on invalid _index and _offset.&lt;br /&gt;
 *&lt;br /&gt;
 * @param _index        Entity index.&lt;br /&gt;
 * @param _offset       Offset to search.&lt;br /&gt;
 * @param _linuxdiff    Linux difference.&lt;br /&gt;
 * @param _macdiff      Mac OS X difference.&lt;br /&gt;
 * @return              A short value is returned.&lt;br /&gt;
 */&lt;br /&gt;
native get_pdata_short(_index, _offset, _linuxdiff = 20, _macdiff = 20);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=set_pdata_short|header=Sets a short value to an entity's private data.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a short value to an entity's private data.&lt;br /&gt;
 *&lt;br /&gt;
 * This function is byte-addressable.  Unlike set_pdata_int() which searches in byte increments of 4,&lt;br /&gt;
 * set_pdata_short searches in increments of 1.&lt;br /&gt;
 *&lt;br /&gt;
 * _linuxdiff value is what to add to the _offset for linux servers.&lt;br /&gt;
 * _macdiff value is what to add to the _offset for os x servers.&lt;br /&gt;
 *&lt;br /&gt;
 * A log error is thrown on invalid _index and _offset.&lt;br /&gt;
 *&lt;br /&gt;
 * @param _index        Entity index.&lt;br /&gt;
 * @param _offset       Offset to search.&lt;br /&gt;
 * @param _value        Value to set.&lt;br /&gt;
 * @param _linuxdiff    Linux difference.&lt;br /&gt;
 * @param _macdiff      Mac OS X difference.&lt;br /&gt;
 * @return              1 on success.&lt;br /&gt;
 */&lt;br /&gt;
native set_pdata_short(_index, _offset, _value, _linuxdiff = 20, _macdiff = 20);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_pdata_vector|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|set_pdata_vector|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_pdata_vector|header=Returns a vector from an entity's private data.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns a vector from an entity's private data.&lt;br /&gt;
 *&lt;br /&gt;
 * This function is byte-addressable. Unlike get_pdata_int() which searches in byte increments of 4,&lt;br /&gt;
 * get_pdata_vector searches in increments of 1.&lt;br /&gt;
 *&lt;br /&gt;
 * _linuxdiff value is what to add to the _offset for linux servers.&lt;br /&gt;
 * _macdiff value is what to add to the _offset for os x servers.&lt;br /&gt;
 *&lt;br /&gt;
 * A log error is thrown on invalid _index and _offset.&lt;br /&gt;
 *&lt;br /&gt;
 * @param _index        Entity index.&lt;br /&gt;
 * @param _offset       Offset to search.&lt;br /&gt;
 * @param _output       Vector returned by reference.&lt;br /&gt;
 * @param _linuxdiff    Linux difference.&lt;br /&gt;
 * @param _macdiff      Mac OS X difference.&lt;br /&gt;
 * @return              1 on success.&lt;br /&gt;
 */&lt;br /&gt;
native get_pdata_vector(_index, _offset, Float:_output[3], _linuxdiff = 20, _macdiff = 20);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=set_pdata_vector|header=Sets a vector to an entity's private data.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a vector to an entity's private data.&lt;br /&gt;
 *&lt;br /&gt;
 * This function is byte-addressable.  Unlike set_pdata_int() which searches in byte increments of 4,&lt;br /&gt;
 * set_pdata_vector searches in increments of 1.&lt;br /&gt;
 *&lt;br /&gt;
 * _linuxdiff value is what to add to the _offset for linux servers.&lt;br /&gt;
 * _macdiff value is what to add to the _offset for os x servers.&lt;br /&gt;
 *&lt;br /&gt;
 * A log error is thrown on invalid _index and _Offset.&lt;br /&gt;
 *&lt;br /&gt;
 * @param _index        Entity index.&lt;br /&gt;
 * @param _offset       Offset to search.&lt;br /&gt;
 * @param _origin       Value to set.&lt;br /&gt;
 * @param _linuxdiff    Linux difference.&lt;br /&gt;
 * @param _macdiff      Mac OS X difference.&lt;br /&gt;
 * @return              1 on success.&lt;br /&gt;
 */&lt;br /&gt;
native set_pdata_vector(_index, _offset, Float:_origin[3], _linuxdiff = 20, _macdiff = 20);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_pdata_ehandle|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|set_pdata_ehandle|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_pdata_ehandle|header=Tries to retrieve an edict (entity encapsulation) pointer from an entity's private data.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Tries to retrieve an edict (entity encapsulation) pointer from an entity's private data.&lt;br /&gt;
 *&lt;br /&gt;
 * This function is byte-addressable.  Unlike get_pdata_int() which searches in byte increments of 4,&lt;br /&gt;
 * get_pdata_ehandle searches in increments of 1.&lt;br /&gt;
 *&lt;br /&gt;
 * _linuxdiff value is what to add to the _offset for linux servers.&lt;br /&gt;
 * _macdiff value is what to add to the _offset for os x servers.&lt;br /&gt;
 *&lt;br /&gt;
 * A log error is thrown on invalid _index and _offset.&lt;br /&gt;
 *&lt;br /&gt;
 * @param _index        Entity index.&lt;br /&gt;
 * @param _offset       Offset to search.&lt;br /&gt;
 * @param _linuxdiff    Linux difference.&lt;br /&gt;
 * @param _macdiff      Mac OS X difference.&lt;br /&gt;
 * @return              -2 if an invalid entity was found.&lt;br /&gt;
 *                      -1 if an empty entity was found.&lt;br /&gt;
 *                      0 if serialnumber is not matching.&lt;br /&gt;
 *                      Otherwise, an entity index is returned.&lt;br /&gt;
 */&lt;br /&gt;
native get_pdata_ehandle(_index, _offset, _linuxdiff = 20, _macdiff = 20);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=set_pdata_ehandle|header=Sets an edict (entity encapsulation) pointer to an entity's private data.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets an edict (entity encapsulation) pointer to an entity's private data.&lt;br /&gt;
 *&lt;br /&gt;
 * This function is byte-addressable.  Unlike set_pdata_int() which searches in byte increments of 4,&lt;br /&gt;
 * set_pdata_ehandle searches in increments of 1.&lt;br /&gt;
 *&lt;br /&gt;
 * _linuxdiff value is what to add to the _offset for linux servers.&lt;br /&gt;
 * _macdiff value is what to add to the _offset for os x servers.&lt;br /&gt;
 *&lt;br /&gt;
 * A log error is thrown on invalid _index and _Offset.&lt;br /&gt;
 *&lt;br /&gt;
 * @param _index        Entity index.&lt;br /&gt;
 * @param _offset       Offset to search.&lt;br /&gt;
 * @param _value        Value to set.&lt;br /&gt;
 * @param _linuxdiff    Linux difference.&lt;br /&gt;
 * @param _macdiff      Mac OS X difference.&lt;br /&gt;
 * @return              1 on success.&lt;br /&gt;
 */&lt;br /&gt;
native set_pdata_ehandle(_index, _offset, _value, _linuxdiff = 20, _macdiff = 20);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''' Gamerules '''&lt;br /&gt;
&lt;br /&gt;
You have now the ability to manage a value using the gamerules object based off a class and member name.&amp;lt;br /&amp;gt;&lt;br /&gt;
The gamedata files are located in {{tt|/data/gamedata/common.games/gamerules.games}} directory.&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Example:|{{hidden|id=get_gamerules_int-ex|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=get_gamerules_int-ex|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
foo()&lt;br /&gt;
{&lt;br /&gt;
    new const score = get_gamerules_int(&amp;quot;CHalfLifeMultiplay&amp;quot;, &amp;quot;m_iNumCTWins&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_gamerules_int|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|set_gamerules_int|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_gamerules_int|header=Retrieves an integer value from the gamerules object based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves an integer value from the gamerules object based off a class&lt;br /&gt;
 * and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This native is used to access the following (C++/engine) data types:&lt;br /&gt;
 *       integer, boolean, short, character, pointer, structure, class,&lt;br /&gt;
 *       stringint and function. Unsigned variants (if applicable) are supported&lt;br /&gt;
 *       and will be converted automatically.&lt;br /&gt;
 *&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param element   Element to retrieve (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Integer value&lt;br /&gt;
 * @error           If member is empty, no offset is found or an invalid offset&lt;br /&gt;
 *                  is retrieved, or the data type does not match, an error will&lt;br /&gt;
 *                  be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native any:get_gamerules_int(const class[], const member[], element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=set_gamerules_int|header=Sets an integer value to the gamerules objecta based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets an integer value to the gamerules objecta based off a class&lt;br /&gt;
 * and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This native is used to access the following (C++/engine) data types:&lt;br /&gt;
 *       integer, boolean, short, character, pointer, stringint and function.&lt;br /&gt;
 *       Unsigned variants (if applicable) are supported and will be converted&lt;br /&gt;
 *       automatically.&lt;br /&gt;
 *&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param value     Value to set&lt;br /&gt;
 * @param element   Element to set (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If member is empty, no offset is found or an invalid offset&lt;br /&gt;
 *                  is retrieved, or the data type does not match, an error will&lt;br /&gt;
 *                  be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native set_gamerules_int(const class[], const member[], any:value, element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_gamerules_float|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|set_gamerules_float|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_gamerules_float|header=Retrieves a float value from the gamerules object based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves a float value from the gamerules object based off a class&lt;br /&gt;
 * and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param element   Element to retrieve (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Float value&lt;br /&gt;
 * @error           If member is empty, no offset is found or an invalid offset&lt;br /&gt;
 *                  is retrieved, or the data type does not match, an error will&lt;br /&gt;
 *                  be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native Float:get_gamerules_float(const class[], const member[], element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=set_gamerules_float|header=Sets an float value to the gamerules objecta based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a float value to the gamerules object based off a class&lt;br /&gt;
 * and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param value     Value to set&lt;br /&gt;
 * @param element   Element to set (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If member is empty, no offset is found or an invalid offset&lt;br /&gt;
 *                  is retrieved, or the data type does not match, an error will&lt;br /&gt;
 *                  be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native set_gamerules_float(const class[], const member[], Float:value, element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_gamerules_vector|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|set_gamerules_vector|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_gamerules_vector|header=Retrieves a vector from the gamerules object based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves a vector from the gamerules object based off a class and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param value     Vector buffer to store data in&lt;br /&gt;
 * @param element   Element to retrieve (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If member is empty, no offset is found or an invalid offset&lt;br /&gt;
 *                  is retrieved, or the data type does not match, an error will&lt;br /&gt;
 *                  be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native get_gamerules_vector(const class[], const member[], Float:value[3], element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=set_gamerules_vector|header=Sets a vector to the gamerules objecta based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a vector to the gamerules object based off a class and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param value     Vector to set&lt;br /&gt;
 * @param element   Element to set (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If member is empty, no offset is found or an invalid offset&lt;br /&gt;
 *                  is retrieved, or the data type does not match, an error will&lt;br /&gt;
 *                  be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native set_gamerules_vector(const class[], const member[], Float:value[3], element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_gamerules_entity|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|set_gamerules_entity|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_gamerules_entity|header=Retrieves an entity index from the gamerules object based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves an entity index from the gamerules object based off a class&lt;br /&gt;
 * and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This native is used to access the following (C++/engine) data types:&lt;br /&gt;
 *       classptr, entvars, edict and ehandle.&lt;br /&gt;
 *&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param element   Element to retrieve (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Entity index if found, -1 otherwise&lt;br /&gt;
 * @error           If member is empty, no offset is found or an invalid offset&lt;br /&gt;
 *                  is retrieved, or the data type does not match, an error will&lt;br /&gt;
 *                  be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native get_gamerules_entity(const class[], const member[], element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=set_gamerules_entity|header=Sets an entity index to the gamerules objecta based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets an entity index to the gamerules object based off a class&lt;br /&gt;
 * and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This native is used to access the following (C++/engine) data types:&lt;br /&gt;
 *       classptr, entvars, edict and ehandle.&lt;br /&gt;
 * @note Pass -1 as value to act as C++ NULL.&lt;br /&gt;
 *&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param value     Entity index to set&lt;br /&gt;
 * @param element   Element to set (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 * @error           If member is empty, no offset is found or an invalid offset&lt;br /&gt;
 *                  is retrieved, or the data type does not match, an error will&lt;br /&gt;
 *                  be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native set_gamerules_entity(const class[], const member[], value, element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_gamerules_string|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|set_gamerules_string|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_gamerules_string|header=Retrieves a string from the gamerules object based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves a string from the gamerules object based off a class and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This native is used to access the following (C++/engine) data types:&lt;br /&gt;
 *       string, stringptr.&lt;br /&gt;
 *&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param value     Buffer to store data in&lt;br /&gt;
 * @param maxlen    Maximum size of the buffer&lt;br /&gt;
 * @param element   Element to retrieve (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Number of cells written to buffer&lt;br /&gt;
 * @error           If member is empty, no offset is found or an invalid offset&lt;br /&gt;
 *                  is retrieved, or the data type does not match, an error will&lt;br /&gt;
 *                  be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native get_gamerules_string(const class[], const member[], value[], maxlen, element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=set_gamerules_string|header=Sets a string to the gamerules objecta based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a string to the gamerules object based off a class and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @note This native is used to access the following (C++/engine) data types:&lt;br /&gt;
 *       string, stringptr.&lt;br /&gt;
 *&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param value     String to set&lt;br /&gt;
 * @param element   Element to set (starting from 0) if member is an array&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Number of cells written to buffer&lt;br /&gt;
 * @error           If member is empty, no offset is found or an invalid offset&lt;br /&gt;
 *                  is retrieved, or the data type does not match, an error will&lt;br /&gt;
 *                  be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native set_gamerules_string(const class[], const member[], const value[], element = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_gamerules_size|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_gamerules_size|header=Retrieves the size of array of a gamerules class member.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Retrieves the size of array of a gamerules class member.&lt;br /&gt;
 *&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Size of array (in elements), otherwise 1 if member is not an array&lt;br /&gt;
 * @error           If either class or member is empty, no offset is found or an invalid&lt;br /&gt;
 *                  offset is retrieved, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native get_gamerules_size(const class[], const member[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|find_gamerules_info|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=find_gamerules_info|header=Finds a gamerules offset based off a class and member name.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Finds a gamerules offset based off a class and member name.&lt;br /&gt;
 *&lt;br /&gt;
 * @param class     Class name&lt;br /&gt;
 * @param member    Member name&lt;br /&gt;
 * @param type      Optional variable to store member type in (FIELD_* constants)&lt;br /&gt;
 * @param arraysize Optional variable to store array size in, if member is an array&lt;br /&gt;
 * @param unsigned  Optional variable to store whether member is unsigned (short and char types only)&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Class member offset&lt;br /&gt;
 * @error           If either class or member is empty, no offset is found or an invalid&lt;br /&gt;
 *                  offset is retrieved, an error will be thrown.&lt;br /&gt;
 */&lt;br /&gt;
native find_gamerules_info(const class[], const member[], &amp;amp;FieldType:type = FIELD_NONE, &amp;amp;arraysize = 0, &amp;amp;bool:unsigned = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Stock&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|get_field_basetype|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=get_field_basetype|header=Returns the data field base type based off a specific field type.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns the data field base type based off a specific field type.&lt;br /&gt;
 *&lt;br /&gt;
 * @note From an AMXX plugin perspective, the (C++/engine) data types can be grouped&lt;br /&gt;
 *       in five base types: integer, float, vector, entity and string. This stock is&lt;br /&gt;
 *       essentially for convenience and debug purpose.&lt;br /&gt;
 *&lt;br /&gt;
 * @param type      Class member type (FIELD_* constants)&lt;br /&gt;
 * @param type_name Optional buffer to store base type name in&lt;br /&gt;
 * @param maxlen    Maximum size of the buffer&lt;br /&gt;
 *&lt;br /&gt;
 * @return          Base field type (BASEFIELD_* constants)&lt;br /&gt;
 */&lt;br /&gt;
stock BaseFieldType:get_field_basetype(FieldType:type, type_name[] = &amp;quot;&amp;quot;, maxlen = 0)&lt;br /&gt;
{&lt;br /&gt;
    static const baseFieldTypeNames[BaseFieldType][] =&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;none&amp;quot;,&lt;br /&gt;
        &amp;quot;integer&amp;quot;,&lt;br /&gt;
        &amp;quot;float&amp;quot;,&lt;br /&gt;
        &amp;quot;vector&amp;quot;,&lt;br /&gt;
        &amp;quot;entity&amp;quot;,&lt;br /&gt;
        &amp;quot;string&amp;quot;,&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    new BaseFieldType:baseType = BASEFIELD_NONE;&lt;br /&gt;
&lt;br /&gt;
    switch (type)&lt;br /&gt;
    {&lt;br /&gt;
        case FIELD_INTEGER, FIELD_STRINGINT, FIELD_SHORT  , FIELD_CHARACTER,&lt;br /&gt;
             FIELD_CLASS  , FIELD_STRUCTURE, FIELD_POINTER, FIELD_FUNCTION,&lt;br /&gt;
             FIELD_BOOLEAN:&lt;br /&gt;
        {&lt;br /&gt;
            baseType = BASEFIELD_INTEGER;&lt;br /&gt;
        }&lt;br /&gt;
        case FIELD_FLOAT:&lt;br /&gt;
        {&lt;br /&gt;
            baseType = BASEFIELD_FLOAT;&lt;br /&gt;
        }&lt;br /&gt;
        case FIELD_VECTOR:&lt;br /&gt;
        {&lt;br /&gt;
            baseType = BASEFIELD_VECTOR;&lt;br /&gt;
        }&lt;br /&gt;
        case FIELD_CLASSPTR, FIELD_ENTVARS, FIELD_EDICT, FIELD_EHANDLE:&lt;br /&gt;
        {&lt;br /&gt;
            baseType = BASEFIELD_ENTITY;&lt;br /&gt;
        }&lt;br /&gt;
        case FIELD_STRINGPTR, FIELD_STRING:&lt;br /&gt;
        {&lt;br /&gt;
            baseType = BASEFIELD_STRING;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (maxlen &amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
        copy(type_name, maxlen, baseFieldTypeNames[baseType]);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return baseType;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''' Miscellaneous '''&lt;br /&gt;
&lt;br /&gt;
* {{tt|get/set_pdata_cbase}} can now be used at map end whereas player's private datas are still valid.&lt;br /&gt;
* {{tt|EngFunc_PlayBackEvent}} can now receive a null invoker.&lt;br /&gt;
* {{tt|KeyValueData}} usage is now compatible with Hamsandwich module.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GeoIP ===&lt;br /&gt;
&lt;br /&gt;
''' Library '''&lt;br /&gt;
&lt;br /&gt;
The module uses the new {{tt|MaxMind GeoIP2 API|bgcolor=none}}. The relevant advantages are:&lt;br /&gt;
* Should be more precise&lt;br /&gt;
* Data is localized (current supported languages: {{tt|de}}, {{tt|en}}, {{tt|es}}, {{tt|fr}}, {{tt|ja}}, {{tt|ru}}, {{tt|pt-BR}}, {{tt|zh-CN}})&lt;br /&gt;
&lt;br /&gt;
If you want further information, see [https://dev.maxmind.com/geoip/geoip2/whats-new-in-geoip2/ What’s New in GeoIP2].&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|{{TT|GeoIP.dat}} is replaced with {{TT|GeoLite2-Country.mmdb}} (default, [http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz downloadable]) or {{TT|GeoLite2-City.mmdb}} ([http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz downloadable]).|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
''' Command '''&lt;br /&gt;
&lt;br /&gt;
A {{tt|geoip}} command is available for troubleshooting: {{tt|geoip &amp;lt;command&amp;gt; [argument]}}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Command&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|version|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=geoip-version|header=Displays the geoip database metadata such as the current loaded database and its version.|labelpos=left|content=&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
  Database metadata&lt;br /&gt;
    Node count:    3998109&lt;br /&gt;
    Record size:   28 bits&lt;br /&gt;
    IP version:    IPv6&lt;br /&gt;
    Binary format: 2.0&lt;br /&gt;
    Build epoch:   1501721259 (2017-08-03 00:47:39 UTC)&lt;br /&gt;
    Type:          GeoLite2-City&lt;br /&gt;
    Languages:     de en es fr ja pt-BR ru zh-CN&lt;br /&gt;
    Description:&lt;br /&gt;
      en:   GeoLite2 City database&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|dump &amp;lt;ip&amp;gt; [output file]|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=geoip-dump||header=Dumps all data from an IP address formatted in a JSON-ish fashion. &amp;lt;br /&amp;gt;An output file is mod-based and if not provided, it will print in the console.||labelpos=left|content=&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* GEOIP2 DATA EXAMPLE:&lt;br /&gt;
*&lt;br /&gt;
* {&lt;br /&gt;
*   &amp;quot;city&amp;quot;:  {&lt;br /&gt;
*       &amp;quot;confidence&amp;quot;:  25,&lt;br /&gt;
*       &amp;quot;geoname_id&amp;quot;: 54321,&lt;br /&gt;
*       &amp;quot;names&amp;quot;:  {&lt;br /&gt;
*           &amp;quot;de&amp;quot;:    &amp;quot;Los Angeles&amp;quot;,&lt;br /&gt;
*           &amp;quot;en&amp;quot;:    &amp;quot;Los Angeles&amp;quot;,&lt;br /&gt;
*           &amp;quot;es&amp;quot;:    &amp;quot;Los Ýngeles&amp;quot;,&lt;br /&gt;
*           &amp;quot;fr&amp;quot;:    &amp;quot;Los Angeles&amp;quot;,&lt;br /&gt;
*           &amp;quot;ja&amp;quot;:    &amp;quot;ロサンゼルス市&amp;quot;,&lt;br /&gt;
*           &amp;quot;pt-BR&amp;quot;:  &amp;quot;Los Angeles&amp;quot;,&lt;br /&gt;
*           &amp;quot;ru&amp;quot;:    &amp;quot;Лоѝ-Ннджелеѝ&amp;quot;,&lt;br /&gt;
*           &amp;quot;zh-CN&amp;quot;: &amp;quot;洛杉矶&amp;quot;&lt;br /&gt;
*       }&lt;br /&gt;
*   },&lt;br /&gt;
*   &amp;quot;continent&amp;quot;:  {&lt;br /&gt;
*       &amp;quot;code&amp;quot;:       &amp;quot;NA&amp;quot;,&lt;br /&gt;
*       &amp;quot;geoname_id&amp;quot;: 123456,&lt;br /&gt;
*       &amp;quot;names&amp;quot;:  {&lt;br /&gt;
*           &amp;quot;de&amp;quot;:    &amp;quot;Nordamerika&amp;quot;,&lt;br /&gt;
*           &amp;quot;en&amp;quot;:    &amp;quot;North America&amp;quot;,&lt;br /&gt;
*           &amp;quot;es&amp;quot;:    &amp;quot;América del Norte&amp;quot;,&lt;br /&gt;
*           &amp;quot;fr&amp;quot;:    &amp;quot;Amérique du Nord&amp;quot;,&lt;br /&gt;
*           &amp;quot;ja&amp;quot;:    &amp;quot;北アメリカ&amp;quot;,&lt;br /&gt;
*           &amp;quot;pt-BR&amp;quot;: &amp;quot;América do Norte&amp;quot;,&lt;br /&gt;
*           &amp;quot;ru&amp;quot;:    &amp;quot;Севернаѝ Нмерика&amp;quot;,&lt;br /&gt;
*           &amp;quot;zh-CN&amp;quot;: &amp;quot;北美洲&amp;quot;&lt;br /&gt;
*&lt;br /&gt;
*       }&lt;br /&gt;
*   },&lt;br /&gt;
*   &amp;quot;country&amp;quot;:  {&lt;br /&gt;
*       &amp;quot;confidence&amp;quot;:  75,&lt;br /&gt;
*       &amp;quot;geoname_id&amp;quot;: &amp;quot;6252001&amp;quot;,&lt;br /&gt;
*       &amp;quot;iso_code&amp;quot;:    &amp;quot;US&amp;quot;,&lt;br /&gt;
*       &amp;quot;names&amp;quot;:  {&lt;br /&gt;
*           &amp;quot;de&amp;quot;:     &amp;quot;USA&amp;quot;,&lt;br /&gt;
*           &amp;quot;en&amp;quot;:     &amp;quot;United States&amp;quot;,&lt;br /&gt;
*           &amp;quot;es&amp;quot;:     &amp;quot;Estados Unidos&amp;quot;,&lt;br /&gt;
*           &amp;quot;fr&amp;quot;:     &amp;quot;États-Unis&amp;quot;,&lt;br /&gt;
*           &amp;quot;ja&amp;quot;:     &amp;quot;アメリカ坈衆国&amp;quot;,&lt;br /&gt;
*           &amp;quot;pt-BR&amp;quot;:  &amp;quot;Estados Unidos&amp;quot;,&lt;br /&gt;
*           &amp;quot;ru&amp;quot;:     &amp;quot;СШН&amp;quot;,&lt;br /&gt;
*           &amp;quot;zh-CN&amp;quot;:  &amp;quot;美国&amp;quot;&lt;br /&gt;
*       }&lt;br /&gt;
*   },&lt;br /&gt;
*   &amp;quot;location&amp;quot;:  {&lt;br /&gt;
*       &amp;quot;accuracy_radius&amp;quot;:   20,&lt;br /&gt;
*       &amp;quot;latitude&amp;quot;:          37.6293,&lt;br /&gt;
*       &amp;quot;longitude&amp;quot;:         -122.1163,&lt;br /&gt;
*       &amp;quot;metro_code&amp;quot;:        807,&lt;br /&gt;
*       &amp;quot;time_zone&amp;quot;:         &amp;quot;America/Los_Angeles&amp;quot;&lt;br /&gt;
*   },&lt;br /&gt;
*   &amp;quot;postal&amp;quot;: {&lt;br /&gt;
*       &amp;quot;code&amp;quot;:       &amp;quot;90001&amp;quot;,&lt;br /&gt;
*       &amp;quot;confidence&amp;quot;: 10&lt;br /&gt;
*   },&lt;br /&gt;
*   &amp;quot;registered_country&amp;quot;:  {&lt;br /&gt;
*       &amp;quot;geoname_id&amp;quot;: &amp;quot;6252001&amp;quot;,&lt;br /&gt;
*       &amp;quot;iso_code&amp;quot;:    &amp;quot;US&amp;quot;,&lt;br /&gt;
*       &amp;quot;names&amp;quot;:  {&lt;br /&gt;
*           &amp;quot;de&amp;quot;:     &amp;quot;USA&amp;quot;,&lt;br /&gt;
*           &amp;quot;en&amp;quot;:     &amp;quot;United States&amp;quot;,&lt;br /&gt;
*           &amp;quot;es&amp;quot;:     &amp;quot;Estados Unidos&amp;quot;,&lt;br /&gt;
*           &amp;quot;fr&amp;quot;:     &amp;quot;États-Unis&amp;quot;,&lt;br /&gt;
*           &amp;quot;ja&amp;quot;:     &amp;quot;アメリカ坈衆国&amp;quot;,&lt;br /&gt;
*           &amp;quot;pt-BR&amp;quot;:  &amp;quot;Estados Unidos&amp;quot;,&lt;br /&gt;
*           &amp;quot;ru&amp;quot;:     &amp;quot;СШН&amp;quot;,&lt;br /&gt;
*           &amp;quot;zh-CN&amp;quot;:  &amp;quot;美国&amp;quot;&lt;br /&gt;
*       }&lt;br /&gt;
*   },&lt;br /&gt;
*   &amp;quot;represented_country&amp;quot;:  {&lt;br /&gt;
*      &amp;quot;geoname_id&amp;quot;: &amp;quot;6252001&amp;quot;,&lt;br /&gt;
*       &amp;quot;iso_code&amp;quot;:    &amp;quot;US&amp;quot;,&lt;br /&gt;
*       &amp;quot;names&amp;quot;:  {&lt;br /&gt;
*           &amp;quot;de&amp;quot;:     &amp;quot;USA&amp;quot;,&lt;br /&gt;
*           &amp;quot;en&amp;quot;:     &amp;quot;United States&amp;quot;,&lt;br /&gt;
*           &amp;quot;es&amp;quot;:     &amp;quot;Estados Unidos&amp;quot;,&lt;br /&gt;
*           &amp;quot;fr&amp;quot;:     &amp;quot;États-Unis&amp;quot;,&lt;br /&gt;
*           &amp;quot;ja&amp;quot;:     &amp;quot;アメリカ坈衆国&amp;quot;,&lt;br /&gt;
*           &amp;quot;pt-BR&amp;quot;:  &amp;quot;Estados Unidos&amp;quot;,&lt;br /&gt;
*           &amp;quot;ru&amp;quot;:     &amp;quot;СШН&amp;quot;,&lt;br /&gt;
*           &amp;quot;zh-CN&amp;quot;:  &amp;quot;美国&amp;quot;&lt;br /&gt;
*       },&lt;br /&gt;
*       &amp;quot;type&amp;quot;: &amp;quot;military&amp;quot;&lt;br /&gt;
*   },&lt;br /&gt;
*   &amp;quot;subdivisions&amp;quot;:  [&lt;br /&gt;
*       {&lt;br /&gt;
*           &amp;quot;confidence&amp;quot;:  50,&lt;br /&gt;
*           &amp;quot;geoname_id&amp;quot;: 5332921,&lt;br /&gt;
*           &amp;quot;iso_code&amp;quot;:    &amp;quot;CA&amp;quot;,&lt;br /&gt;
*           &amp;quot;names&amp;quot;:  {&lt;br /&gt;
*               &amp;quot;de&amp;quot;:    &amp;quot;Kalifornien&amp;quot;,&lt;br /&gt;
*               &amp;quot;en&amp;quot;:    &amp;quot;California&amp;quot;,&lt;br /&gt;
*               &amp;quot;es&amp;quot;:    &amp;quot;California&amp;quot;,&lt;br /&gt;
*               &amp;quot;fr&amp;quot;:    &amp;quot;Californie&amp;quot;,&lt;br /&gt;
*               &amp;quot;ja&amp;quot;:    &amp;quot;カリフォルニア&amp;quot;,&lt;br /&gt;
*               &amp;quot;ru&amp;quot;:    &amp;quot;Калифорниѝ&amp;quot;,&lt;br /&gt;
*               &amp;quot;zh-CN&amp;quot;: &amp;quot;加州&amp;quot;&lt;br /&gt;
*           }&lt;br /&gt;
*       }&lt;br /&gt;
*   ],&lt;br /&gt;
*   &amp;quot;traits&amp;quot;: {&lt;br /&gt;
*       &amp;quot;autonomous_system_number&amp;quot;:      &amp;quot;1239&amp;quot;,&lt;br /&gt;
*       &amp;quot;autonomous_system_organization&amp;quot;: &amp;quot;Linkem IR WiMax Network&amp;quot;,&lt;br /&gt;
*       &amp;quot;domain&amp;quot;:                        &amp;quot;example.com&amp;quot;,&lt;br /&gt;
*       &amp;quot;is_anonymous_proxy&amp;quot;:            true,&lt;br /&gt;
*       &amp;quot;is_transparent_proxy&amp;quot;:          true,&lt;br /&gt;
*       &amp;quot;isp&amp;quot;:                           &amp;quot;Linkem spa&amp;quot;,&lt;br /&gt;
*       &amp;quot;ip_address&amp;quot;:                    &amp;quot;1.2.3.4&amp;quot;,&lt;br /&gt;
*       &amp;quot;organization&amp;quot;:                  &amp;quot;Linkem IR WiMax Network&amp;quot;,&lt;br /&gt;
*       &amp;quot;user_type&amp;quot;:                     &amp;quot;traveler&amp;quot;,&lt;br /&gt;
*   },&lt;br /&gt;
*   &amp;quot;maxmind&amp;quot;: {&lt;br /&gt;
*       &amp;quot;queries_remaining&amp;quot;:            &amp;quot;54321&amp;quot;&lt;br /&gt;
*   }&lt;br /&gt;
* }&lt;br /&gt;
*/&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
  |}&lt;br /&gt;
&lt;br /&gt;
''' Deprecated natives '''&lt;br /&gt;
&lt;br /&gt;
{{tt|geoip_country}} has been marked as deprecated in favor of {{tt|geoip_country_ex}}. &amp;lt;br /&amp;gt;&lt;br /&gt;
Hardcoding the maximum buffer length and returning &amp;quot;error&amp;quot; if nothing is found, were not quite the good idea.&lt;br /&gt;
&lt;br /&gt;
''' New natives '''&lt;br /&gt;
&lt;br /&gt;
The natives which can output localized data, have a new {{tt|id}} {{hidden|id=new_id_param|labelonly=yes}} parameter in order to retrieve data into the player's language.&lt;br /&gt;
{{hidden|id=new_id_param|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * @param id        An optional player's index in order to return the result&lt;br /&gt;
 *                  in the player's language, if supported.&lt;br /&gt;
 *                  -1: the default language, which is english.&lt;br /&gt;
 *                   0: the server language. You can use LANG_SERVER define.&lt;br /&gt;
 *                 &amp;gt;=1: the player's language.&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Database&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Localized&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|geoip_country_ex|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | Country / City&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | ✓&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=geoip_country_ex|labelonly=yes}} Looks up the full country name.&lt;br /&gt;
{{hidden|id=geoip_country_ex|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Looks up the full country name for the given IP address.&lt;br /&gt;
 *&lt;br /&gt;
 * @param ip        The IP address to lookup.&lt;br /&gt;
 * @param result    The result of the geoip lookup.&lt;br /&gt;
 * @param len       The maximum length of the result buffer.&lt;br /&gt;
 * @param id        An optional player's index in order to return the result&lt;br /&gt;
 *                  in the player's language, if supported.&lt;br /&gt;
 *                  -1: the default language, which is english.&lt;br /&gt;
 *                   0: the server language. You can use LANG_SERVER define.&lt;br /&gt;
 *                 &amp;gt;=1: the player's language.&lt;br /&gt;
 *&lt;br /&gt;
 * @return          The result length on successful lookup, 0 otherwise.&lt;br /&gt;
 */&lt;br /&gt;
native geoip_country_ex(const ip[], result[], len, id = -1);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|geoip_city|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | City&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | ✓&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=geoip_city|labelonly=yes}} Returns the (localized) city name.&lt;br /&gt;
{{hidden|id=geoip_city|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Look up the full city name for the given IP address.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  This native requires GeoIP City database, which can be retrieved from:&lt;br /&gt;
 *        http://dev.maxmind.com/geoip/geoip2/geolite2/ (MaxMind DB binary)&lt;br /&gt;
 *&lt;br /&gt;
 * @param ip        The IP address to look up.&lt;br /&gt;
 * @param result    The result of the geoip look up.&lt;br /&gt;
 * @param len       The maximum length of the result buffer.&lt;br /&gt;
 * @param id        An optional player's index in order to return the result&lt;br /&gt;
 *                  in the player's language, if supported.&lt;br /&gt;
 *                  -1: the default language, which is english.&lt;br /&gt;
 *                   0: the server language. You can use LANG_SERVER define.&lt;br /&gt;
 *                 &amp;gt;=1: the player's language.&lt;br /&gt;
 *&lt;br /&gt;
 * @return          The result length on successful lookup, 0 otherwise.&lt;br /&gt;
 */&lt;br /&gt;
native geoip_city(const ip[], result[], len, id = -1);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | colspan=2 style=&amp;quot;padding: 0;&amp;quot; |&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|geoip_continent_code|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | City&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | ✗&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=geoip_continent_code|labelonly=yes}} Returns the continent code. Example: {{tt|EU}} (Europe)&lt;br /&gt;
{{hidden|id=geoip_continent_code|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Looks up the continent code for a given IP address.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  This native requires GeoIP City database, which can be retrieved from:&lt;br /&gt;
 *        http://dev.maxmind.com/geoip/geoip2/geolite2/ (MaxMind DB binary)&lt;br /&gt;
 * @note  The code can be retrieved as integer (See CONTINENT_* constants.) or string (2 characters).&lt;br /&gt;
 * @note  Possible continent codes are AF, AN, AS, EU, NA, OC, SA for&lt;br /&gt;
 *        Africa(1), Antarctica(2), Asia(3), Europe(4), North America(5), Oceania(6), South America(7).&lt;br /&gt;
 *&lt;br /&gt;
 * @param ip        The IP address to look up.&lt;br /&gt;
 * @param result    The result of the geoip look up.&lt;br /&gt;
 *&lt;br /&gt;
 * @return          The continent id on successful lookup, 0 otherwise.&lt;br /&gt;
 */&lt;br /&gt;
enum Continent&lt;br /&gt;
{&lt;br /&gt;
    CONTINENT_UNKNOWN = 0,&lt;br /&gt;
    CONTINENT_AFRICA,&lt;br /&gt;
    CONTINENT_ANTARCTICA,&lt;br /&gt;
    CONTINENT_ASIA,&lt;br /&gt;
    CONTINENT_EUROPE,&lt;br /&gt;
    CONTINENT_NORTH_AMERICA,&lt;br /&gt;
    CONTINENT_OCEANIA,&lt;br /&gt;
    CONTINENT_SOUTH_AMERICA,&lt;br /&gt;
};&lt;br /&gt;
native Continent:geoip_continent_code(const ip[], result[3]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|geoip_continent_name|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | City&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | ✓&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=geoip_continent_name|labelonly=yes}} Returns the (localized) continent name. Example: {{tt|Europe}}&lt;br /&gt;
{{hidden|id=geoip_continent_name|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Look up the full continent name for the given IP address.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  This native requires GeoIP City database, which can be retrieved from:&lt;br /&gt;
 *        http://dev.maxmind.com/geoip/geoip2/geolite2/ (MaxMind DB binary)&lt;br /&gt;
 *&lt;br /&gt;
 * @param ip        The IP address to look up.&lt;br /&gt;
 * @param result    The result of the geoip look up.&lt;br /&gt;
 * @param len       The maximum length of the result buffer.&lt;br /&gt;
 * @param id        An optional player's index in order to return the result&lt;br /&gt;
 *                  in the player's language, if supported.&lt;br /&gt;
 *                  -1: the default language, which is english.&lt;br /&gt;
 *                   0: the server language. You can use LANG_SERVER define.&lt;br /&gt;
 *                 &amp;gt;=1: the player's language.&lt;br /&gt;
 *&lt;br /&gt;
 * @return          The result length on successful lookup, 0 otherwise.&lt;br /&gt;
 */&lt;br /&gt;
native geoip_continent_name(const ip[], result[], len, id = -1);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | colspan=2 style=&amp;quot;padding: 0;&amp;quot; |&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|geoip_region_code|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | City&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | ✗&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=geoip_region_code|labelonly=yes}} Returns a region code.&lt;br /&gt;
{{hidden|id=geoip_region_code|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Look up the region/state code for the given IP address.&lt;br /&gt;
 * e.g. &amp;quot;US-OH&amp;quot;, &amp;quot;DE-HH&amp;quot;, IT-82, &amp;quot;FR-U&amp;quot;, etc.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  This native requires GeoIP City database, which can be retrieved from:&lt;br /&gt;
 *        http://dev.maxmind.com/geoip/geoip2/geolite2/ (MaxMind DB binary)&lt;br /&gt;
 *&lt;br /&gt;
 * @param ip        The IP address to look up.&lt;br /&gt;
 * @param result    The result of the geoip look up.&lt;br /&gt;
 * @param len       The maximum length of the result buffer.&lt;br /&gt;
 *&lt;br /&gt;
 * @return          The result length on successful lookup, 0 otherwise.&lt;br /&gt;
 */&lt;br /&gt;
native geoip_region_code(const ip[], result[], len);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|geoip_region_name|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | City&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | ✓&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=geoip_region_name|labelonly=yes}} Returns a (localized) region name.&lt;br /&gt;
{{hidden|id=geoip_region_name|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Look up the full region/state name for the given IP address.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  This native requires GeoIP City database, which can be retrieved from:&lt;br /&gt;
 *        http://dev.maxmind.com/geoip/geoip2/geolite2/ (MaxMind DB binary)&lt;br /&gt;
 *&lt;br /&gt;
 * @param ip        The IP address to look up.&lt;br /&gt;
 * @param result    The result of the geoip look up.&lt;br /&gt;
 * @param len       The maximum length of the result buffer.&lt;br /&gt;
 * @param id        An optional player's index in order to return the result&lt;br /&gt;
 *                  in the player's language, if supported.&lt;br /&gt;
 *                  -1: the default language, which is english.&lt;br /&gt;
 *                   0: the server language. You can use LANG_SERVER define.&lt;br /&gt;
 *                 &amp;gt;=1: the player's language.&lt;br /&gt;
 *&lt;br /&gt;
 * @return          The result length on successful lookup, 0 otherwise.&lt;br /&gt;
 */&lt;br /&gt;
native geoip_region_name(const ip[], result[], len, id = -1);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | colspan=2 style=&amp;quot;padding: 0;&amp;quot; |&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|geoip_latitude|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | City&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | ✗&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=geoip_latitude|labelonly=yes}} Returns a city's latitude.&lt;br /&gt;
{{hidden|id=geoip_latitude|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Look up the city's latitude for the given IP address.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  This native requires GeoIP City database, which can be retrieved from:&lt;br /&gt;
 *        http://dev.maxmind.com/geoip/geoip2/geolite2/ (MaxMind DB binary)&lt;br /&gt;
 *&lt;br /&gt;
 * @param ip        The IP address to look up.&lt;br /&gt;
 *&lt;br /&gt;
 * @return          The result of the geoip look up, 0 if latitude is not found.&lt;br /&gt;
 */&lt;br /&gt;
native Float:geoip_latitude(const ip[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|geoip_longitude|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | City&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | ✗&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=geoip_longitude|labelonly=yes}} Returns a city's longitude.&lt;br /&gt;
{{hidden|id=geoip_longitude|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Look up the city's longitude for the given IP address.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  This native requires GeoIP City database, which can be retrieved from:&lt;br /&gt;
 *        http://dev.maxmind.com/geoip/geoip2/geolite2/ (MaxMind DB binary)&lt;br /&gt;
 *&lt;br /&gt;
 * @param ip        The IP address to look up.&lt;br /&gt;
 *&lt;br /&gt;
 * @return          The result of the geoip look up, 0 if longitude is not found.&lt;br /&gt;
 */&lt;br /&gt;
native Float:geoip_longitude(const ip[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|geoip_distance|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | City&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | ✗&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=geoip_distance|labelonly=yes}} Calculates the distance between geographical coordinates.&lt;br /&gt;
{{hidden|id=geoip_distance|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Calculate the distance between geographical coordinates, latitude and longitude.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  This native requires GeoIP City database, which can be retrieved from:&lt;br /&gt;
 *        http://dev.maxmind.com/geoip/geoip2/geolite2/ (MaxMind DB binary)&lt;br /&gt;
 *&lt;br /&gt;
 * @param lat1      The first IP latitude.&lt;br /&gt;
 * @param lon1      The first IP longitude.&lt;br /&gt;
 * @param lat2      The second IP latitude.&lt;br /&gt;
 * @param lon2      The second IP longitude.&lt;br /&gt;
 * @param system    The system of measurement, 0 = Metric(kilometers) or 1 = English(miles).&lt;br /&gt;
 *&lt;br /&gt;
 * @return          The distance as result in specified system of measurement.&lt;br /&gt;
 */&lt;br /&gt;
#define SYSTEM_METRIC   0 // kilometers&lt;br /&gt;
#define SYSTEM_IMPERIAL 1 // statute miles&lt;br /&gt;
&lt;br /&gt;
native Float:geoip_distance(Float:lat1, Float:lon1, Float:lat2, Float:lon2, system = SYSTEM_METRIC);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | colspan=2 style=&amp;quot;padding: 0;&amp;quot; |&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|geoip_timezone|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | City&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align:center;&amp;quot; | ✗&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=geoip_timezone|labelonly=yes}} Returns a full time zone. Example: {{tt|Europe/Paris}}&lt;br /&gt;
{{hidden|id=geoip_timezone|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Look up the full time zone for the given IP address.&lt;br /&gt;
 * e.g. America/Los_Angeles, Europe/Paris.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  This native requires GeoIP City database, which can be retrieved from:&lt;br /&gt;
 *        http://dev.maxmind.com/geoip/geoip2/geolite2/ (MaxMind DB binary)&lt;br /&gt;
 *&lt;br /&gt;
 * @param ip        The IP address to look up.&lt;br /&gt;
 * @param result    The result of the geoip look up.&lt;br /&gt;
 * @param len       The maximum length of the result buffer.&lt;br /&gt;
 *&lt;br /&gt;
 * @return          The result length on successful lookup, 0 otherwise.&lt;br /&gt;
 */&lt;br /&gt;
native geoip_timezone(const ip[], result[], len);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hamsandwich ===&lt;br /&gt;
&lt;br /&gt;
''' Games support '''&lt;br /&gt;
&lt;br /&gt;
The following games are now supported:&lt;br /&gt;
* Deathmatch Classic&lt;br /&gt;
* Adrenaline Gamer&lt;br /&gt;
* Opposing Forces&lt;br /&gt;
&lt;br /&gt;
The following games have been updated to their latest version:&lt;br /&gt;
* Sven Coop v5.17&lt;br /&gt;
&lt;br /&gt;
''' ItemInfo structure '''&lt;br /&gt;
&lt;br /&gt;
A new set of functions have added to manage the {{{tt|ItemInfo}} structure.&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|CreateHamItemInfo|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=CreateHamItemInfo|header=Creates an ItemInfo handle. &amp;lt;br /&amp;gt;The handle can be used in {{tt|GetHamItemInfo|bgcolor=white}} and {{tt|SetHamItemInfo|bgcolor=white}}.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Creates an ItemInfo handle.  This value should never be altered.&lt;br /&gt;
 * The handle can be used in Get/SetHamItemInfo.&lt;br /&gt;
 *&lt;br /&gt;
 * NOTE: You must call FreeHamItemInfo() on every handle made with CreateHamItemInfo().&lt;br /&gt;
 *&lt;br /&gt;
 * @return			A new ItemInfo handle.&lt;br /&gt;
 */&lt;br /&gt;
native CreateHamItemInfo();&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|FreeHamItemInfo|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=FreeHamItemInfo|header=Frees an ItemIndo handle created with {{tt|CreateHamItemInfo|bgcolor=white}}.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Frees an ItemIndo handle created with CreateHamItemInfo().  Do not call&lt;br /&gt;
 * this more than once per handle, or on handles not created through&lt;br /&gt;
 * CreateHamItemInfo().&lt;br /&gt;
 *&lt;br /&gt;
 * @param itemInfo_handle	ItemInfo handle created via CreateHamItemInfo().&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native FreeHamItemInfo(itemInfo_handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|GetHamItemInfo|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|SetHamItemInfo|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=GetHamItemInfo|header=Gets a parameter on the fly of the current hook.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets a parameter on the fly of the current hook.&lt;br /&gt;
 * Use this on parameters that are iteminfo result handles.&lt;br /&gt;
 *&lt;br /&gt;
 * @param iteminfo_handle	Item info handle.&lt;br /&gt;
 * @param type				Item info type. See HamItemInfo constants.&lt;br /&gt;
 */&lt;br /&gt;
native GetHamItemInfo(iteminfo_handle, HamItemInfo:type, any:...);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=SetHamItemInfo|header=Sets a parameter on the fly of the current hook.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a parameter on the fly of the current hook.&lt;br /&gt;
 * Use this on parameters that are iteminfo result handles.&lt;br /&gt;
 *&lt;br /&gt;
 * @param iteminfo_handle	Item info handle.&lt;br /&gt;
 * @param type				Item info type. See HamItemInfo_ constants.&lt;br /&gt;
 */&lt;br /&gt;
native SetHamItemInfo(iteminfo_handle, HamItemInfo:type, any:...);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|SetHamParamItemInfo|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=SetHamParamItemInfo|header=Sets a parameter on the fly of the current hook.  This has no effect in post hooks.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a parameter on the fly of the current hook.  This has no effect in post hooks.&lt;br /&gt;
 * Use this on parameters that are trace result handles.&lt;br /&gt;
 *&lt;br /&gt;
 * @param which				Which parameter to change.  Starts at 1, and works up from the left to right.  1 is always &amp;quot;this&amp;quot;.&lt;br /&gt;
 * @param iteminfo_handle	The value to change it to.&lt;br /&gt;
 */&lt;br /&gt;
native SetHamParamItemInfo(which, iteminfo_handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' Miscellaneous '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|SetParamEntity2|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=SetParamEntity2|header=Sets a parameter on the fly of the current hook.  This has no effect in post hooks&lt;br /&gt;
{{alert|info|Note:| Same as {{tt|SetHamParamEntity|bgcolor=white}} except the changes made by this native are reflected in the corresponding post forward.|opt=full-border}}&lt;br /&gt;
 .|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a parameter on the fly of the current hook.  This has no effect in post hooks.&lt;br /&gt;
 * Use this on parameters that are entities.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Same as SetHamParamEntity except the changes made by this native are reflected in the corresponding post forward.&lt;br /&gt;
 *&lt;br /&gt;
 * @param which				Which parameter to change.  Starts at 1, and works up from the left to right.  1 is always &amp;quot;this&amp;quot;.&lt;br /&gt;
 * @param value				The value to change it to.&lt;br /&gt;
 */&lt;br /&gt;
native SetHamParamEntity2(which, value);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' Special bot '''&lt;br /&gt;
&lt;br /&gt;
{{tt|RegisterHam}} has now the ability to register a bot without {{tt|player}} classname.&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Parameter&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|RegisterHam|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|specialbot|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=RegisterHam|header=Whether or not to enable support for bot without &amp;quot;player&amp;quot; classname.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Hooks the virtual table for the specified entity class.&lt;br /&gt;
 * An example would be: RegisterHam(Ham_TakeDamage, &amp;quot;player&amp;quot;, &amp;quot;player_hurt&amp;quot;);&lt;br /&gt;
 * Look at the Ham enum for parameter lists.&lt;br /&gt;
 *&lt;br /&gt;
 * @param function		The function to hook.&lt;br /&gt;
 * @param EntityClass	The entity classname to hook.&lt;br /&gt;
 * @param callback		The forward to call.&lt;br /&gt;
 * @param post			Whether or not to forward this in post.&lt;br /&gt;
 * @param specialbot	Whether or not to enable support for bot without &amp;quot;player&amp;quot; classname.&lt;br /&gt;
 * @return 				Returns a handle to the forward.  Use EnableHamForward/DisableHamForward to toggle the forward on or off.&lt;br /&gt;
 */&lt;br /&gt;
native HamHook:RegisterHam(Ham:function, const EntityClass[], const Callback[], Post=0, bool:specialbot = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
For convenience a stock to make more intuitive registering a function on &amp;quot;player&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Stock&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|RegisterHamPlayer|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=RegisterHamPlayer|header=Hooks the virtual table for the player class.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Hooks the virtual table for the player class.&lt;br /&gt;
 * An example would be: RegisterHam(Ham_TakeDamage, &amp;quot;player_hurt&amp;quot;);&lt;br /&gt;
 * Look at the Ham enum for parameter lists.&lt;br /&gt;
 *&lt;br /&gt;
 * @param function		The function to hook.&lt;br /&gt;
 * @param callback		The forward to call.&lt;br /&gt;
 * @param post			Whether or not to forward this in post.&lt;br /&gt;
 * @return 				Returns a handle to the forward.  Use EnableHamForward/DisableHamForward to toggle the forward on or off.&lt;br /&gt;
 */&lt;br /&gt;
stock HamHook:RegisterHamPlayer(Ham:function, const Callback[], Post=0)&lt;br /&gt;
{&lt;br /&gt;
    return RegisterHam(function, &amp;quot;player&amp;quot;, Callback, Post, true);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' Virtual function '''&lt;br /&gt;
&lt;br /&gt;
A lot of missing virtual functions have been added for all games.&amp;lt;br /&amp;gt;&lt;br /&gt;
Some of the existing common functions have been renamed because they are mod-dependent.&lt;br /&gt;
&lt;br /&gt;
Short overview:&lt;br /&gt;
* {{hidden|id=v-common|labelonly=yes}} Common&lt;br /&gt;
{{hidden|id=v-common|contentonly=yes|content=&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
Ham_ChangeYaw&lt;br /&gt;
Ham_HasHumanGibs&lt;br /&gt;
Ham_HasAlienGibs&lt;br /&gt;
Ham_FadeMonster&lt;br /&gt;
Ham_GibMonster&lt;br /&gt;
Ham_BecomeDead&lt;br /&gt;
Ham_IRelationship&lt;br /&gt;
Ham_PainSound&lt;br /&gt;
Ham_ReportAIState&lt;br /&gt;
Ham_MonsterInitDead&lt;br /&gt;
Ham_Look&lt;br /&gt;
Ham_BestVisibleEnemy&lt;br /&gt;
Ham_FInViewCone&lt;br /&gt;
Ham_FVecInViewCone&lt;br /&gt;
Ham_GetDeathActivity&lt;br /&gt;
Ham_Item_GetItemInfo&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
* {{hidden|id=v-common-2|labelonly=yes}} Common (not supported by Counter-Strike, The Specialists and Natural Selection mods)&lt;br /&gt;
{{hidden|id=v-common-2|contentonly=yes|content=&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
Ham_RunAI,&lt;br /&gt;
Ham_MonsterThink,&lt;br /&gt;
Ham_MonsterInit,&lt;br /&gt;
Ham_CheckLocalMove,&lt;br /&gt;
Ham_Move,&lt;br /&gt;
Ham_MoveExecute,&lt;br /&gt;
Ham_ShouldAdvanceRoute,&lt;br /&gt;
Ham_GetStoppedActivity,&lt;br /&gt;
Ham_Stop,&lt;br /&gt;
Ham_CheckRangeAttack1,&lt;br /&gt;
Ham_CheckRangeAttack2,&lt;br /&gt;
Ham_CheckMeleeAttack1,&lt;br /&gt;
Ham_CheckMeleeAttack2,&lt;br /&gt;
Ham_ScheduleChange,&lt;br /&gt;
Ham_CanPlaySequence,&lt;br /&gt;
Ham_CanPlaySentence,&lt;br /&gt;
Ham_PlaySentence,&lt;br /&gt;
Ham_PlayScriptedSentence,&lt;br /&gt;
Ham_SentenceStop,&lt;br /&gt;
Ham_GetIdealState,&lt;br /&gt;
Ham_SetActivity,&lt;br /&gt;
Ham_CheckEnemy,&lt;br /&gt;
Ham_FTriangulate,&lt;br /&gt;
Ham_SetYawSpeed,&lt;br /&gt;
Ham_BuildNearestRoute,&lt;br /&gt;
Ham_FindCover,&lt;br /&gt;
Ham_CoverRadius,&lt;br /&gt;
Ham_FCanCheckAttacks,&lt;br /&gt;
Ham_CheckAmmo,&lt;br /&gt;
Ham_IgnoreConditions,&lt;br /&gt;
Ham_FValidateHintType,&lt;br /&gt;
Ham_FCanActiveIdle,&lt;br /&gt;
Ham_ISoundMask,&lt;br /&gt;
Ham_HearingSensitivity,&lt;br /&gt;
Ham_BarnacleVictimBitten,&lt;br /&gt;
Ham_BarnacleVictimReleased,&lt;br /&gt;
Ham_PrescheduleThink,&lt;br /&gt;
Ham_DeathSound,&lt;br /&gt;
Ham_AlertSound,&lt;br /&gt;
Ham_IdleSound,&lt;br /&gt;
Ham_StopFollowing,&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
* {{hidden|id=v-cs|labelonly=yes}} Specific to Counter-Strike&lt;br /&gt;
{{hidden|id=v-cs|contentonly=yes|content=&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
Ham_CS_Item_IsWeapon&lt;br /&gt;
Ham_CS_Weapon_SendWeaponAnim&lt;br /&gt;
Ham_CS_Player_ResetMaxSpeed&lt;br /&gt;
Ham_CS_Player_IsBot&lt;br /&gt;
Ham_CS_Player_GetAutoaimVector&lt;br /&gt;
Ham_CS_Player_Blind&lt;br /&gt;
Ham_CS_Player_OnTouchingWeapon&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
* {{hidden|id=v-dod|labelonly=yes}} Specific to Day Of Defeat&lt;br /&gt;
{{hidden|id=v-dod|contentonly=yes|content=&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
Ham_DOD_SetScriptReset&lt;br /&gt;
Ham_DOD_Item_SpawnDeploy&lt;br /&gt;
Ham_DOD_Item_SetDmgTime&lt;br /&gt;
Ham_DOD_Item_DropGren&lt;br /&gt;
Ham_DOD_Weapon_IsUseable&lt;br /&gt;
Ham_DOD_Weapon_Aim&lt;br /&gt;
Ham_DOD_Weapon_flAim&lt;br /&gt;
Ham_DOD_Weapon_RemoveStamina&lt;br /&gt;
Ham_DOD_Weapon_ChangeFOV&lt;br /&gt;
Ham_DOD_Weapon_ZoomOut&lt;br /&gt;
Ham_DOD_Weapon_ZoomIn&lt;br /&gt;
Ham_DOD_Weapon_GetFOV&lt;br /&gt;
Ham_DOD_Weapon_PlayerIsWaterSniping&lt;br /&gt;
Ham_DOD_Weapon_UpdateZoomSpeed&lt;br /&gt;
Ham_DOD_Weapon_Special&lt;br /&gt;
Ham_DOD_Weapon_SendWeaponAnim&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
* {{hidden|id=v-esf|labelonly=yes}} Specific to Earth's Special Forces&lt;br /&gt;
{{hidden|id=v-esf|contentonly=yes|content=&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
Ham_ESF_IsFighter&lt;br /&gt;
Ham_ESF_IsBuddy&lt;br /&gt;
Ham_ESF_EmitSound&lt;br /&gt;
Ham_ESF_EmitNullSound&lt;br /&gt;
Ham_ESF_IncreaseStrength&lt;br /&gt;
Ham_ESF_IncreasePL&lt;br /&gt;
Ham_ESF_SetPowerLevel&lt;br /&gt;
Ham_ESF_SetMaxPowerLevel&lt;br /&gt;
Ham_ESF_StopAniTrigger&lt;br /&gt;
Ham_ESF_StopFly&lt;br /&gt;
Ham_ESF_HideWeapon&lt;br /&gt;
Ham_ESF_ClientRemoveWeapon&lt;br /&gt;
Ham_ESF_SendClientsCustomModel&lt;br /&gt;
Ham_ESF_CanTurbo&lt;br /&gt;
Ham_ESF_CanPrimaryFire&lt;br /&gt;
Ham_ESF_CanSecondaryFire&lt;br /&gt;
Ham_ESF_CanStopFly&lt;br /&gt;
Ham_ESF_CanBlock&lt;br /&gt;
Ham_ESF_CanRaiseKi&lt;br /&gt;
Ham_ESF_CanRaiseStamina&lt;br /&gt;
Ham_ESF_CanTeleport&lt;br /&gt;
Ham_ESF_CanStartFly&lt;br /&gt;
Ham_ESF_CanStartPowerup&lt;br /&gt;
Ham_ESF_CanJump&lt;br /&gt;
Ham_ESF_CanWallJump&lt;br /&gt;
Ham_ESF_IsSuperJump&lt;br /&gt;
Ham_ESF_IsMoveBack&lt;br /&gt;
Ham_ESF_CheckWallJump&lt;br /&gt;
Ham_ESF_EnableWallJump&lt;br /&gt;
Ham_ESF_DisableWallJump&lt;br /&gt;
Ham_ESF_ResetWallJumpVars&lt;br /&gt;
Ham_ESF_GetWallJumpAnim&lt;br /&gt;
Ham_ESF_GetWallJumpAnim2&lt;br /&gt;
Ham_ESF_SetWallJumpAnimation&lt;br /&gt;
Ham_ESF_SetFlyMoveType&lt;br /&gt;
Ham_ESF_IsFlyMoveType&lt;br /&gt;
Ham_ESF_IsWalkMoveType&lt;br /&gt;
Ham_ESF_SetWalkMoveType&lt;br /&gt;
Ham_ESF_DrawChargeBar&lt;br /&gt;
Ham_ESF_StartBlock&lt;br /&gt;
Ham_ESF_StopBlock&lt;br /&gt;
Ham_ESF_StartFly&lt;br /&gt;
Ham_ESF_GetMaxSpeed&lt;br /&gt;
Ham_ESF_SetAnimation&lt;br /&gt;
Ham_ESF_PlayAnimation&lt;br /&gt;
Ham_ESF_GetMoveForward&lt;br /&gt;
Ham_ESF_GetMoveRight&lt;br /&gt;
Ham_ESF_GetMoveUp&lt;br /&gt;
Ham_ESF_AddBlindFX&lt;br /&gt;
Ham_ESF_RemoveBlindFX&lt;br /&gt;
Ham_ESF_DisablePSBar&lt;br /&gt;
Ham_ESF_AddBeamBoxCrosshair&lt;br /&gt;
Ham_ESF_RemoveBeamBoxCrosshair&lt;br /&gt;
Ham_ESF_DrawPSWinBonus&lt;br /&gt;
Ham_ESF_DrawPSBar&lt;br /&gt;
Ham_ESF_LockCrosshair&lt;br /&gt;
Ham_ESF_UnLockCrosshair&lt;br /&gt;
Ham_ESF_RotateCrosshair&lt;br /&gt;
Ham_ESF_UnRotateCrosshair&lt;br /&gt;
Ham_ESF_WaterMove&lt;br /&gt;
Ham_ESF_CheckTimeBasedDamage&lt;br /&gt;
Ham_ESF_DoesSecondaryAttack&lt;br /&gt;
Ham_ESF_DoesPrimaryAttack&lt;br /&gt;
Ham_ESF_RemoveSpecialModes&lt;br /&gt;
Ham_ESF_StopTurbo&lt;br /&gt;
Ham_ESF_TakeBean&lt;br /&gt;
Ham_ESF_GetPowerLevel&lt;br /&gt;
Ham_ESF_RemoveAllOtherWeapons&lt;br /&gt;
Ham_ESF_StopSwoop&lt;br /&gt;
Ham_ESF_SetDeathAnimation&lt;br /&gt;
Ham_ESF_SetModel&lt;br /&gt;
Ham_ESF_AddAttacks&lt;br /&gt;
Ham_ESF_EmitClassSound&lt;br /&gt;
Ham_ESF_CheckLightning&lt;br /&gt;
Ham_ESF_FreezeControls&lt;br /&gt;
Ham_ESF_UnFreezeControls&lt;br /&gt;
Ham_ESF_UpdateKi&lt;br /&gt;
Ham_ESF_UpdateHealth&lt;br /&gt;
Ham_ESF_GetTeleportDir&lt;br /&gt;
Ham_ESF_Weapon_HolsterWhenMeleed&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
* {{hidden|id=v-ns|labelonly=yes}} Specific to Natural Selection&lt;br /&gt;
{{hidden|id=v-ns|contentonly=yes|content=&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
Ham_NS_SetBoneController&lt;br /&gt;
Ham_NS_SaveDataForReset&lt;br /&gt;
Ham_NS_GetHull&lt;br /&gt;
Ham_NS_GetMaxWalkSpeed&lt;br /&gt;
Ham_NS_SetTeamID&lt;br /&gt;
Ham_NS_GetEffectivePlayerClass&lt;br /&gt;
Ham_NS_GetAuthenticationMask&lt;br /&gt;
Ham_NS_EffectivePlayerClassChanged&lt;br /&gt;
Ham_NS_NeedsTeamUpdate&lt;br /&gt;
Ham_NS_SendTeamUpdate&lt;br /&gt;
Ham_NS_SendWeaponUpdate&lt;br /&gt;
Ham_NS_InitPlayerFromSpawn&lt;br /&gt;
Ham_NS_PackDeadPlayerItems&lt;br /&gt;
Ham_NS_GetAnimationForActivity&lt;br /&gt;
Ham_NS_StartObserver&lt;br /&gt;
Ham_NS_StopObserver&lt;br /&gt;
Ham_NS_GetAdrenalineFactor&lt;br /&gt;
Ham_NS_GiveNamedItem&lt;br /&gt;
Ham_NS_Suicide&lt;br /&gt;
Ham_NS_GetCanUseWeapon&lt;br /&gt;
Ham_NS_Weapon_GetWeaponPrimeTime&lt;br /&gt;
Ham_NS_Weapon_PrimeWeapon&lt;br /&gt;
Ham_NS_Weapon_GetIsWeaponPrimed&lt;br /&gt;
Ham_NS_Weapon_GetIsWeaponPriming&lt;br /&gt;
Ham_NS_Weapon_DefaultDeploy&lt;br /&gt;
Ham_NS_Weapon_DefaultReload&lt;br /&gt;
Ham_NS_Weapon_GetDeployTime&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
* {{hidden|id=v-sc|labelonly=yes}} Specific to Sven Coop&lt;br /&gt;
{{hidden|id=v-sc|contentonly=yes|content=&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
Ham_SC_GetClassification,&lt;br /&gt;
Ham_SC_IsMonster,&lt;br /&gt;
Ham_SC_IsPhysX,&lt;br /&gt;
Ham_SC_IsPointEntity,&lt;br /&gt;
Ham_SC_IsMachine,&lt;br /&gt;
Ham_SC_CriticalRemove,&lt;br /&gt;
Ham_SC_UpdateOnRemove,&lt;br /&gt;
Ham_SC_FVisible,&lt;br /&gt;
Ham_SC_FVisibleFromPos,&lt;br /&gt;
Ham_SC_IsFacings,&lt;br /&gt;
Ham_SC_GetPointsForDamage,&lt;br /&gt;
Ham_SC_GetDamagePoints,&lt;br /&gt;
Ham_SC_OnCreate,&lt;br /&gt;
Ham_SC_OnDestroy,&lt;br /&gt;
Ham_SC_IsValidEntity,&lt;br /&gt;
Ham_SC_ShouldFadeOnDeath,&lt;br /&gt;
Ham_SC_SetupFriendly,&lt;br /&gt;
Ham_SC_ReviveThink,&lt;br /&gt;
Ham_SC_Revive,&lt;br /&gt;
Ham_SC_StartMonster,&lt;br /&gt;
Ham_SC_CheckRangeAttack1_Move,&lt;br /&gt;
Ham_SC_CheckRangeAttack2_Move,&lt;br /&gt;
Ham_SC_CheckMeleeAttack1_Move,&lt;br /&gt;
Ham_SC_CheckMeleeAttack2_Move,&lt;br /&gt;
Ham_SC_CheckTankUsage,&lt;br /&gt;
Ham_SC_SetGaitActivity,&lt;br /&gt;
Ham_SC_FTriangulate,&lt;br /&gt;
Ham_SC_FTriangulateExtension,&lt;br /&gt;
Ham_SC_FindCoverGrenade,&lt;br /&gt;
Ham_SC_FindCoverDistance,&lt;br /&gt;
Ham_SC_FindAttackPoint,&lt;br /&gt;
Ham_SC_FValidateCover,&lt;br /&gt;
Ham_SC_NoFriendlyFire1,&lt;br /&gt;
Ham_SC_NoFriendlyFire2,&lt;br /&gt;
Ham_SC_NoFriendlyFire3,&lt;br /&gt;
Ham_SC_NoFriendlyFireToPos,&lt;br /&gt;
Ham_SC_FVisibleGunPos,&lt;br /&gt;
Ham_SC_FInBulletCone,&lt;br /&gt;
Ham_SC_CallGibMonster,&lt;br /&gt;
Ham_SC_CheckTimeBasedDamage,&lt;br /&gt;
Ham_SC_IsMoving,&lt;br /&gt;
Ham_SC_IsPlayerFollowing,&lt;br /&gt;
Ham_SC_StartPlayerFollowing,&lt;br /&gt;
Ham_SC_StopPlayerFollowing,&lt;br /&gt;
Ham_SC_UseSound,&lt;br /&gt;
Ham_SC_UnUseSound,&lt;br /&gt;
Ham_SC_RideMonster,&lt;br /&gt;
Ham_SC_CheckApplyGenericAttacks,&lt;br /&gt;
Ham_SC_CheckScared,&lt;br /&gt;
Ham_SC_CheckCreatureDanger,&lt;br /&gt;
Ham_SC_CheckFallDamage,&lt;br /&gt;
Ham_SC_CheckRevival,&lt;br /&gt;
Ham_SC_MedicCallSound,&lt;br /&gt;
&lt;br /&gt;
Ham_SC_Player_MenuInputPerformed,&lt;br /&gt;
Ham_SC_Player_IsMenuInputDone,&lt;br /&gt;
Ham_SC_Player_SpecialSpawn,&lt;br /&gt;
Ham_SC_Player_IsValidInfoEntity,&lt;br /&gt;
Ham_SC_Player_LevelEnd,&lt;br /&gt;
Ham_SC_Player_VoteStarted,&lt;br /&gt;
Ham_SC_Player_CanStartNextVote,&lt;br /&gt;
Ham_SC_Player_Vote,&lt;br /&gt;
Ham_SC_Player_HasVoted,&lt;br /&gt;
Ham_SC_Player_ResetVote,&lt;br /&gt;
Ham_SC_Player_LastVoteInput,&lt;br /&gt;
Ham_SC_Player_InitVote,&lt;br /&gt;
Ham_SC_Player_TimeToStartNextVote,&lt;br /&gt;
Ham_SC_Player_ResetView,&lt;br /&gt;
Ham_SC_Player_GetLogFrequency,&lt;br /&gt;
Ham_SC_Player_LogPlayerStats,&lt;br /&gt;
Ham_SC_Player_DisableCollisionWithPlayer,&lt;br /&gt;
Ham_SC_Player_EnableCollisionWithPlayer,&lt;br /&gt;
Ham_SC_Player_CanTouchPlayer,&lt;br /&gt;
&lt;br /&gt;
Ham_SC_Item_Materialize,&lt;br /&gt;
&lt;br /&gt;
Ham_SC_Weapon_BulletAccuracy,&lt;br /&gt;
Ham_SC_Weapon_TertiaryAttack,&lt;br /&gt;
Ham_SC_Weapon_BurstSupplement,&lt;br /&gt;
Ham_SC_Weapon_GetP_Model,&lt;br /&gt;
Ham_SC_Weapon_GetW_Model,&lt;br /&gt;
Ham_SC_Weapon_GetV_Model,&lt;br /&gt;
Ham_SC_Weapon_PrecacheCustomModels,&lt;br /&gt;
Ham_SC_Weapon_IsMultiplayer,&lt;br /&gt;
Ham_SC_Weapon_FRunfuncs,&lt;br /&gt;
Ham_SC_Weapon_SetFOV,&lt;br /&gt;
Ham_SC_Weapon_FCanRun,&lt;br /&gt;
Ham_SC_Weapon_CustomDecrement,&lt;br /&gt;
Ham_SC_Weapon_SetV_Model,&lt;br /&gt;
Ham_SC_Weapon_SetP_Model,&lt;br /&gt;
Ham_SC_Weapon_ChangeWeaponSkin,&lt;br /&gt;
&lt;br /&gt;
Ham_SC_TakeHealth,&lt;br /&gt;
Ham_SC_TakeArmor,&lt;br /&gt;
Ham_SC_GiveAmmo,&lt;br /&gt;
Ham_SC_CheckAttacker,&lt;br /&gt;
Ham_SC_Player_IsConnected,&lt;br /&gt;
&lt;br /&gt;
Ham_SC_PreSpawn,&lt;br /&gt;
Ham_SC_PostSpawn,&lt;br /&gt;
Ham_SC_OnKeyValueUpdate,&lt;br /&gt;
Ham_SC_SetClassification,&lt;br /&gt;
Ham_SC_IsTriggered,&lt;br /&gt;
Ham_SC_MyCustomPointer,&lt;br /&gt;
Ham_SC_MyItemPointer,&lt;br /&gt;
Ham_SC_AddPoints,&lt;br /&gt;
Ham_SC_AddPointsToTeam,&lt;br /&gt;
Ham_SC_RemovePlayerItem,&lt;br /&gt;
Ham_SC_OnControls,&lt;br /&gt;
Ham_SC_IsSneaking,&lt;br /&gt;
Ham_SC_IsAlive,&lt;br /&gt;
Ham_SC_IsBSPModel,&lt;br /&gt;
Ham_SC_ReflectGauss,&lt;br /&gt;
Ham_SC_HasTarget,&lt;br /&gt;
Ham_SC_IsInWorld,&lt;br /&gt;
Ham_SC_IsPlayer,&lt;br /&gt;
Ham_SC_IsNetClient,&lt;br /&gt;
Ham_SC_IsBreakable,&lt;br /&gt;
Ham_SC_SUB_UseTargets,&lt;br /&gt;
Ham_SC_IsLockedByMaster,&lt;br /&gt;
Ham_SC_FBecomeProne,&lt;br /&gt;
Ham_SC_FVecVisible,&lt;br /&gt;
Ham_SC_SetPlayerAlly,&lt;br /&gt;
Ham_SC_OnSetOriginByMap,&lt;br /&gt;
Ham_SC_IsRevivable,&lt;br /&gt;
Ham_SC_BeginRevive,&lt;br /&gt;
Ham_SC_EndRevive,&lt;br /&gt;
Ham_SC_CanPlaySequence,&lt;br /&gt;
Ham_SC_CanPlaySentence2,&lt;br /&gt;
Ham_SC_PlayScriptedSentence,&lt;br /&gt;
Ham_SC_Item_AddToPlayer,&lt;br /&gt;
Ham_SC_Item_AddDuplicate,&lt;br /&gt;
Ham_SC_Item_AddAmmoFromItem,&lt;br /&gt;
Ham_SC_Item_GetPickupSound,&lt;br /&gt;
Ham_SC_Item_CanCollect,&lt;br /&gt;
Ham_SC_Item_Collect,&lt;br /&gt;
Ham_SC_Item_GetItemInfo,&lt;br /&gt;
Ham_SC_Item_CanDeploy,&lt;br /&gt;
Ham_SC_Item_Deploy,&lt;br /&gt;
Ham_SC_Item_CanHolster,&lt;br /&gt;
Ham_SC_Item_InactiveItemPreFrame,&lt;br /&gt;
Ham_SC_Item_InactiveItemPostFrame,&lt;br /&gt;
Ham_SC_Item_DetachFromPlayer,&lt;br /&gt;
Ham_SC_Item_UpdateClientData,&lt;br /&gt;
Ham_SC_Item_GetRespawnTime,&lt;br /&gt;
Ham_SC_Item_CanHaveDuplicates,&lt;br /&gt;
Ham_SC_Weapon_ExtractAmmoFromItem,&lt;br /&gt;
Ham_SC_Weapon_AddWeapon,&lt;br /&gt;
Ham_SC_Weapon_GetAmmo1Drop,&lt;br /&gt;
Ham_SC_Weapon_GetAmmo2Drop,&lt;br /&gt;
Ham_SC_Weapon_PlayEmptySound,&lt;br /&gt;
Ham_SC_Weapon_IsUsable,&lt;br /&gt;
Ham_SC_Weapon_FinishReload,&lt;br /&gt;
Ham_SC_Weapon_ShouldReload,&lt;br /&gt;
Ham_SC_Weapon_ShouldWeaponIdle,&lt;br /&gt;
Ham_SC_Weapon_UseDecrement,&lt;br /&gt;
Ham_SC_Player_EnteredObserver,&lt;br /&gt;
Ham_SC_Player_LeftObserver,&lt;br /&gt;
Ham_SC_Player_IsObserver,&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
* {{hidden|id=v-opf|labelonly=yes}} Specific to Opposing Force&lt;br /&gt;
{{hidden|id=v-opf|contentonly=yes|content=&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
Ham_OPF_MySquadTalkMonsterPointer&lt;br /&gt;
Ham_OPF_WeaponTimeBase&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
* {{hidden|id=v-tfc|labelonly=yes}} Specific to Team Fortress Classic&lt;br /&gt;
{{hidden|id=v-tfc|contentonly=yes|content=&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
Ham_TFC_DB_GetItemName&lt;br /&gt;
Ham_TFC_IsTriggered&lt;br /&gt;
Ham_TFC_Killed&lt;br /&gt;
Ham_TFC_RadiusDamage&lt;br /&gt;
Ham_TFC_RadiusDamage2&lt;br /&gt;
Ham_TFC_Weapon_GetNextAttackDelay&lt;br /&gt;
Ham_TFC_Weapon_SendWeaponAnim&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
* {{hidden|id=v-ts|labelonly=yes}} Specific to The Specialists&lt;br /&gt;
{{hidden|id=v-ts|contentonly=yes|content=&lt;br /&gt;
&amp;lt;text&amp;gt;&lt;br /&gt;
Ham_TS_Weapon_AlternateAttack&lt;br /&gt;
&amp;lt;/text&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
See [https://github.com/alliedmodders/amxmodx/blob/master/plugins/include/ham_const.inc#L1182 ham_const.inc] for a full list (it starts from line 1182).&lt;br /&gt;
&lt;br /&gt;
=== MySQL ===&lt;br /&gt;
&lt;br /&gt;
''' Connectivity '''&lt;br /&gt;
&lt;br /&gt;
To improve the connectivity, few features have been added.&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Feature&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | ''Reconnection''&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | This has MySQL automatically reconnects if times out or loses connection through {{tt|MYSQL_OPT_RECONNECT|bgcolor=white}} option.&amp;lt;br /&amp;gt; This should prevent &amp;quot;MySQL server has gone away&amp;quot; errors after a while.&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | ''Timeout''&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | This establishes a default read/write timeout for MySQL connectivity through {{tt|MYSQL_OPT_CONNECT_TIMEOUT|bgcolor=white}} option. &amp;lt;br /&amp;gt;A new option to set globally the timeout (60s by default) can be found in {{tt|core.ini|bgcolor=white}} {{hidden|id=mysql_timeout|labelonly=yes}} and a new {{tt|amx_sql_timeout|bgcolor=white}} cvar in {{tt|sql.cfg|bgcolor=white}} {{hidden|id=cvar_timeout|labelonly=yes}}.&lt;br /&gt;
{{hidden|id=mysql_timeout|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
; MySQL default timeout&lt;br /&gt;
mysql_timeout 60&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=cvar_timeout|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
amx_sql_timeout &amp;quot;60&amp;quot;&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' Miscellaneous '''&lt;br /&gt;
&lt;br /&gt;
* Module threading has been updated to be more responsive. This should help in reducing potential hang up in situations such as on change map or lost connection.&lt;br /&gt;
&lt;br /&gt;
''' Character Set '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Stock&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|MySQL_SetCharset|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=MySQL_SetCharset|header=Sets the character set of the current connection.|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets the character set of the current connection.&lt;br /&gt;
 * Like SET NAMES .. in mysql, but stays after connection problems.&lt;br /&gt;
 *&lt;br /&gt;
 * If a connection tuple is supplied, this should be called before SQL_Connect or SQL_ThreadQuery.&lt;br /&gt;
 * Also note the change will remain until you call this function with another value.&lt;br /&gt;
 * This native does nothing in SQLite.&lt;br /&gt;
 *&lt;br /&gt;
 * Example: &amp;quot;utf8&amp;quot;, &amp;quot;latin1&amp;quot;&lt;br /&gt;
 *&lt;br /&gt;
 * @param h					Database or connection tuple Handle.&lt;br /&gt;
 * @param charset			The character set string to change to.&lt;br /&gt;
 * @return					True, if character set was changed, false otherwise.&lt;br /&gt;
 */&lt;br /&gt;
native bool:SQL_SetCharset(Handle:h, const charset[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RegEx ===&lt;br /&gt;
&lt;br /&gt;
''' Library '''&lt;br /&gt;
&lt;br /&gt;
The internal {{texttip|PCRE|Perl Compatible Regular Expressions}} library version has been updated from {{tt|6.4|bgcolor=none}} to {{tt|8.35|bgcolor=none}} and has been compiled with UTF-8 support. &amp;lt;br /&amp;gt;&lt;br /&gt;
If you are interested, see the [https://github.com/alliedmodders/amxmodx/blob/master/tools/pcre/ChangeLog changelog].&lt;br /&gt;
&lt;br /&gt;
''' Miscellaneous '''&lt;br /&gt;
&lt;br /&gt;
* {{tt|regex_subtr}}: The internal static buffer has been increased to match the same size as core and has been made UTF-8 safe.&lt;br /&gt;
* The maximum number of sub-patterns has been increased from {{tt|30|bgcolor=none}} to {{tt|150|bgcolor=none}}.&lt;br /&gt;
&lt;br /&gt;
''' New Natives &amp;amp; Stocks '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|regex_compile_ex|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=regex_compile_ex|header=Precompiles a regular expression. &lt;br /&gt;
 &lt;br /&gt;
 {{alert|info|Note:|Similar as {{tt|regex_compile/_c|bgcolor=white}} but with the differences that you can use directly {{tt|PCRE_*|bgcolor=white}} {{hidden|id=pcre_flags|labelonly=yes}} flags and the error parameter is an integer associated to {{tt|REGEX_ERROR_*|bgcolor=white}} {{hidden|id=regex_errors|labelonly=yes}} flags.|opt=full-border}}&lt;br /&gt;
 &lt;br /&gt;
|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Precompiles a regular expression.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  Use this if you intend on using the same expression multiple times.&lt;br /&gt;
 *        Pass the regex handle returned here to regex_match_c() to check for matches.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  Unlike regex_compile(), this allows you to use PCRE flags directly.&lt;br /&gt;
 *&lt;br /&gt;
 * @param pattern       The regular expression pattern.&lt;br /&gt;
 * @param flags         General flags for the regular expression, see PCRE_* defines.&lt;br /&gt;
 * @param error         Error message encountered, if applicable.&lt;br /&gt;
 * @param maxLen        Maximum string length of the error buffer.&lt;br /&gt;
 * @param errcode       Regex type error code encountered, if applicable. See REGEX_ERROR_* defines.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              Valid regex handle (&amp;gt; 0) on success, or -1 on failure.&lt;br /&gt;
 */&lt;br /&gt;
native Regex:regex_compile_ex(const pattern[], flags = 0, error[]= &amp;quot;&amp;quot;, maxLen = 0, &amp;amp;errcode = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=pcre_flags|contentonly=yes|content=&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Flags for compiling regex expressions.&lt;br /&gt;
 * These come directly from the pcre library and can be used in regex_compile_ex.&lt;br /&gt;
 */&lt;br /&gt;
#define PCRE_CASELESS           0x00000001  /* Ignore Case */&lt;br /&gt;
#define PCRE_MULTILINE          0x00000002  /* Multilines (affects ^ and $ so that they match the start/end of a line rather than matching the start/end of the string). */&lt;br /&gt;
#define PCRE_DOTALL             0x00000004  /* Single line (affects . so that it matches any character, even new line characters). */&lt;br /&gt;
#define PCRE_EXTENDED           0x00000008  /* Pattern extension (ignore whitespace and # comments). */&lt;br /&gt;
#define PCRE_ANCHORED           0x00000010  /* Force pattern anchoring. */&lt;br /&gt;
#define PCRE_DOLLAR_ENDONLY     0x00000020  /* $ not to match newline at end. */&lt;br /&gt;
#define PCRE_UNGREEDY           0x00000200  /* Invert greediness of quantifiers */&lt;br /&gt;
#define PCRE_NOTEMPTY           0x00000400  /* An empty string is not a valid match. */&lt;br /&gt;
#define PCRE_UTF8               0x00000800  /* Use UTF-8 Chars */&lt;br /&gt;
#define PCRE_NO_UTF8_CHECK      0x00002000  /* Do not check the pattern for UTF-8 validity (only relevant if PCRE_UTF8 is set) */&lt;br /&gt;
#define PCRE_NEVER_UTF          0x00010000  /* Lock out interpretation of the pattern as UTF-8 */&lt;br /&gt;
#define PCRE_FIRSTLINE          0x00040000  /* Force matching to be before newline */&lt;br /&gt;
#define PCRE_DUPNAMES           0x00080000  /* Allow duplicate names for subpattern */&lt;br /&gt;
#define PCRE_NEWLINE_CR         0x00100000  /* Specify that a newline is indicated by a single character CR           )                            */&lt;br /&gt;
#define PCRE_NEWLINE_CRLF       0x00300000  /* specify that a newline is indicated by the two-character CRLF sequence )  Overrides the default     */&lt;br /&gt;
#define PCRE_NEWLINE_ANY        0x00400000  /* Specify that any Unicode newline sequence should be recognized.        )  newline definition (LF)   */&lt;br /&gt;
#define PCRE_NEWLINE_ANYCRLF    0x00500000  /* Specify that any of CR, LF and CRLF sequences should be recognized     )                            */&lt;br /&gt;
#define PCRE_UCP                0x20000000  /* Change the way PCRE processes \B, \b, \D, \d, \S, \s, \W, \w etc. to use Unicode properties */&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=regex_errors|contentonly=yes|content=&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Regex expression error codes.&lt;br /&gt;
 * This can be used with regex_compile_ex and regex_match_ex.&lt;br /&gt;
 */&lt;br /&gt;
enum /*RegexError*/&lt;br /&gt;
{&lt;br /&gt;
    REGEX_ERROR_NONE           =  0,    /* No error */&lt;br /&gt;
    REGEX_ERROR_NOMATCH        = -1,    /* No match was found */&lt;br /&gt;
    REGEX_ERROR_NULL           = -2,&lt;br /&gt;
    REGEX_ERROR_BADOPTION      = -3,&lt;br /&gt;
    REGEX_ERROR_BADMAGIC       = -4,&lt;br /&gt;
    REGEX_ERROR_UNKNOWN_OPCODE = -5,&lt;br /&gt;
    REGEX_ERROR_NOMEMORY       = -6,&lt;br /&gt;
    REGEX_ERROR_NOSUBSTRING    = -7,&lt;br /&gt;
    REGEX_ERROR_MATCHLIMIT     = -8,&lt;br /&gt;
    REGEX_ERROR_CALLOUT        = -9,    /* Never used by PCRE itself */&lt;br /&gt;
    REGEX_ERROR_BADUTF8        = -10,&lt;br /&gt;
    REGEX_ERROR_BADUTF8_OFFSET = -11,&lt;br /&gt;
    REGEX_ERROR_PARTIAL        = -12,&lt;br /&gt;
    REGEX_ERROR_BADPARTIAL     = -13,&lt;br /&gt;
    REGEX_ERROR_INTERNAL       = -14,&lt;br /&gt;
    REGEX_ERROR_BADCOUNT       = -15,&lt;br /&gt;
    REGEX_ERROR_DFA_UITEM      = -16,&lt;br /&gt;
    REGEX_ERROR_DFA_UCOND      = -17,&lt;br /&gt;
    REGEX_ERROR_DFA_UMLIMIT    = -18,&lt;br /&gt;
    REGEX_ERROR_DFA_WSSIZE     = -19,&lt;br /&gt;
    REGEX_ERROR_DFA_RECURSE    = -20,&lt;br /&gt;
    REGEX_ERROR_RECURSIONLIMIT = -21,&lt;br /&gt;
    REGEX_ERROR_NULLWSLIMIT    = -22,   /* No longer actually used */&lt;br /&gt;
    REGEX_ERROR_BADNEWLINE     = -23,&lt;br /&gt;
    REGEX_ERROR_BADOFFSET      = -24,&lt;br /&gt;
    REGEX_ERROR_SHORTUTF8      = -25,&lt;br /&gt;
    REGEX_ERROR_RECURSELOOP    = -26,&lt;br /&gt;
    REGEX_ERROR_JIT_STACKLIMIT = -27,&lt;br /&gt;
    REGEX_ERROR_BADMODE        = -28,&lt;br /&gt;
    REGEX_ERROR_BADENDIANNESS  = -29,&lt;br /&gt;
    REGEX_ERROR_DFA_BADRESTART = -30,&lt;br /&gt;
    REGEX_ERROR_JIT_BADOPTION  = -31,&lt;br /&gt;
    REGEX_ERROR_BADLENGTH      = -32,&lt;br /&gt;
    REGEX_ERROR_UNSET          = -33&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|regex_match_all|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|regex_match_all_c|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=regex_match_all|header=Matches a string against a regular (compiled) expression pattern, matching all occurrences of the pattern inside the string. &lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|This is similar to using the {{tt|g|bgcolor=white}} flag in perl regex.|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Matches a string against a regular expression pattern, matching all occurrences of the&lt;br /&gt;
 * pattern inside the string. This is similar to using the &amp;quot;g&amp;quot; flag in perl regex.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  If you intend on using the same regular expression pattern&lt;br /&gt;
 *        multiple times, consider using regex_compile and regex_match_ex&lt;br /&gt;
 *        instead of making this function reparse the expression each time.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  Flags only exist in amxmodx 1.8 and later.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  You should free the returned handle with regex_free()&lt;br /&gt;
 *        when you are done extracting all of the substrings.&lt;br /&gt;
 *&lt;br /&gt;
 * @param string        The string to check.&lt;br /&gt;
 * @param pattern       The regular expression pattern.&lt;br /&gt;
 * @param flags         General flags for the regular expression, see PCRE_* defines.&lt;br /&gt;
 * @param error         Error message encountered, if applicable.&lt;br /&gt;
 * @param maxLen        Maximum string length of the error buffer.&lt;br /&gt;
 * @param errcode       Regex type error code encountered, if applicable. See REGEX_ERROR_* defines.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              -2 = Matching error (error code is stored in ret)&lt;br /&gt;
 *                      -1 = Error in pattern (error message and offset # in error and ret)&lt;br /&gt;
 *                       0 = No match.&lt;br /&gt;
 *                      &amp;gt;1 = Handle for getting more information (via regex_substr)&lt;br /&gt;
 */&lt;br /&gt;
native Regex:regex_match_all(const string[], const pattern[], flags = 0, error[]= &amp;quot;&amp;quot;, maxLen = 0, &amp;amp;errcode = 0);&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Matches a string against a pre-compiled regular expression pattern, matching all&lt;br /&gt;
 * occurrences of the pattern inside the string. This is similar to using the &amp;quot;g&amp;quot; flag&lt;br /&gt;
 * in perl regex.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  You should free the returned handle (with regex_free())&lt;br /&gt;
 *        when you are done with this pattern.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  Use the regex handle passed to this function to extract&lt;br /&gt;
 *        matches with regex_substr().&lt;br /&gt;
 *&lt;br /&gt;
 * @param pattern       The regular expression pattern.&lt;br /&gt;
 * @param string        The string to check.&lt;br /&gt;
 * @param ret           Error code, if applicable, or number of results on success.&lt;br /&gt;
 *                      See REGEX_ERROR_* defines.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              -2 = Matching error (error code is stored in ret)&lt;br /&gt;
 *                       0 = No match.&lt;br /&gt;
 *                      &amp;gt;1 = Number of results.&lt;br /&gt;
 */&lt;br /&gt;
native regex_match_all_c(const string[], Regex:pattern, &amp;amp;ret = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Stock&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|regex_match_simple|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=regex_match_simple|header=Matches a string against a regular expression pattern. Useful if you need to use the pattern one time.}|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Matches a string against a regular expression pattern.&lt;br /&gt;
 *&lt;br /&gt;
 * @note  If you intend on using the same regular expression pattern&lt;br /&gt;
 *        multiple times, consider using compile regex_compile_ex and regex_match*&lt;br /&gt;
 *        instead of making this function reparse the expression each time.&lt;br /&gt;
 *&lt;br /&gt;
 * @param str           The string to check.&lt;br /&gt;
 * @param pattern       The regular expression pattern.&lt;br /&gt;
 * @param flags         General flags for the regular expression.&lt;br /&gt;
 * @param error         Error message, if applicable.&lt;br /&gt;
 * @param maxLen        Maximum length of the error buffer.&lt;br /&gt;
 * @param errcode       Regex type error code encountered, if applicable. See REGEX_ERROR_* defines.&lt;br /&gt;
 *&lt;br /&gt;
 * @return              -2 = Matching error (error code is stored in ret)&lt;br /&gt;
 *                      -1 = Pattern error (error code is stored in ret)&lt;br /&gt;
 *                       0 = No match.&lt;br /&gt;
 *                      &amp;gt;1 = Number of results.&lt;br /&gt;
 */&lt;br /&gt;
stock regex_match_simple(const str[], const pattern[], flags = 0, error[]= &amp;quot;&amp;quot;, maxLen = 0, &amp;amp;errcode = 0)&lt;br /&gt;
{&lt;br /&gt;
    new Regex:regex = regex_compile_ex(pattern, flags, error, maxLen, errcode);&lt;br /&gt;
    if (regex &amp;lt; REGEX_OK)&lt;br /&gt;
    {&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
    new substrings = regex_match_c(str, regex);&lt;br /&gt;
    regex_free(regex);&lt;br /&gt;
    return substrings;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Socket ===&lt;br /&gt;
&lt;br /&gt;
* WinSock is now update from version {{tt|1.1|bgcolor=white}} to {{tt|2.2|bgcolor=white}}&lt;br /&gt;
* Natives won't be registered if WinSock can't be started&lt;br /&gt;
&lt;br /&gt;
''' Improvements '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Parameter&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=socket_open|labelonly=yes}} {{tt|socket_open|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|_flags|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | &lt;br /&gt;
The following flags are additive:&lt;br /&gt;
* {{tt|SOCK_NON_BLOCKING|bgcolor=white}}: if set, the socket will be on nonblocking mode&lt;br /&gt;
* {{tt|SOCK_LIBC_ERRORS|bgcolor=white}}: f set, the new libc errors will be seen on {{tt|_error|bgcolor=white}}&lt;br /&gt;
&lt;br /&gt;
{{hidden|id=socket_open|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Error reporting&lt;br /&gt;
 */&lt;br /&gt;
#define SOCK_ERROR_OK               0 /* No error */&lt;br /&gt;
#define SOCK_ERROR_CREATE_SOCKET    1 /* Couldn't create a socket */&lt;br /&gt;
#define SOCK_ERROR_SERVER_UNKNOWN   2 /* Server unknown */&lt;br /&gt;
#define SOCK_ERROR_WHILE_CONNECTING 3 /* Error while connecting */&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Connects to the given node and service via TCP/UDP.&lt;br /&gt;
 *&lt;br /&gt;
 * @note There's 2 types of error reporting on this function that you can use.&lt;br /&gt;
 * @note Default error codes:&lt;br /&gt;
 *       0 - No error&lt;br /&gt;
 *       1 - Error while creating socket&lt;br /&gt;
 *       2 - Couldn't resolve hostname&lt;br /&gt;
 *       3 - Couldn't connect&lt;br /&gt;
 * @note New, more expressive libc error codes:&lt;br /&gt;
 *       https://www.gnu.org/software/libc/manual/html_node/Error-Codes.html&lt;br /&gt;
 *       https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/errno.h&lt;br /&gt;
 *       https://msdn.microsoft.com/en-us/library/ms740668.aspx&lt;br /&gt;
 *&lt;br /&gt;
 * @note The currently available bit flags are:&lt;br /&gt;
 *       - SOCK_NON_BLOCKING : if set, the socket will be on nonblocking mode&lt;br /&gt;
 *       - SOCK_LIBC_ERRORS : if set, the new libc errors will be seen on _error&lt;br /&gt;
 *&lt;br /&gt;
 * @note If no flags are set, the behaviour of the function will not be modified.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Multiple flags may be set at the same time using the | operator. &lt;br /&gt;
 *       For example, SOCK_NON_BLOCKING|SOCK_LIBC_ERRORS will create a nonblocking socket with libc error codes.&lt;br /&gt;
 *&lt;br /&gt;
 * @note If you're creating a new nonblocking socket, _hostname should be numeric to avoid calling the &lt;br /&gt;
 *       name resolution server and potentially blocking the call.&lt;br /&gt;
 *&lt;br /&gt;
 * @note If the socket is a nonblocking one, the returned socket descriptor may be still connecting and &lt;br /&gt;
 *       further checks should be done with socket_is_writable() before trying to send data.&lt;br /&gt;
 *&lt;br /&gt;
 * @param _hostname    Node to connect to&lt;br /&gt;
 * @param _port        Service to connect to&lt;br /&gt;
 * @param _protocol    Connect via SOCKET_TCP or SOCKET_UDP&lt;br /&gt;
 * @param _error       Set an error code here if anything goes wrong&lt;br /&gt;
 * @param _flags       Optional bit flags that change the behaviour of the function&lt;br /&gt;
 *&lt;br /&gt;
 * @return             A socket descriptor (a positive integer) on success&lt;br /&gt;
 *                     -1 on failure&lt;br /&gt;
*/&lt;br /&gt;
native socket_open(const _hostname[], _port, _protocol = SOCKET_TCP, &amp;amp;_error, _flags = 0);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|An example is available at [https://github.com/alliedmodders/amxmodx/pull/301#issuecomment-204794080 PR 301]|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
''' New natives '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|socket_is_writable|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=socket_is_writable|header=Checks if a socket is marked as writable.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Checks if a socket is marked as writable.&lt;br /&gt;
 *&lt;br /&gt;
 * @note Use this function to check if a nonblocking socket is ready to be used.&lt;br /&gt;
 * @note Set _timeout to 0 avoid blocking the call.&lt;br /&gt;
 * @note An UDP socket is always writable.&lt;br /&gt;
 *&lt;br /&gt;
 * @param _socket    Socket descriptor&lt;br /&gt;
 * @param _timeout   Amount of time to block the call waiting for the socket to be marked as writable or&lt;br /&gt;
 *                   for the timeout to expire, in µSeconds (1 sec = 1000000 µsec)&lt;br /&gt;
 *&lt;br /&gt;
 * @return           1 if the socket is marked as writable&lt;br /&gt;
 *                   0 otherwise&lt;br /&gt;
 */&lt;br /&gt;
native socket_is_writable(_socket, _timeout = 100000);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|socket_is_readable|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=socket_is_readable|header=Checks if a socket is marked as readable.&lt;br /&gt;
&lt;br /&gt;
 {{alert|info|Note:|This function is an alias of {{tt|socket_change}} which is now deprecated.|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
 |labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Checks if a socket is marked as readable.&lt;br /&gt;
 *&lt;br /&gt;
 * @note You can use this function to make sure there's something on the socket and avoid a blocking call.&lt;br /&gt;
 * @note Set _timeout to 0 avoid blocking the call.&lt;br /&gt;
 * @note A socket will become readable if there's any data or an EOF.&lt;br /&gt;
 *&lt;br /&gt;
 * @param _socket    Socket descriptor&lt;br /&gt;
 * @param _timeout   Amount of time to block the call waiting for the socket to be marked as readable or&lt;br /&gt;
 *                   for the timeout to expire, in µSeconds (1 sec = 1000000 µsec)&lt;br /&gt;
 *&lt;br /&gt;
 * @return           1 if the socket is marked as readable&lt;br /&gt;
 *                   0 otherwise&lt;br /&gt;
 */&lt;br /&gt;
native socket_is_readable(_socket, _timeout = 100000);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SQLite ===&lt;br /&gt;
&lt;br /&gt;
''' Library '''&lt;br /&gt;
&lt;br /&gt;
The SQLite library version has been updated from {{tt|3.3.13|bgcolor=none}} to {{tt|3.24.0|bgcolor=none}}. &amp;lt;br /&amp;gt;&lt;br /&gt;
If you are interested, see the [https://www.sqlite.org/changes.html changelog].&lt;br /&gt;
&lt;br /&gt;
''' Character Set '''&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Stock&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|SQL_SetCharset|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=SQL_SetCharset|header=Sets the character set of the current connection.|labelpos=left||content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets the character set of the current connection.&lt;br /&gt;
 * Like SET NAMES .. in mysql, but stays after connection problems.&lt;br /&gt;
 *&lt;br /&gt;
 * If a connection tuple is supplied, this should be called before SQL_Connect or SQL_ThreadQuery.&lt;br /&gt;
 * Also note the change will remain until you call this function with another value.&lt;br /&gt;
 * This native does nothing in SQLite.&lt;br /&gt;
 *&lt;br /&gt;
 * Example: &amp;quot;utf8&amp;quot;, &amp;quot;latin1&amp;quot;&lt;br /&gt;
 *&lt;br /&gt;
 * @param h					Database or connection tuple Handle.&lt;br /&gt;
 * @param charset			The character set string to change to.&lt;br /&gt;
 * @return					True, if character set was changed, false otherwise.&lt;br /&gt;
 */&lt;br /&gt;
native bool:SQL_SetCharset(Handle:h, const charset[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
''' Miscellaneous '''&lt;br /&gt;
&lt;br /&gt;
* The {{tt|queuetime}} value is now properly passed to the {{tt|SQL_ThreadQuery|bgcolor=none}} callback.&lt;br /&gt;
&lt;br /&gt;
== New module ==&lt;br /&gt;
&lt;br /&gt;
=== JSON ===&lt;br /&gt;
&lt;br /&gt;
A JSON module is now part of the official AMX Mod X package.&lt;br /&gt;
&lt;br /&gt;
Essentially:&lt;br /&gt;
* Supports decoding and encoding (also with pretty format)&lt;br /&gt;
* Relies on Parson, which is lighweight and simple JSON library written in C&lt;br /&gt;
* Supports dot notation (Values can be accessed by typing objectA.objectB.value)&lt;br /&gt;
* Allows us to iterate through arrays and objects&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|Examples are available on [https://github.com/alliedmodders/amxmodx/pull/379 Github] an in the {{tt|testsuite}} directory, see [https://github.com/alliedmodders/amxmodx/blob/master/plugins/testsuite/textparse_test.sma textparse.sma].|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Native&lt;br /&gt;
 ! style=&amp;quot;padding: 0.4em;&amp;quot; | Description&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align: center; background-color: white;&amp;quot; colspan=&amp;quot;2&amp;quot; | {{color|steelblue|General}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_parse|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_parse|header=Parses JSON string or a file that contains JSON.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Parses JSON string or a file that contains JSON.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    Needs to be freed using json_free() native.&lt;br /&gt;
 *&lt;br /&gt;
 * @param string            String to parse&lt;br /&gt;
 * @param is_file           True to treat string param as filename, false otherwise&lt;br /&gt;
 * @param with_comments     True if parsing JSON includes comments (it will ignore them), false otherwise&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  JSON handle, Invalid_JSONValue if error occurred&lt;br /&gt;
 */&lt;br /&gt;
native JSON:json_parse(const string[], bool:is_file = false, bool:with_comments = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_equals|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_equals|header=Checks if the first value is the same as the second one.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Checks if the first value is the same as the second one.&lt;br /&gt;
 *&lt;br /&gt;
 * @param value1            JSON handle&lt;br /&gt;
 * @param value2            JSON handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if they are the same, false otherwise&lt;br /&gt;
 * @error                   If passed value is not a valid handle&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_equals(const JSON:value1, const JSON:value2);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_validate|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_validate|header=Validates json by checking if object have identically named fields with matching types.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Validates json by checking if object have identically named&lt;br /&gt;
 * fields with matching types.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    Schema {&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;, &amp;quot;age&amp;quot;:0} will validate&lt;br /&gt;
 *                          {&amp;quot;name&amp;quot;:&amp;quot;Joe&amp;quot;, &amp;quot;age&amp;quot;:25} and {&amp;quot;name&amp;quot;:&amp;quot;Joe&amp;quot;, &amp;quot;age&amp;quot;:25, &amp;quot;gender&amp;quot;:&amp;quot;m&amp;quot;},&lt;br /&gt;
 *                          but not {&amp;quot;name&amp;quot;:&amp;quot;Joe&amp;quot;} or {&amp;quot;name&amp;quot;:&amp;quot;Joe&amp;quot;, &amp;quot;age&amp;quot;:&amp;quot;Cucumber&amp;quot;}.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    In case of arrays, only first value in schema&lt;br /&gt;
 *                          is checked against all values in tested array.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    Empty objects ({}) validate all objects,&lt;br /&gt;
 *                          empty arrays ([]) validate all arrays,&lt;br /&gt;
 *                          null validates values of every type.&lt;br /&gt;
 *&lt;br /&gt;
 * @param schema            JSON handle&lt;br /&gt;
 * @param value             JSON handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if passed value is valid, false otherwise&lt;br /&gt;
 * @error                   If a schema handle or value handle is invalid&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_validate(const JSON:schema, const JSON:value);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_get_parent|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_get_parent|header=Gets value's parent handle.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets value's parent handle.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                  Parent's handle needs to be freed using json_free() native.&lt;br /&gt;
 *&lt;br /&gt;
 * @param value           JSON handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return                Parent's handle&lt;br /&gt;
 */&lt;br /&gt;
native JSON:json_get_parent(const JSON:value);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_get_type|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_get_type|header=Gets JSON type of passed value.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets JSON type of passed value.&lt;br /&gt;
 *&lt;br /&gt;
 * @param value             JSON handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  JSON type (JSONType constants)&lt;br /&gt;
 * @error                   If a value handle is invalid&lt;br /&gt;
 */&lt;br /&gt;
native JSONType:json_get_type(const JSON:value);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_init_object|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_init_array|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_init_string|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_init_number|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_init_real|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_init_bool|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_init_object|header=Inits an empty object.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Inits an empty object.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    Needs to be freed using json_free() native.&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  JSON handle, Invalid_JSON if error occurred&lt;br /&gt;
 */&lt;br /&gt;
native JSON:json_init_object();&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_init_array|header=Inits an empty array.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Inits an empty array.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    Needs to be freed using json_free() native.&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  JSON handle, Invalid_JSON if error occurred&lt;br /&gt;
 */&lt;br /&gt;
native JSON:json_init_array();&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_init_string|header=Inits string data.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Inits string data.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    Needs to be freed using json_free() native.&lt;br /&gt;
 *&lt;br /&gt;
 * @param value             String that the handle will be initialized with&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  JSON handle, Invalid_JSON if error occurred&lt;br /&gt;
 */&lt;br /&gt;
native JSON:json_init_string(const value[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_init_number|header=Inits a number.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Inits a number.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    Needs to be freed using json_free() native.&lt;br /&gt;
 *&lt;br /&gt;
 * @param value             Integer number that the handle will be initialized with&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  JSON handle, Invalid_JSON if error occurred&lt;br /&gt;
 */&lt;br /&gt;
native JSON:json_init_number(value);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_init_real|header=Inits a real number.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Inits a real number.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    Needs to be freed using json_free() native.&lt;br /&gt;
 *&lt;br /&gt;
 * @param value             Real number that the handle will be initialized with&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  JSON handle, Invalid_JSON if error occurred&lt;br /&gt;
 */&lt;br /&gt;
native JSON:json_init_real(Float:value);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_init_bool|header=Inits a boolean value.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Inits a boolean value.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    Needs to be freed using json_free() native.&lt;br /&gt;
 *&lt;br /&gt;
 * @param value             Boolean value that the handle will be initialized with&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  JSON handle, Invalid_JSON if error occurred&lt;br /&gt;
 */&lt;br /&gt;
native JSON:json_init_bool(bool:value);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_init_null|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_init_null|header=Inits a null.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Inits a null.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    Needs to be freed using json_free() native.&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  JSON handle, Invalid_JSON if error occurred&lt;br /&gt;
 */&lt;br /&gt;
native JSON:json_init_null();&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_deep_copy|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_deep_copy|header=Creates deep copy of passed value.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Creates deep copy of passed value.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    Needs to be freed using json_free() native.&lt;br /&gt;
 *&lt;br /&gt;
 * @param value             JSON handle to be copied&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  JSON handle, Invalid_JSON if error occurred&lt;br /&gt;
 * @error                   If passed value is not a valid handle&lt;br /&gt;
 */&lt;br /&gt;
native JSON:json_deep_copy(const JSON:value);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_free|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_free|header=Frees handle.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Frees handle.&lt;br /&gt;
 *&lt;br /&gt;
 * @param handle            JSON handle to be freed&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid handle&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_free(&amp;amp;JSON:handle);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_get_string|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_get_number|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_get_real|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_get_bool|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_get_string|header=Gets string data.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets string data.&lt;br /&gt;
 *&lt;br /&gt;
 * @param value             JSON handle&lt;br /&gt;
 * @param buffer            Buffer to copy string to&lt;br /&gt;
 * @param maxlen            Maximum size of the buffer&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  The number of cells written to the buffer&lt;br /&gt;
 * @error                   If passed value is not a valid handle&lt;br /&gt;
 */&lt;br /&gt;
native json_get_string(const JSON:value, buffer[], maxlen);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_get_number|header=Gets a number.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets a number.&lt;br /&gt;
 *&lt;br /&gt;
 * @param value             JSON handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  Number&lt;br /&gt;
 * @error                   If passed value is not a valid handle&lt;br /&gt;
 */&lt;br /&gt;
native json_get_number(const JSON:value);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_get_real|header=Gets a real number.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets a real number.&lt;br /&gt;
 *&lt;br /&gt;
 * @param value             JSON handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  Real number&lt;br /&gt;
 * @error                   If passed value is not a valid handle&lt;br /&gt;
 */&lt;br /&gt;
native Float:json_get_real(const JSON:value);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_get_bool|header=Gets a boolean value.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets a boolean value.&lt;br /&gt;
 *&lt;br /&gt;
 * @param value             JSON handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  Boolean value&lt;br /&gt;
 * @error                   If passed value is not a valid handle&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_get_bool(const JSON:value);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align: center; background-color: white;&amp;quot; colspan=&amp;quot;2&amp;quot; | {{color|steelblue|Array}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_array_get_value|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_array_get_string|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_array_get_number|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_array_get_real|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_array_get_bool|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_array_get_count|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_array_get_value|header=Gets a value from the array.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets a value from the array.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    Needs to be freed using json_free() native.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 * @param index             Position in the array (starting from 0)&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  JSON handle, Invalid_JSON if error occurred&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native JSON:json_array_get_value(const JSON:array, index);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_array_get_string|header=Gets string data from the array.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets string data from the array.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 * @param index             Position in the array (starting from 0)&lt;br /&gt;
 * @param buffer            Buffer to copy string to&lt;br /&gt;
 * @param maxlen            Maximum size of the buffer&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  The number of cells written to the buffer&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native json_array_get_string(const JSON:array, index, buffer[], maxlen);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_array_get_number|header=Gets a number from the array.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets a number from the array.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 * @param index             Position in the array (starting from 0)&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  The number as integer&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native json_array_get_number(const JSON:array, index);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_array_get_real|header=Gets a real number from the array.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets a real number from the array.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 * @param index             Position in the array (starting from 0)&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  The number as float&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native Float:json_array_get_real(const JSON:array, index);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_array_get_bool|header=Gets a boolean value from the array.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets a boolean value from the array.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 * @param index             Position in the array (starting from 0)&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  Boolean value&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_array_get_bool(const JSON:array, index);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_array_get_count|header=Gets count of the elements in the array.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets count of the elements in the array.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  Number of elements in the array&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native json_array_get_count(const JSON:array);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_array_replace_value|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_array_replace_string|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_array_replace_number|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_array_replace_real|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_array_replace_bool|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_array_replace_null|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_array_replace_value|header=Replaces an element in the array with value.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Replaces an element in the array with value.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 * @param index             Position in the array to be replaced&lt;br /&gt;
 * @param value             JSON handle to set&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_array_replace_value(JSON:array, index, const JSON:value);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_array_replace_string|header=Replaces an element in the array with string data.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Replaces an element in the array with string data.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 * @param index             Position in the array to be replaced&lt;br /&gt;
 * @param string            String to copy&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_array_replace_string(JSON:array, index, const string[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_array_replace_number|header=Replaces an element in the array with number.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Replaces an element in the array with number.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 * @param index             Position in the array to be replaced&lt;br /&gt;
 * @param number            Number to set&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_array_replace_number(JSON:array, index, number);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_array_replace_real|header=Replaces an element in the array with real number.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Replaces an element in the array with real number.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 * @param index             Position in the array to be replaced&lt;br /&gt;
 * @param number            Real number to set&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_array_replace_real(JSON:array, index, Float:number);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_array_replace_bool|header=Replaces an element in the array with boolean value.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Replaces an element in the array with boolean value.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 * @param index             Position in the array to be replaced&lt;br /&gt;
 * @param boolean           Boolean value to set&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_array_replace_bool(JSON:array, index, bool:boolean);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_array_replace_null|header=Replaces an element in the array with null.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Replaces an element in the array with null.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 * @param index             Position in the array to be replaced&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_array_replace_null(JSON:array, index);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_array_append_value|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_array_append_string|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_array_append_number|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_array_append_real|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_array_append_bool|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_array_append_null|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_arrayjson_array_append_value_replace_null|header=Appends a value in the array.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Appends a value in the array.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 * @param value             JSON handle to set&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_array_append_value(JSON:array, const JSON:value);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_array_append_string|header=Appends string data in the array.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Appends string data in the array.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 * @param string            String to copy&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_array_append_string(JSON:array, const string[]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_array_append_number|header=Appends a number in the array.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Appends a number in the array.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 * @param number            Number to set&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_array_append_number(JSON:array, number);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_array_append_real|header=Appends a real number in the array.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Appends a real number in the array.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 * @param number            Real number to set&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_array_append_real(JSON:array, Float:number);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_array_append_bool|header=Appends a boolean value in the array.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Appends a boolean value in the array.Appends a boolean value in the array.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 * @param boolean           Boolean value to set&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_array_append_bool(JSON:array, bool:boolean);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_array_append_null|header=Appends a null in the array.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Appends a null in the array.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_array_append_null(JSON:array);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_array_remove|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_array_remove|header=Removes an element from the array.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Removes an element from the array.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    Order of values in array may change during execution.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 * @param index             Position in the array (starting from 0)&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_array_remove(JSON:array, index);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_array_clear|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_array_clear|header=Removes all elements from the array.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Removes all elements from the array.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array             Array handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid array&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_array_clear(JSON:array);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align: center; background-color: white;&amp;quot; colspan=&amp;quot;2&amp;quot; | {{color|steelblue|Object}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_object_get_value|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_object_get_string|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_object_get_number|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_object_get_real|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_object_get_bool|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_object_get_value|header=Gets a value from the object.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets a value from the object.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    Needs to be freed using json_free() native.&lt;br /&gt;
 * @note                    If dot notation is used some values may be inaccessible&lt;br /&gt;
 *                          because valid names in JSON can contain dots.&lt;br /&gt;
 *&lt;br /&gt;
 * @param object            Object handle&lt;br /&gt;
 * @param name              Key name&lt;br /&gt;
 * @param dot_not           True to use dot notation, false to not&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  JSON handle, Invalid_JSON if error occurred&lt;br /&gt;
 * @error                   If passed handle is not a valid object&lt;br /&gt;
 */&lt;br /&gt;
native JSON:json_object_get_value(const JSON:object, const name[], bool:dot_not = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_object_get_string|header=Gets string data from the object.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets string data from the object.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    If dot notation is used some values may be inaccessible&lt;br /&gt;
 *                          because valid names in JSON can contain dots.&lt;br /&gt;
 *&lt;br /&gt;
 * @param object            Object handle&lt;br /&gt;
 * @param name              Key name&lt;br /&gt;
 * @param buffer            Buffer to copy string to&lt;br /&gt;
 * @param maxlen            Maximum size of the buffer&lt;br /&gt;
 * @param dot_not           True to use dot notation, false to not&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  The number of cells written to the buffer&lt;br /&gt;
 * @error                   If passed handle is not a valid object&lt;br /&gt;
 */&lt;br /&gt;
native json_object_get_string(const JSON:object, const name[], buffer[], maxlen, bool:dot_not = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_object_get_number|header=Gets a number from the object.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets a number from the object.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    If dot notation is used some values may be inaccessible&lt;br /&gt;
 *                          because valid names in JSON can contain dots.&lt;br /&gt;
 *&lt;br /&gt;
 * @param object            Object handle&lt;br /&gt;
 * @param name              Key name&lt;br /&gt;
 * @param dot_not           True to use dot notation, false to not&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  Number&lt;br /&gt;
 * @error                   If passed handle is not a valid object&lt;br /&gt;
 */&lt;br /&gt;
native json_object_get_number(const JSON:object, const name[], bool:dot_not = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_object_get_real|header=Gets a real number from the object.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets a real number from the object.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    If dot notation is used some values may be inaccessible&lt;br /&gt;
 *                          because valid names in JSON can contain dots.&lt;br /&gt;
 *&lt;br /&gt;
 * @param object            Object handle&lt;br /&gt;
 * @param name              Key name&lt;br /&gt;
 * @param dot_not           True to use dot notation, false to not&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  Real number&lt;br /&gt;
 * @error                   If passed handle is not a valid object&lt;br /&gt;
 */&lt;br /&gt;
native Float:json_object_get_real(const JSON:object, const name[], bool:dot_not = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_object_get_bool|header=Gets a boolean value from the object.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets a boolean value from the object.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    If dot notation is used some values may be inaccessible&lt;br /&gt;
 *                          because valid names in JSON can contain dots.&lt;br /&gt;
 *&lt;br /&gt;
 * @param object            Object handle&lt;br /&gt;
 * @param name              Key name&lt;br /&gt;
 * @param dot_not           True to use dot notation, false to not&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  Boolean value&lt;br /&gt;
 * @error                   If passed handle is not a valid object&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_object_get_bool(const JSON:object, const name[], bool:dot_not = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_object_get_count|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_object_get_name|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_object_get_count|header=Gets count of the keys in the object.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets count of the keys in the object.&lt;br /&gt;
 *&lt;br /&gt;
 * @param object            Object handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  Keys count&lt;br /&gt;
 * @error                   If passed handle is not a valid object&lt;br /&gt;
 */&lt;br /&gt;
native json_object_get_count(const JSON:object);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_object_get_name|header=Gets name of the object's key.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets name of the object's key.&lt;br /&gt;
 *&lt;br /&gt;
 * @param object            Object handle&lt;br /&gt;
 * @param index             Position from which get key name&lt;br /&gt;
 * @param buffer            Buffer to copy string to&lt;br /&gt;
 * @param maxlen            Maximum size of the buffer&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  The number of cells written to the buffer&lt;br /&gt;
 * @error                   If passed handle is not a valid object&lt;br /&gt;
 */&lt;br /&gt;
native json_object_get_name(const JSON:object, index, buffer[], maxlen);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_object_get_value_at|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_object_get_value_at|header=Gets a value at the specified position from the object.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets a value at the specified position from the object.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    Needs to be freed using json_free() native.&lt;br /&gt;
 *&lt;br /&gt;
 * @param object            Object handle&lt;br /&gt;
 * @param index             Position from which get key name&lt;br /&gt;
 * @param buffer            Buffer to copy string to&lt;br /&gt;
 * @param maxlen            Maximum size of the buffer&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  The number of cells written to the buffer&lt;br /&gt;
 * @error                   If passed handle is not a valid object&lt;br /&gt;
 */&lt;br /&gt;
native JSON:json_object_get_value_at(const JSON:object, index);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_object_has_value|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_object_has_value|header=Checks if the object has a value with a specific name and type.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Checks if the object has a value with a specific name and type.&lt;br /&gt;
 *&lt;br /&gt;
 * @param object            Object handle&lt;br /&gt;
 * @param name              Key name&lt;br /&gt;
 * @param type              Type of value, if JSONError type will not be checked&lt;br /&gt;
 * @param dot_not           True to use dot notation, false to not&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if has, false if not&lt;br /&gt;
 * @error                   If passed handle is not a valid object&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_object_has_value(const JSON:object, const name[], JSONType:type = JSONError, bool:dot_not = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_object_set_value|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_object_set_string|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_object_set_number|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_object_set_real|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_object_set_bool|bgcolor=white}}&amp;lt;br /&amp;gt;{{tt|json_object_set_null|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_object_set_value|header=Sets a value in the object.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a value in the object.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    If dot notation is used some values may be inaccessible&lt;br /&gt;
 *                          because valid names in JSON can contain dots.&lt;br /&gt;
 * @note                    It also removes the old value if any.&lt;br /&gt;
 *&lt;br /&gt;
 * @param object            Object handle&lt;br /&gt;
 * @param name              Key name&lt;br /&gt;
 * @param value             JSON handle to set&lt;br /&gt;
 * @param dot_not           True to use dot notation, false to not&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid object&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_object_set_value(JSON:object, const name[], const JSON:value, bool:dot_not = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_object_set_string|header=Sets string data in the object.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets string data in the object.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    If dot notation is used some values may be inaccessible&lt;br /&gt;
 *                          because valid names in JSON can contain dots.&lt;br /&gt;
 * @note                    It also removes the old value if any.&lt;br /&gt;
 *&lt;br /&gt;
 * @param object            Object handle&lt;br /&gt;
 * @param name              Key name&lt;br /&gt;
 * @param string            String to copy&lt;br /&gt;
 * @param dot_not           True to use dot notation, false to not&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid object&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_object_set_string(JSON:object, const name[], const string[], bool:dot_not = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_object_set_number|header=Sets a number in the object.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a number in the object.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    If dot notation is used some values may be inaccessible&lt;br /&gt;
 *                          because valid names in JSON can contain dots.&lt;br /&gt;
 * @note                    It also removes the old value if any.&lt;br /&gt;
 *&lt;br /&gt;
 * @param object            Object handle&lt;br /&gt;
 * @param name              Key name&lt;br /&gt;
 * @param number            Number to set&lt;br /&gt;
 * @param dot_not           True to use dot notation, false to not&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid object&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_object_set_number(JSON:object, const name[], number, bool:dot_not = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_object_set_real|header=Sets a real number in the object.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a real number in the object.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    If dot notation is used some values may be inaccessible&lt;br /&gt;
 *                          because valid names in JSON can contain dots.&lt;br /&gt;
 * @note                    It also removes the old value if any.&lt;br /&gt;
 *&lt;br /&gt;
 * @param object            Object handle&lt;br /&gt;
 * @param name              Key name&lt;br /&gt;
 * @param number            Real number to set&lt;br /&gt;
 * @param dot_not           True to use dot notation, false to not&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid object&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_object_set_real(JSON:object, const name[], Float:number, bool:dot_not = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_object_set_bool|header=Sets a boolean value in the object.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a boolean value in the object.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    If dot notation is used some values may be inaccessible&lt;br /&gt;
 *                          because valid names in JSON can contain dots.&lt;br /&gt;
 * @note                    It also removes the old value if any.&lt;br /&gt;
 *&lt;br /&gt;
 * @param object            Object handle&lt;br /&gt;
 * @param name              Key name&lt;br /&gt;
 * @param boolean           Boolean value to set&lt;br /&gt;
 * @param dot_not           True to use dot notation, false to not&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid object&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_object_set_bool(JSON:object, const name[], bool:boolean, bool:dot_not = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
{{hidden|id=json_object_set_null|header=Sets a null in the object.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Sets a null in the object.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    If dot notation is used some values may be inaccessible&lt;br /&gt;
 *                          because valid names in JSON can contain dots.&lt;br /&gt;
 * @note                    It also removes the old value if any.&lt;br /&gt;
 *&lt;br /&gt;
 * @param object            Object handle&lt;br /&gt;
 * @param name              Key name&lt;br /&gt;
 * @param dot_not           True to use dot notation, false to not&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid object&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_object_set_null(JSON:object, const name[], bool:dot_not = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_object_remove|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_object_remove|header=Removes a key and its value in the object.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Removes a key and its value in the object.&lt;br /&gt;
 *&lt;br /&gt;
 * @note                    If dot notation is used some values may be inaccessible&lt;br /&gt;
 *                          because valid names in JSON can contain dots.&lt;br /&gt;
 *&lt;br /&gt;
 * @param object            Object handle&lt;br /&gt;
 * @param name              Key name&lt;br /&gt;
 * @param dot_not           True to use dot notation, false to not&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid object&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_object_remove(JSON:object, const name[], bool:dot_not = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_object_clear|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_object_clear|header=Removes all keys and their values in the object.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Removes all keys and their values in the object.&lt;br /&gt;
 *&lt;br /&gt;
 * @param object            Object handle&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid object&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_object_clear(JSON:object);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em; text-align: center; background-color: white;&amp;quot; colspan=&amp;quot;2&amp;quot; | {{color|steelblue|Serialization}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_serial_size|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_serial_size|header=Gets size of serialization.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Gets size of serialization.&lt;br /&gt;
 *&lt;br /&gt;
 * @param value             JSON handle&lt;br /&gt;
 * @param pretty            True to count size for pretty format, false to not&lt;br /&gt;
 * @param null_byte         True to include null byte, false to not&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  Size of serialized string&lt;br /&gt;
 * @error                   If passed handle is not a valid value&lt;br /&gt;
 */&lt;br /&gt;
native json_serial_size(const JSON:value, bool:pretty = false, bool:null_byte = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_serial_to_string|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_serial_to_string|header=Copies serialized string to the buffer.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Copies serialized string to the buffer.&lt;br /&gt;
 *&lt;br /&gt;
 * @param value             JSON handle&lt;br /&gt;
 * @param buffer            Buffer to copy string to&lt;br /&gt;
 * @param maxlen            Maximum size of the buffer&lt;br /&gt;
 * @param pretty            True to format pretty JSON string, false to not&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  The number of cells written to the buffer&lt;br /&gt;
 * @error                   If passed handle is not a valid value&lt;br /&gt;
 */&lt;br /&gt;
native json_serial_to_string(const JSON:value, buffer[], maxlen, bool:pretty = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |-&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|json_serial_to_file|bgcolor=white}}&lt;br /&gt;
 | style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=json_serial_to_file|header=Copies serialized string to the file.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Copies serialized string to the file.&lt;br /&gt;
 *&lt;br /&gt;
 * @param value             JSON handle&lt;br /&gt;
 * @param file              Path to the file&lt;br /&gt;
 * @param pretty            True to format pretty JSON string, false to not&lt;br /&gt;
 *&lt;br /&gt;
 * @return                  True if succeed, false otherwise&lt;br /&gt;
 * @error                   If passed handle is not a valid value&lt;br /&gt;
 */&lt;br /&gt;
native bool:json_serial_to_file(const JSON:value, const file[], bool:pretty = false);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{{alert|success|Constants &amp;amp; Macros:|{{hidden|id=json_example|labelonly=yes}}|opt=full-border}}&lt;br /&gt;
{{hidden|id=json_example|contentonly=yes|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * JSON types&lt;br /&gt;
 */&lt;br /&gt;
enum JSONType&lt;br /&gt;
{&lt;br /&gt;
    JSONError   = -1,&lt;br /&gt;
    JSONNull    = 1,&lt;br /&gt;
    JSONString  = 2,&lt;br /&gt;
    JSONNumber  = 3,&lt;br /&gt;
    JSONObject  = 4,&lt;br /&gt;
    JSONArray   = 5,&lt;br /&gt;
    JSONBoolean = 6&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * JSON invalid handle&lt;br /&gt;
 */&lt;br /&gt;
enum JSON&lt;br /&gt;
{&lt;br /&gt;
    Invalid_JSON = -1&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Helper macros for checking type&lt;br /&gt;
 */&lt;br /&gt;
#define json_is_object(%1)   (%1 != Invalid_JSON &amp;amp;&amp;amp; json_get_type(%1) == JSONObject)&lt;br /&gt;
#define json_is_array(%1)    (%1 != Invalid_JSON &amp;amp;&amp;amp; json_get_type(%1) == JSONArray)&lt;br /&gt;
#define json_is_string(%1)   (%1 != Invalid_JSON &amp;amp;&amp;amp; json_get_type(%1) == JSONString)&lt;br /&gt;
#define json_is_number(%1)   (%1 != Invalid_JSON &amp;amp;&amp;amp; json_get_type(%1) == JSONNumber)&lt;br /&gt;
#define json_is_bool(%1)     (%1 != Invalid_JSON &amp;amp;&amp;amp; json_get_type(%1) == JSONBoolean)&lt;br /&gt;
#define json_is_null(%1)     (%1 != Invalid_JSON &amp;amp;&amp;amp; json_get_type(%1) == JSONNull)&lt;br /&gt;
#define json_is_true(%1)     (%1 != Invalid_JSON &amp;amp;&amp;amp; json_is_bool(%1) &amp;amp;&amp;amp; json_get_bool(%1))&lt;br /&gt;
#define json_is_false(%1)    (%1 != Invalid_JSON &amp;amp;&amp;amp; json_is_bool(%1) &amp;amp;&amp;amp; !json_get_bool(%1))&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripting (AMX Mod X)]]&lt;/div&gt;</summary>
		<author><name>Shooting King</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMX_Mod_X_1.9_Release_Notes&amp;diff=11238</id>
		<title>AMX Mod X 1.9 Release Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMX_Mod_X_1.9_Release_Notes&amp;diff=11238"/>
		<updated>2021-09-30T19:18:50Z</updated>

		<summary type="html">&lt;p&gt;Shooting King: Assign a Amxmodx category&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{alert|info|&amp;lt;span style&amp;lt;nowiki&amp;gt;=&amp;lt;/nowiki&amp;gt;&amp;quot;vertical-align: super;&amp;quot;&amp;gt;[[File:Ambox_content_soft.svg|35px]]&amp;lt;/span&amp;gt;{{ns|2}}{{resize|200%|This version is not yet released. The release notes are not final.}}|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
AMX Mod X 1.9 is a major update, containing many features, fixes, and improvements under the hood.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:✓ All old plugins and modules will continue to work.&lt;br /&gt;
:✓ This release does have new configuration files.&lt;br /&gt;
:✓ This release does have configuration changes.&lt;br /&gt;
:✓ This release does include plugin changes.&lt;br /&gt;
:✓ This release does have translations changes.&lt;br /&gt;
:✓ This release does not break compatibility.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Hint:|This page includes hidden reference that you can toggle with {{tt|{{hidden|id=hint|labelonly=yes}}}}.|opt=full-border}}&lt;br /&gt;
{{hidden|id=hint|contentonly=yes|content=🙌 Congratulations for understanding the hint!{{margin|10px|}}}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Major Highlights ==&lt;br /&gt;
&lt;br /&gt;
=== GitHub ===&lt;br /&gt;
&lt;br /&gt;
A friendly reminder of the [https://forums.alliedmods.net/showthread.php?t=240468 previous announcement] on the AMX Mod X website, all development is now done on GitHub.&amp;lt;br /&amp;gt;&lt;br /&gt;
You can now check out the latest changes on https://github.com/alliedmodders/amxmodx.&lt;br /&gt;
&lt;br /&gt;
Any help is welcomed and encouraged. To contribute, there are two ways:&lt;br /&gt;
&lt;br /&gt;
* To report a bug or request a feature, you can create an issue here: https://github.com/alliedmodders/amxmodx/issues&lt;br /&gt;
* To directly contribute to the AMX Mod X repository, you can create a ''Pull Request'' by following this guide: https://wiki.alliedmods.net/Git_Tutorial.&lt;br /&gt;
: You can see the current PRs here as well: https://github.com/alliedmodders/amxmodx/pulls. &lt;br /&gt;
: → Don't hesitate to give your thoughts or to review, anyone can participate!&lt;br /&gt;
&lt;br /&gt;
=== General ===&lt;br /&gt;
&lt;br /&gt;
The improvements for AMX Mod X 1.9 span the whole project:&lt;br /&gt;
&lt;br /&gt;
* Stability and performance improvements&lt;br /&gt;
* Official support for ReHLDS and ReGameDLL&lt;br /&gt;
* Greatly improved UTF-8 support across the project&lt;br /&gt;
* Significant improvements to modules and official plugins&lt;br /&gt;
* (Almost) completely revised and completed documentation&lt;br /&gt;
* Tons of new functionalities for plugin developers and admins&lt;br /&gt;
&lt;br /&gt;
=== Compatibility ===&lt;br /&gt;
&lt;br /&gt;
For AMX Mod X plugins and modules, this release is fully backward compatible. Anything else is a bug. &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, a lot of legacy AMX Mod (no X) code has been removed, so we no longer guarantee backward compatibility for AMX Mod plugins.&lt;br /&gt;
&lt;br /&gt;
AMX Mod X contains a host of new features for developers, so plugins and modules compiled against AMX Mod X 1.9 will not run on an earlier version.&lt;br /&gt;
&lt;br /&gt;
If we are made aware of compatibility issues, we will list the known issues below while a fix is developed.&lt;br /&gt;
&lt;br /&gt;
Known Issues:&lt;br /&gt;
* None&lt;br /&gt;
&lt;br /&gt;
=== Upgrading ===&lt;br /&gt;
&lt;br /&gt;
Upgrading follows the standard procedure, however, there are some specific steps that require additional attention.&lt;br /&gt;
&lt;br /&gt;
==== General ====&lt;br /&gt;
&lt;br /&gt;
your game server is completely stopped as you cannot properly update some files while they are still in use.&lt;br /&gt;
# Replace all binaries:&lt;br /&gt;
#* Any {{tt|.so}} [[File:Linux.svg|16px]] or {{tt|.dll}} [[File:Windows.svg|16px]] files in {{tt|/amxmodx/dlls}} and {{tt|/amxmodx/modules}} folders&lt;br /&gt;
#* Any {{tt|.amxx}} files in {{tt|/amxmodx/plugins}} folder&lt;br /&gt;
# Replace languages files:&lt;br /&gt;
#* Any {{tt|.txt}} files in {{tt|/amxmodx/data/lang}} folder&lt;br /&gt;
# Replace {{tt|hamdata.ini}} in {{tt|/amxmodx/configs}} folder&lt;br /&gt;
# If you do scripting locally:&lt;br /&gt;
#* Replace all base includes and source files: any {{tt|.sma}} in {{tt|/amxmodx/scripting}} folder and {{tt|.inc}} in {{tt|/amxmodx/scripting/include}} folder&lt;br /&gt;
#* Replace the compiler and its binaries in {{tt|/amxmodx/scripting}} folder&lt;br /&gt;
#** [[File:Linux.svg|16px]] {{tt|amxxpc}} and {{tt|amxxpc32}}&lt;br /&gt;
#** [[File:Windows.svg|16px]] {{tt|amxxpc.exe}} and {{tt|amxxpc32.dll}}&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|If you are using ReGameDLL or ReHLDS, make sure you are using a recent version|opt=full-border}}&lt;br /&gt;
&lt;br /&gt;
==== New files ====&lt;br /&gt;
&lt;br /&gt;
* Copy {{tt|GeoLite2-Country.mmdb}} to the {{tt|/amxmodx/data}} folder (optionally, delete the old {{tt|GeoIP.dat}} file)&lt;br /&gt;
* Copy the whole {{tt|gamedata}} directory to the {{tt|/amxmodx/data}} folder&lt;br /&gt;
&lt;br /&gt;
==== Config changes ====&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | File&lt;br /&gt;
! style=&amp;quot;padding: 0.4em;&amp;quot; | Changes&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|amxx.cfg|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=amxxcfg|header=New cvars|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
// Server language in ISO 639-1 format&lt;br /&gt;
// Please see data/lang/languages.txt file for a list of supported languages&lt;br /&gt;
//&lt;br /&gt;
// Default value: en&lt;br /&gt;
amx_language &amp;quot;en&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// If you set this to 0, clients will not see a message about amx_langmenu when they join the server&lt;br /&gt;
//&lt;br /&gt;
// Default value: 1&lt;br /&gt;
amx_language_display_msg 1&lt;br /&gt;
&lt;br /&gt;
// Max temporary ban time (admins with ADMIN_BAN_TEMP access can't ban more than this time)&lt;br /&gt;
// time in minutes, 60 is 1 hour, 120 is 2 hours, 1440 is 1 day, and 10080 is 1 week&lt;br /&gt;
// Default value: 4320 aka 3 days&lt;br /&gt;
amx_tempban_maxtime 4320&lt;br /&gt;
&lt;br /&gt;
// Time to wait (in seconds) before displaying a message about amx_help to a client once joined the server&lt;br /&gt;
//&lt;br /&gt;
// Default value: 15&lt;br /&gt;
amx_help_display_msg_time 15&lt;br /&gt;
&lt;br /&gt;
// If you set this to 0, clients will not see a message about amx_help when they join the server&lt;br /&gt;
//&lt;br /&gt;
// Default value: 1&lt;br /&gt;
amx_help_display_msg 1&lt;br /&gt;
&lt;br /&gt;
// Amount of commands per amx_help page&lt;br /&gt;
//&lt;br /&gt;
// Default value: 10&lt;br /&gt;
amx_help_amount_per_page 10&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{alert|info|Note:|{{tt|amx_help_display_msg}} replaces the {{tt|DISPLAY_MSG}} define in {{tt|admin_help.sma}}.|opt=full-border}}&lt;br /&gt;
{{alert|info|Note:|{{tt|amx_help_amount_per_page}} replaces the {{tt|HELPAMOUNT}} define in {{tt|admin_help.sma}}.|opt=full-border}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{hidden|id=doccfg|header=Documentation adjusted|labelpos=left|content=&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Slay is now in the last position.&lt;br /&gt;
&amp;quot;0&amp;quot; slap damage to the default values was wrongly left out.&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
// Slay is automaticall inserted as the last option&lt;br /&gt;
// Default values: 0 1 5&lt;br /&gt;
amx_plmenu_slapdmg 0 1 5&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Missing values:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
// Show admins activity&lt;br /&gt;
// 0 - disabled&lt;br /&gt;
// 1 - show without admin name&lt;br /&gt;
// 2 - show with name&lt;br /&gt;
// 3 - show name only to admins, hide name from normal users&lt;br /&gt;
// 4 - show name only to admins, show nothing to normal users&lt;br /&gt;
// 5 - hide name only to admins, show nothing to normal users&lt;br /&gt;
//&lt;br /&gt;
// Default value: 2&lt;br /&gt;
amx_show_activity 2&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|core.ini|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=corecfg|header=One missing and one new option.|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
; Admin commnand flag manager&lt;br /&gt;
; 0 - enabled&lt;br /&gt;
; 1 - disabled&lt;br /&gt;
disableflagman 0&lt;br /&gt;
&lt;br /&gt;
; MySQL default timeout&lt;br /&gt;
mysql_timeout 60&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|sql.cfg|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=sqlcfg|header=New cvar|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
amx_sql_timeout &amp;quot;60&amp;quot;&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{tt|users.ini|bgcolor=white}}&lt;br /&gt;
| style=&amp;quot;padding: 0.4em;&amp;quot; | {{hidden|id=userscfg|header=New flag &amp;amp; documentation adjusted|labelpos=left|content=&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
; d - amx_ban and amx_unban commands (permanent and temporary bans)&lt;br /&gt;
; v - amx_ban and amx_unban commands (temporary bans only, about amx_unban, only self performed ban during map gonna be allowed)&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
== Overview for Admins ==&lt;br /&gt;
&lt;br /&gt;
=== Gamedata ===&lt;br /&gt;
&lt;br /&gt;
The AMX Mod X team has made an effort to avoid hard-coding game-specific data into AMXX core and modules. New ''gamedata'' files have been created which are located in the {{tt|amxmodx/data/gamedata/}} directory.&amp;lt;br /&amp;gt;&lt;br /&gt;
These files are now mandatory.&lt;br /&gt;
&lt;br /&gt;
Game data files shipped with AMX Mod X can and will be updated at any time, therefore it is strongly discouraged to edit them manually. &amp;lt;br 7&amp;gt;&lt;br /&gt;
To make custom gamedata changes, please use the {{tt|custom}} folder under the {{tt|gamedata}} directory. All files under this directory are parsed (in an undefined order) after the main files are loaded. They will never be overwritten.&lt;br /&gt;
&lt;br /&gt;
=== GeoIP ===&lt;br /&gt;
&lt;br /&gt;
The {{tt|GeoIP.dat}} file is now replaced by {{tt|GeoLite2-Country.mmdb}} file.&lt;br /&gt;
&lt;br /&gt;
As usual, a more detailed city version exists but is not provided in the default distribution. Plugins can require this version to operate.&lt;br /&gt;
&lt;br /&gt;
Both (Country: ~2 MB, City: ~30 MB) can be downloaded from the official page: https://dev.maxmind.com/geoip/geoip2/geolite2/ (MaxMind DB binary).&lt;br /&gt;
&lt;br /&gt;
=== Plugins ===&lt;br /&gt;
&lt;br /&gt;
Most plugins received large amounts of code improvements, modernizing and optimizing them using the latest AMXX core features.&lt;br /&gt;
This also includes a few security fixes.&lt;br /&gt;
&lt;br /&gt;
However, this does not (yet) translate into major user-facing features. We tried to improve internal tools before focusing on that.&lt;br /&gt;
&lt;br /&gt;
The features in this release are:&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''General'''}}&lt;br /&gt;
&lt;br /&gt;
* A new access level flag {{tt|v}} for temporary bans&lt;br /&gt;
* UTF-8 support in some MOTD&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Admin Commands'''}}&lt;br /&gt;
&lt;br /&gt;
* A new {{tt|amx_extendmap}} command to extend the time limit of the current map. Usage: {{tt|&amp;lt;nowiki&amp;gt;&amp;lt;time in minutes&amp;gt;&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
* A new {{tt|amx_xvar_int}} and {{tt|amx_xvar_float}} command&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Admin Chat'''}}&lt;br /&gt;
&lt;br /&gt;
* Cooldown on {{tt|say_team @]}} to avoid overflow on admins&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Admin Help'''}}&lt;br /&gt;
&lt;br /&gt;
* A new {{tt|amx_searchcmd}} command to display information about a command. Usage: {{tt|&amp;lt;match&amp;gt; &amp;lt;entry no.&amp;gt; [no. of entries to display (server only)]}}&lt;br /&gt;
* The hardcoded defines are replaced with {{tt|amx_help_display_msg}}, {{tt|amx_help_display_msg_time}} and {{tt|amx_help_amount_per_page}} cvars&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''CS Misc. Stats'''}}&lt;br /&gt;
&lt;br /&gt;
* A new {{tt|/msounds}} client command to enable/disable sounds&lt;br /&gt;
* A new option to disable showing last man's health&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Players Menu'''}}&lt;br /&gt;
&lt;br /&gt;
* A new Silent Transfer option&lt;br /&gt;
* A new {{tt|amx_language_display_msg}} cvar for previously hardcoded {{tt|DISPLAY_MSG}}&lt;br /&gt;
* Slay is now the last option in the Slay/Slap Menu&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Restrict Weapons'''}}&lt;br /&gt;
&lt;br /&gt;
* The {{tt|MAPSETTINGS}} define is replaced by {{tt|amx_restrmapsettings}} cvar&lt;br /&gt;
* No more hardcoded multilingual messages&lt;br /&gt;
* Admin activity is displayed on config loading/saving&lt;br /&gt;
* Opened menu is refereshed if the command is used to save/load/set&lt;br /&gt;
* Menu/command items are now grouped per class&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Stats X'''}}&lt;br /&gt;
&lt;br /&gt;
* Some translations are now player-specific.&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Teleport Menu'''}}&lt;br /&gt;
&lt;br /&gt;
* Possibility of being stuck should be reduced.&lt;br /&gt;
&lt;br /&gt;
=== Translations ===&lt;br /&gt;
&lt;br /&gt;
Along with fixes, improvements, and completion of existing translations, two new languages are provided:&lt;br /&gt;
* Russian&lt;br /&gt;
* Chinese&lt;br /&gt;
&lt;br /&gt;
== Overview for Developers ==&lt;br /&gt;
&lt;br /&gt;
=== General ===&lt;br /&gt;
&lt;br /&gt;
There are too many additions to list them here in details. For complete API changes and additions, see [[AMX_Mod_X_1.9_API_Changes]]. &amp;lt;br /&amp;gt;&lt;br /&gt;
It is strongly recommended to check out the changes, a lot of information is contained there.&lt;br /&gt;
&lt;br /&gt;
Essentially:&lt;br /&gt;
* Documentation has been updated in many ways.&lt;br /&gt;
* Compiler got a bunch of fixes and minor improvements/features.&lt;br /&gt;
* The API has been updated with various fixes and improvements.&lt;br /&gt;
* New module&lt;br /&gt;
* New core APIs&lt;br /&gt;
* Existing core APIs additions&lt;br /&gt;
* Existing module APIs additions&lt;br /&gt;
&lt;br /&gt;
== Changelog ==&lt;br /&gt;
&lt;br /&gt;
=== Internal ===&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Compilation'''}}&lt;br /&gt;
* Ported buildscripts to new AMBuild2 platform, https://github.com/alliedmodders/ambuild&lt;br /&gt;
* Removed MakeFile ({{pr|amxx|262}})&lt;br /&gt;
* Fixed GCC 4.8, Clang 3.9+ compilation ({{amb|273061}}, {{pr|amxx|458}})&lt;br /&gt;
* Built assembly files with AMBuild ({{pr|amxx|481}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Library'''}}&lt;br /&gt;
* Now using new AlliedModders Template Library (AMTL) in many places, https://github.com/alliedmodders/amtl  ({{pr|amxx|138}}, {{pr|amxx|260}}, {{pr|amxx|270}}, {{pr|amxx|296}}, {{pr|amxx|422}}, {{pr|amxx|436}})&lt;br /&gt;
* Added basic ReHLDS and ReGameDLL support ({{pr|amxx|417}}, {{pr|amxx|423}}, {{pr|amxx|425}}, {{pr|amxx|427}}, {{pr|amxx|446}}, {{pr|amxx|450}}, {{pr|amxx|483}}, {{pr|amxx|520}})&lt;br /&gt;
* Removed pre-compiled zlib from the tree ({{pr|amxx|117}}, {{pr|amxx|118}}, {{pr|amxx|527}})&lt;br /&gt;
* Unified zlib linkage by compiling it as a static library and linking it to concerned projects ({{pr|amxx|195}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Others'''}}&lt;br /&gt;
* Added license files for GPL2+/GPL3+, updated headers and {{TT|amxx gpl}} command ({{pr|amxx|102}}, {{pr|amxx|103}})&lt;br /&gt;
* Deduplicated a number of files used by modules by moving them to the public directory ({{pr|amxx|112}})&lt;br /&gt;
* Enabled C++11 support ({{pr|amxx|162}})&lt;br /&gt;
* Updated versioning system and added missing module RC file ({{pr|amxx|165}})&lt;br /&gt;
* Improved SELinux compatibility ({{pr|amxx|328}})&lt;br /&gt;
* Updated Visual Studio projects files ({{pr|amxx|109}}, {{pr|amxx|247}})&lt;br /&gt;
* Added Visual Studio 2015+ support ({{pr|amxx|179}}, {{pr|amxx|333}}, {{pr|amxx|397}})&lt;br /&gt;
* Added or adjusted a bunch of safety checks ({{pr|amxx|433}})&lt;br /&gt;
&lt;br /&gt;
=== Core ===&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Config'''}}&lt;br /&gt;
* Implemented a game config parser ({{pr|amxx|254}}, {{pr|amxx|258}}, {{pr|amxx|280}}, {{pr|amxx|282}}, {{pr|amxx|336}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Command'''}}&lt;br /&gt;
* Made registered server commands case-insensitive ({{bz|5625}})&lt;br /&gt;
* Extended {{tt|amxx list}} command to search with criteria ({{pr|amxx|377}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Menu'''}}&lt;br /&gt;
* Updated mods list supporting colored menus: DMC, TFC and Valve ({{pr|amxx|143}})&lt;br /&gt;
* Fixed unexpected behaviors when a game menu is overlapped with a custom one ({{bz|3199}})&lt;br /&gt;
* Fixed a crash with overlapping newmenu ({{pr|amxx|462}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Module API'''}}&lt;br /&gt;
* Added the following functions (see api changes) ({{pr|amxx|97}}, {{pr|amxx|254}}, {{pr|amxx|530}})&lt;br /&gt;
** {{tt|MF_SetAmxStringUTF8Char}}&lt;br /&gt;
** {{tt|MF_SetAmxStringUTF8Cell}}&lt;br /&gt;
** {{tt|MF_GetAmxStringNull}}&lt;br /&gt;
** {{tt|MF_GetAmxVectorNull}}&lt;br /&gt;
** {{tt|MF_GetConfigManager}}&lt;br /&gt;
** {{tt|MF_LoadAmxScriptEx}}&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed {{tt|OnPluginsUnloaded}} not being called for reloadable modules ({{pr|amxx|485}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Multilingual'''}}&lt;br /&gt;
* Improved method to check whether a multilingual file has been processed ({{pr|amxx|213}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed dictionary text files parser failing on BOM marking ({{bz|5858}})&lt;br /&gt;
* Fixed missing status reset on successful language key retrieval ({{bz|5994}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Native'''}}&lt;br /&gt;
* Increased {{tt|get_amxstring}} buffer size up to 16k ({{bz|5901}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed crash when dynamic native is executed with the max number of params ({{pr|amxx|291}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Others'''}}&lt;br /&gt;
* Added plugin version to debug trace information ({{bz|3649}})&lt;br /&gt;
* Removed KTrie dependency to Hash map ({{pr|amxx|8}}, {{pr|amxx|406}})&lt;br /&gt;
* Removed AMX Mod compatibility ({{pr|amxx|31}}, {{pr|amxx|461}})&lt;br /&gt;
* Removed useless natives: hcsardhnexsnu, is_user_hacking, is_rukia_a_hag, and amxx_setpl_curweap ({{pr|amxx|461}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed incorrect message error on plugin which uses a deprecated file format ({{pr|amxx|275}})&lt;br /&gt;
* Fixed spectator team index not being set in specific situations (Counter-strike only) ({{pr|amxx|15}})&lt;br /&gt;
* Fixed an unicode issue with {{tt|amx_SetStringOld}} ({{pr|amxx|22}}, {{pr|amxx|23}})&lt;br /&gt;
* Fixed log not written earlier at the first server start ({{pr|amxx|265}})&lt;br /&gt;
* Fixed a memory leak when registering a forward fails due to missing callback ({{pr|amxx|465}})&lt;br /&gt;
&lt;br /&gt;
=== User ===&lt;br /&gt;
&lt;br /&gt;
==== Translation ====&lt;br /&gt;
&lt;br /&gt;
* Added Chinese language ({{pr|amxx|75}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Updated Macedonian &amp;amp; Bulgarian translations ({{pr|amxx|477}})&lt;br /&gt;
* Updated Hungarian translations ({{pr|amxx|474}}, {{pr|amxx|494}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed incorrect keys in several multilingual files ({{pr|amxx|27}})&lt;br /&gt;
* Fixed missing translations for the following languages: de, cz, ro and sr ({{pr|amxx|27}})&lt;br /&gt;
* Fixed various translations ({{pr|amxx|67}})&lt;br /&gt;
&lt;br /&gt;
==== Plugin ====&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''General'''}}&lt;br /&gt;
&lt;br /&gt;
* Added a new access level flag {{tt|v}} for temporary bans ({{bz|3218}}, {{pr|amxx|440}})&lt;br /&gt;
* Added UTF-8 support in some MOTD ({{bz|5825}}, {{pr|amxx|135}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Removed AMX Mod compatibility ({{pr|amxx|28}})&lt;br /&gt;
* Removed leet speak translation ({{pr|amxx|83}})&lt;br /&gt;
* Removed some {{tt|client_cmd}} usage ({{pr|amxx|88}})&lt;br /&gt;
* Applied general optimizations ({{bz|5822}}, {{bz|5833}}, {{bz|5818}}, {{pr|amxx|9}}, {{pr|amxx|17}}, {{pr|amxx|78}}, {{pr|amxx|82}}, {{pr|amxx|88}}, {{pr|amxx|89}}, {{pr|amxx|90}}, {{pr|amxx|136}}, {{pr|amxx|139}}, {{pr|amxx|141}}, {{pr|amxx|190}}, {{pr|amxx|194}}, {{pr|amxx|214}}, {{pr|amxx|216}}, {{pr|amxx|227}}, {{pr|amxx|241}}, {{pr|amxx|256}}, {{pr|amxx|362}}, {{pr|amxx|424}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Admin Base'''}}&lt;br /&gt;
&lt;br /&gt;
* Directly kick players rather than use a loopback command ({{bz|5946}})&lt;br /&gt;
* Assigned {{tt|FCVAR_PROTECTED}} directly  in {{tt|register_cvar}} instead of after startup ({{pr|amxx|87}})&lt;br /&gt;
* Replaced {{tt|console_print}} with {{tt|engclient_print}} to support connecting players ({{pr|amxx|251}}, {{bz|6372}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed an issue when not including a port when an admin is added by IP address ({{bz|5978}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Admin Chat'''}}&lt;br /&gt;
&lt;br /&gt;
* Implemented cooldown on {{tt|say_team @]}} to prevent admin's client get overflowed if executed a couple of times ({{bz|5815}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed broken admin chat access consistency ({{bz|5822}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Admin Commands'''}}&lt;br /&gt;
&lt;br /&gt;
* Added {{tt|amx_extendmap}} command ({{bz|3068}})&lt;br /&gt;
* Added {{tt|amx_xvar}} command ({{bz|5896}})&lt;br /&gt;
* Added check for empty string in {{tt|amx_chat}} command ({{bz|6017}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Trimmed target in {{tt|amx_ban}} to prevent bypassing checks ({{pr|amxx|86}})&lt;br /&gt;
* Removed slowhack in {{tt|amx_nick}} command ({{bz|5832}})&lt;br /&gt;
* Sanitized {{tt|servercfgfile}} and {{tt|lservercfgfile}} values ({{bz|6578}}&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed {{amx_slap}} unexpected behavior using large negative damage ({{bz|4975}})&lt;br /&gt;
* Fixed a permission scalability bug in the following commands: ({{bz|6578}}, {{pr|amxx|441}})&lt;br /&gt;
** {{tt|amx_addban}}&lt;br /&gt;
** {{tt|amx_exec}}&lt;br /&gt;
** {{tt|amx_cvar}}&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Admin Help'''}}&lt;br /&gt;
&lt;br /&gt;
* Added {{tt|amx_searchcmd}} command ({{pr|amxx|415}}, {{pr|amxx|456}})&lt;br /&gt;
* Replaced hardcoded defines with {{tt|amx_help_display_msg}}, {{tt|amx_help_display_msg_time}} and {{tt|amx_help_amount_per_page}} cvars ({{pr|amxx|84}}, {{pr|amxx|415}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''CS Misc. Stats'''}}&lt;br /&gt;
&lt;br /&gt;
* Added {{tt|/msounds}} client command to enable/disable sounds ({{bz|5846}})&lt;br /&gt;
* Added an option to disable showing last man's health ({{bz|5847}}, {{pr|amxx|122}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed missing stats sounds, sounds precaching and few bugs ({{bz|5810}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Map Menu Plugin'''}}&lt;br /&gt;
&lt;br /&gt;
* Fixed possible buffer overflows ({{pr|amxx|91}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Multi-Lingula System'''}}&lt;br /&gt;
&lt;br /&gt;
* Moved {{tt|amx_language}} cvar to core ({{pr|amxx|82}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''NextMap'''}}&lt;br /&gt;
&lt;br /&gt;
* Fixed last map not properly saving resulting mapcycle reset at mapchange ({{bz|5817}})&lt;br /&gt;
* Fixed an in-game issue where {{tt|mp_chattime}} cvar doesn't exist ({{bz|5922}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Nextmap Chooser'''}}&lt;br /&gt;
&lt;br /&gt;
* Fixed possible buffer overflows ({{pr|amxx|91}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Players Menu'''}}&lt;br /&gt;
&lt;br /&gt;
* Added Silent Transfer Option ({{pr|amxx|113}}, {{pr|amxx|161}})&lt;br /&gt;
* Added {{tt|amx_language_display_msg}} cvar for previously hardcoded {{tt|DISPLAY_MSG}} ({{pr|amxx|82}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Moved slay as last option instead of first in Slay/Slap Menu ({{bz|5861}})&lt;br /&gt;
* Removed vault usage, {{tt|amx_setlang}} and server language from the menu in favor of {{tt|amx_language}} ({{pr|amxx|82}})&lt;br /&gt;
* Used server language as fallback if client's &amp;quot;lang&amp;quot; key is not defined ({{pr|amxx|106}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed player transfer issues ({{bz|5850}})&lt;br /&gt;
* Fixed incorrect language key ({{pr|amxx|32}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Plugin Menu'''}}&lt;br /&gt;
&lt;br /&gt;
* Fixed unreachable code warning ({{pr|amxx|131}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Restrict Weapons'''}}&lt;br /&gt;
&lt;br /&gt;
* Overhauled the plugin ({{pr|amxx|347}})&lt;br /&gt;
** Applied general optimization and small QoL changes&lt;br /&gt;
** Moved {{tt|MAPSETTINGS}} define to cvar {{tt|amx_restrmapsettings}}&lt;br /&gt;
** Made hardcoded messages multilingual&lt;br /&gt;
** Displayed admin activity on config loading/saving&lt;br /&gt;
** Refreshed opened menus if the command is used to save/load/set&lt;br /&gt;
** Grouped visually menu/command items per class&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Stats X'''}}&lt;br /&gt;
&lt;br /&gt;
* Moved formatting from {{tt|LANG_SERVER}} to player-specific translations where possible ({{pr|amxx|9}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''TimeLeft'''}}&lt;br /&gt;
&lt;br /&gt;
* Fixed possible out of bound error ({{bz|5818}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Teleport Menu'''}}&lt;br /&gt;
&lt;br /&gt;
* Improved precision to reduce the possibility of being stuck after teleportation ({{pr|amxx|17}})&lt;br /&gt;
&lt;br /&gt;
=== Developer ===&lt;br /&gt;
&lt;br /&gt;
==== General ====&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''New Modules'''}}&lt;br /&gt;
&lt;br /&gt;
* Introduced a JSON module ({{pr|amxx|379}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Engine'''}}&lt;br /&gt;
* Fixed some natives relying on a known engine bug related to last player's edict being invalid ({{bz|6429}}, {{pr|297}}, {{pr|299}}, {{pr|306}})&lt;br /&gt;
:{|&lt;br /&gt;
| {{tt|emit_sound}}&lt;br /&gt;
| Last player wasn't hearing the sound.&lt;br /&gt;
|-&lt;br /&gt;
| {{tt|e/message_begin}}, {{tt|dod_weaponlist}}&lt;br /&gt;
| Was leading to a crash because engine doesn't like {{tt|MSG_ONE_*}} with null entity.&lt;br /&gt;
|-&lt;br /&gt;
| {{tt|TFC_[Clear/Set]Model}}&lt;br /&gt;
| Was leading to a crash because of null edict.&lt;br /&gt;
|-&lt;br /&gt;
| {{tt|set_tr/2}}&lt;br /&gt;
| Was not working when used with {{tt|TR_pHit}}&lt;br /&gt;
|-&lt;br /&gt;
| {{tt|pev}}&lt;br /&gt;
| Was returning 0 used with {{tt|pev_edict}}&lt;br /&gt;
|-&lt;br /&gt;
| {{tt|pev_valid}}&lt;br /&gt;
| Was returning 0.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Miscellaneous'''}}&lt;br /&gt;
&lt;br /&gt;
* Added {{tt|DMG_GRENADE}} constant (CS Only) ({{bz|6030}})&lt;br /&gt;
* Added missing {{tt|SVC_}} messages ({{pr|amxx|223}})&lt;br /&gt;
** {{tt|SVC_RESOURCELOCATION}}&lt;br /&gt;
** {{tt|SVC_SENDCVARVALUE}}&lt;br /&gt;
** {{tt|SVC_SENDCVARVALUE2}}&lt;br /&gt;
* Added new xs stocks ({{pr|amxx|426}})&lt;br /&gt;
** {{tt|xs_vec_len_2d}}&lt;br /&gt;
** {{tt|xs_vec_distance}}&lt;br /&gt;
** {{tt|xs_vec_distance_2d}}&lt;br /&gt;
** {{tt|xs_vec_add_scaled}}&lt;br /&gt;
** {{tt|xs_vec_sub_scaled}}&lt;br /&gt;
* Added {{tt|STATSX_*}}, {{tt|DODX_*}} and {{tt|MAX_BODYHITS}} constants for client statistics ({{pr|amxx|509}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Allowed {{tt|arrayset}} to accept any type ({{pr|amxx|516}})&lt;br /&gt;
* Allowed {{tt|ExecuteForward}} without need to create variable for returned value ({{pr|amxx|382}})&lt;br /&gt;
* Enforced {{tt|any:}} tag in several natives header for convenience ({{pr|amxx|166}}, {{pr|amxx|222}},  {{pr|amxx|499}})&lt;br /&gt;
* Moved string constants and stocks in their own {{tt|string_const.inc}} and {{tt|string_stocks.inc}} includes {{pr|amxx|407}}&lt;br /&gt;
&lt;br /&gt;
==== Core ====&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''New APIs'''}}&lt;br /&gt;
* Introduced Automatic Config File API ({{pr|amxx|266}}, {{pr|amxx|289}}, {{pr|amxx|496}})&lt;br /&gt;
* Introduced DataPacks API ({{bz|5885}}, {{pr|amxx|231}}, {{pr|amxx|261}}, {{pr|419}})&lt;br /&gt;
* Introduced Game Config Parser API ({{pr|amxx|254}})&lt;br /&gt;
* Introduced Hasher API ({{pr|amxx|206}}, {{pr|amxx|384}})&lt;br /&gt;
* Introduced Stack structures API ({{pr|amxx|94}})&lt;br /&gt;
* Introduced TextParser API ({{pr|amxx|101}}, {{pr|amxx|272}}, {{pr|amxx|344}}, {{bz|6228}}, {{bz|6476}})&lt;br /&gt;
* Introduced Trie Iterator API ({{pr|amxx|413}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Cellarray'''}}&lt;br /&gt;
* Added {{tt|ArraySortEx}}/{{tt|SortADTArray}} natives and new {{tt|Sort_Random}} sort method ({{bz|5494}}, {{pr|amxx|279}})&lt;br /&gt;
* Added the following new CellArray natives: {{tt|ArrayClone}}, {{tt|ArrayResize}}, {{tt|ArrayFindString}} and {{tt|ArrayFindValue}} ({{bz|6104}}, {{pr|107}}, {{pr|amxx|408}})&lt;br /&gt;
* Added {{tt|size}} parameter to {{tt|ArrayGetArray}}, {{tt|ArraySetArray}} and {{tt|ArrayPushArray}} to control the number of elements to use ({{pr|76}}, {{pr|111}})&lt;br /&gt;
* Added {{tt|block}} parameter to {{tt|ArrayGetCell}} and {{tt|ArraySetCell}} to specify which block ({{pr|amxx|76}}, {{pr|amxx|111}})&lt;br /&gt;
* Added {{tt|achar}} parameter to {{tt|ArrayGetCell}} and {{tt|ArraySetCell}} value as a byte ({{pr|amxx|76}}, {{pr|amxx|111}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed an overflow issue with {{tt|ArrayInsertBefore}} and {{tt|ArrayInsertAfter}} ({{bz|4330}})&lt;br /&gt;
* Fixed {{tt|ArrayDestroy}} erroring on invalid handle ({{pr|amxx|210}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''CellTrie'''}}&lt;br /&gt;
* Added {{tt|TrieGetSize}} and {{tt|TrieSnapshot*}} natives ({{pr|amxx|8}})&lt;br /&gt;
* Added new {{tt|replace}} parameters for {{tt|TrieSet*}} natives to make the operation fail if key already set ({{pr|amxx|8}})&lt;br /&gt;
* Added new {{tt|size}} parameter for {{tt|TrieGetString}} and {{tt|TrieGetArray}} to return the number of bytes written in the buffer ({{pr|amxx|8}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Client'''}}&lt;br /&gt;
* Added {{tt|client_disconnected}} forward to fix player not being internally disconnected in some situation ({{pr|amxx|264}}, {{pr|amxx|304}}, {{pr|amxx|334}})&lt;br /&gt;
* Added {{tt|client_remove}} forward (post version of {{tt|client_disconnected}} {{pr|amxx|414}}&lt;br /&gt;
* Added {{tt|client_connectex}} forward to allow to reject player’s attempt to join ({{pr|amxx|322}})&lt;br /&gt;
* Added {{tt|flag}} parameter to {{tt|user_silentkill}} ({{pr|amxx|323}})&lt;br /&gt;
* Added {{tt|find_player_ex}} native, a wrapper of {{tt|find_player}} using flags as strings ({{pr|amxx|389}})&lt;br /&gt;
* Added {{tt|get_players_ex}} stock, a wrapper of {{tt|get_players}} using flags as strings ({{pr|amxx|389}})&lt;br /&gt;
* Added {{tt|get_playersnum_ex}} native to retrieve directly the player's count using flags as strings ({{pr|amxx|517}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Extended {{tt|client_authorized}} to pass steam ID ({{pr|amxx|322}})&lt;br /&gt;
* Set {{tt|set_user_rendering}} default color/amount to 0 to follow game behavior ({{bz|5772}})&lt;br /&gt;
* Allowed the following natives to be used on connecting players: {{tt|find_player}}, {{tt|get_players}} and {{tt|engclient_print}} (console only) ({{bz|6229}}, {{pr|amxx|126}})&lt;br /&gt;
* Made the {{tt|body}} param in {{tt|get_user_aiming}} optional ({{pr|amxx|532}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed {{tt|user_slap}} unexpected behavior when using large negative damage ({{bz|4975}})&lt;br /&gt;
* Fixed missing new line on client console message which is not truncated server-side if its length exceeds buffer size ({{bz|3140}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Cvar/Command'''}}&lt;br /&gt;
* Introduced several natives for cvars management ({{pr|amxx|185}},  {{pr|amxx|202}}, {{pr|amxx|203}},  {{pr|amxx|211}},  {{pr|amxx|230}}, {{pr|amxx|318}}, {{pr|amxx|337}}, {{pr|amxx|453}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Added {{tt|amxclient_cmd}} native ({{bz|5887}}, {{pr|amxx|438}}, {{pr|amxx|518}})&lt;br /&gt;
* Added {{tt|read_argv_int}} and {{tt|read_argv_float}} to return the value directly as integer or float ({{pr|amxx|366}}, {{pr|amxx|383}})&lt;br /&gt;
* Added a param to {{tt|register_*cmd}} and {{tt|get_*cmd}} to specify {{tt|info}} is a multilingual key in order to encourage command translation ({{pr|amxx|349}}, {{pr|amxx|434}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed a {{tt|engclient_cmd}} buffer issue ({{pr|amxx|438}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Event'''}}&lt;br /&gt;
* Added new {{tt|register_event}} flags to filter humans and bots ({{bz|5768}})&lt;br /&gt;
* Added {{tt|register_event_ex}} native, a wrapper of {{tt|register_event}} using flags as strings ({{pr|amxx|389}})&lt;br /&gt;
* Added {{tt|enable/disable_event}} natives ({{bz|6360}}, {{pr|amxx|267}})&lt;br /&gt;
* Added {{tt|enable/disable_logevent}} natives ({{pr|amxx|326}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed reentrancy issue when a generated message is sent during {{tt|register_event}} forward ({{bz|3664}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''File'''}}&lt;br /&gt;
* Added support for Valve FS to natives that use file handles ({{pr|amxx|217}}, {{pr|amxx|235}}, {{pr|amxx|467}})&lt;br /&gt;
* Added {{tt|SetFilePermissions}} native&lt;br /&gt;
* Added {{tt|FileReadInt8}}, {{tt|FileReadUint8}}, {{tt|FileReadInt16}}, {{tt|FileReadUint16}} and {{tt|FileReadInt32}} natives&lt;br /&gt;
* Added {{tt|FileWriteInt8}}, {{tt|FileWriteInt16}} and {{tt|FileWriteInt32}} natives&lt;br /&gt;
* Added {{tt|GetFileTime}} native returning a file timestamp as a unix timestamp ({{bz|4543}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Menu'''}}&lt;br /&gt;
* Added menu timeout functionality to Newmenu API ({{pr|amxx|21}}) TODO: link to script changes?&lt;br /&gt;
* Added {{tt|MEXIT_FORCE}} to force a proper exit button on unpaginated menus ({{pr|amxx|20}})&lt;br /&gt;
* Added {{tt|MPROP_SHOWPAGE}} to set whether or not to show the page number in menu title ({{pr|amxx|473}})&lt;br /&gt;
* Added {{tt| menu_addblank2}} and {{tt|menu_addtext2}} to fix unexpected behavior with the original ones when {{tt|slot}} param is set to 1 ({{bz|3096}})&lt;br /&gt;
* Added menu pagination callback ({{pr|amxx|420}})&lt;br /&gt;
* Add default values for {{tt|menu_item_getinfo}}'s arguments ({{pr|amxx|511}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Allowed {{tt|show_menu}} native to send empty text + added {{tt|reset_menu}} stock ({{bz|6244}}, {{pr|amxx|150}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed recursion issues with {{tt|show_menu}} and newmenus ({{pr|amxx|140}}, {{pr|amxx|335}})&lt;br /&gt;
* Fixed a potential underflow bug which can occur when a non-paginated menu has no items in it ({{pr|amxx|20}})&lt;br /&gt;
* Fixed a potential menu handle leak when {{tt|show_menu}} is used after a newmenu was opened ({{pr|amxx|21}})&lt;br /&gt;
* Fixed {{tt|MPROP_NOCOLORS}} menu property not working ({{pr|amxx|283}})&lt;br /&gt;
* Fixed missing format param on error in {{tt|next_hudchannel}} native ({{pr|amxx|391}})&lt;br /&gt;
* Fixed a menu recursion issue ({{pr|amxx|471}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''Message'''}}&lt;br /&gt;
* Added {{tt|e/write_/coord/angle/_f}} and {{tt|e/message_begin_f}} natives ({{bz|5829}})&lt;br /&gt;
* Added {{tt|client_print_color}} native (Counter-Strike only) ({{bz|5823}}, {{pr|amxx|338}}, {{pr|amxx|504}})&lt;br /&gt;
* Added {{tt|set/show_dhudmessage}} which uses a different kind of message HUD (hint) ({{bz|5979}})&lt;br /&gt;
* Added {{tt|client_printex}} stock ({{bz|5828}}, {{pr|amxx|10}})&lt;br /&gt;
* Added {{tt|MSG_INIT}} support in {{tt|message_begin}} native ({{bz|6254}}, {{pr|amxx|151}})&lt;br /&gt;
* Added {{tt|elog_message}} native ({{pr|amxx|451}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Set {{tt|set_hudmessage}} default channel to -1 to reflect auto-channeling support ({{bz|5771}})&lt;br /&gt;
&lt;br /&gt;
{{color|dimgrey|'''String'''}}&lt;br /&gt;
* Added {{tt|strtol}} native ({{bz|3233}})&lt;br /&gt;
* Added {{tt|strtof}} native ({{bz|5909}})&lt;br /&gt;
* Added {{tt|strtok2}} which fixes a trim issue with {{tt|strtok}} ({{bz|3993}})&lt;br /&gt;
* Added new string-related stocks ({{bz|6110}}, {{pr|amxx|327}})&lt;br /&gt;
* Added new string-related natives ({{bz|6110}})&lt;br /&gt;
* Added {{tt|fmt}} native to format and return a string inline ({{pr|amxx|350}})&lt;br /&gt;
* Added support for binary format {{tt|%b}} ({{bz|6110}})&lt;br /&gt;
* Added special format specifiers {{tt|%n}} and {{tt|%N}} ({{pr|amxx|93}})&lt;br /&gt;
* Added support for {{tt|%l}} format specifier ({{bz|6361}}, {{pr|amxx|229}}, {{pr|amxx|313}}, {{pr|amxx|320}}, {{pr|amxx|331}}, {{pr|amxx|343}})&lt;br /&gt;
* Added {{tt|SetGlobalTransTarget}} to globally set the player’s language, for use with {{tt|%l}} format specifier ({{pr|amxx|229}})&lt;br /&gt;
* Added text formatting ability to {{tt|set_fail_state}} ({{bz|5800}})&lt;br /&gt;
* Added some UTF-8 compatible natives ({{pr|amxx|407}})&lt;br /&gt;
** {{tt|mb_strotolower}}&lt;br /&gt;
** {{tt|mb_strtoupper}}&lt;br /&gt;
** {{tt|mb_ucfirst}}&lt;br /&gt;
** {{tt|mb_strtotitle }}&lt;br /&gt;
** {{tt|is_string_category}}&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Made formatting-capable function UTF-8 safe (including precision with %s e.g. %.12s) ({{bz|6110}})&lt;br /&gt;
* Made a bunch of stocks/natives UTF-8 safe ({{bz|6110}}, {{pr|amxx|159}})&lt;br /&gt;
* Improved UTF-8 support in some natives ({{pr|amxx|407}}, {{pr|amxx|459}})&lt;br /&gt;
** {{tt|containi}}&lt;br /&gt;
** {{tt|strfind}} (with ignorecase set)&lt;br /&gt;
** {{tt|strcmp}} (with ignorecase set)&lt;br /&gt;
** {{tt|strncmp}} (with ignorecase set)&lt;br /&gt;
** {{tt|equali}}&lt;br /&gt;
** {{tt|replace_string}} (with ignorecase set)&lt;br /&gt;
** {{tt|replace_stringex}} (with ignorecase set)&lt;br /&gt;
** {{tt|get_players}} (with name and ignorecase flags set)&lt;br /&gt;
** {{tt|find_player}} (with name and ignorecase flags set)&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed UTF-8 character parsing due to improper casting ({{pr|amxx|401}})&lt;br /&gt;
* Fixed {{tt|strncmp}} case sensitivity ({{pr|amxx|314}})&lt;br /&gt;
* Fixed a {{tt|floatround}} overflow on large numbers resulting in a negative number when optimization is enabled ({{pr|amxx|376}})&lt;br /&gt;
&lt;br /&gt;
{{color|brown|'''Others'''}}&lt;br /&gt;
&lt;br /&gt;
* Added {{tt|GetModelBoundingBox}} native ({{bz|3527}}, {{pr|amxx|536}})&lt;br /&gt;
* Added {{tt|has_map_ent_class}} native ({{bz|5814}})&lt;br /&gt;
* Added {{tt|engine_changelevel}} ({{pr|amxx|104}}, {{pr|amxx|184}}, {{pr|amxx|503}})&lt;br /&gt;
* Added {{tt|FP_VAL_BYREF}} to pass values by reference in forwards ({{pr|amxx|369}})&lt;br /&gt;
* Added {{tt|RequestFrame}} native ({{pr|amxx|412}})&lt;br /&gt;
* Added {{tt|set_task_ex}} stock, a wrapper of {{tt|set_task}} using flags as strings ({{pr|amxx|389}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Added {{tt|get_user_rendering}} native ({{pr|amxx|514}})&lt;br /&gt;
* Hidden blank line in abort native with {{tt|AMX_ERR_NONE}} ({{bz|6233}}, {{pr|amxx|125}})&lt;br /&gt;
* Improved {{tt|power}} native on large number ({{pr|amxx|385}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed definite time drift on repeating tasks ({{bz|3302}})&lt;br /&gt;
* Fixed a potential issue in {{tt|get_plugin}} ({{pr|amxx|277}})&lt;br /&gt;
* Fixed a crash when a dynamic native is executed with the max number of params ({{pr|amxx|291}})&lt;br /&gt;
&lt;br /&gt;
=== Compiler ===&lt;br /&gt;
&lt;br /&gt;
* Added support for Emscripten to the compiler ({{pr|amxx|115}})&lt;br /&gt;
* Added the following globals ({{pr|amxx|116}})&lt;br /&gt;
** {{TT|__BINARY_PATH__}}&lt;br /&gt;
** {{TT|__BINARY_FILE__}}&lt;br /&gt;
** {{TT|__LINE__}}&lt;br /&gt;
* Added {{TT|&amp;lt;nowiki&amp;gt;#pragma deprecated&amp;lt;/nowiki&amp;gt;}} ({{pr|amxx|116}}, {{pr|amxx|307}})&lt;br /&gt;
* Added a flag {{TT|-E}} to consider all warnings as errors ({{pr|amxx|137}})&lt;br /&gt;
* Added string literal concatenation and stringizing operator ({{pr|amxx|173}})&lt;br /&gt;
* Added ability to directly reference another address in a default argument (for arrays only) ({{pr|amxx|248}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Removed AMX Mod compatibility ({{pr|amxx|31}})&lt;br /&gt;
* Increased variable and functions maximum name length from {{tt|31}} to {{tt|63}} characters ({{bz|5924}})&lt;br /&gt;
* Increased input line length from {{tt|511}} to {{tt|4095}} characters ({{pr|amxx|116}})&lt;br /&gt;
* Ignored {{TT|&amp;lt;nowiki&amp;gt;#pragma tabsize&amp;lt;/nowiki&amp;gt;}} with non-positive argument ({{pr|amxx|116}})&lt;br /&gt;
* Improved {{TT|sizeof}} return on array without specifying the dimensions ({{pr|amxx|116}}, {{pr|amxx|158}})&lt;br /&gt;
* Improved the reported line number accuracy on warning 203/4 (symbol never used) ({{pr|amxx|116}})&lt;br /&gt;
* Used in-memory buffers for reading files, and handling newline better ({{pr|amxx|116}})&lt;br /&gt;
* Used hash table for global name lookups ({{pr|amxx|116}})&lt;br /&gt;
* Disabled the estimated usage calculation because it doesn’t work well and is not that useful ({{pr|amxx|137}})&lt;br /&gt;
* Removed scpack ({{pr|amxx|221}}, {{pr|amxx|226}})&lt;br /&gt;
* Prevented declaring arrays that the compiler is too buggy to handle ({{pr|amxx|248}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed returning strings from variadic functions ({{pr|amxx|121}}, {{pr|amxx|399}})&lt;br /&gt;
* Fixed issue with multidimensional array variable release ({{pr|amxx|116}})&lt;br /&gt;
* Fixed memory corruption when parsing natives ({{pr|amxx|116}})&lt;br /&gt;
* Fixed improper handling of constant chained relational operators, i.e: {{TT|&amp;lt;nowiki&amp;gt;0 &amp;lt; 1 &amp;lt;= 2&amp;lt;/nowiki&amp;gt;}} ({{pr|amxx|116}})&lt;br /&gt;
* Fixed bogus assert about name lengths ({{pr|amxx|116}})&lt;br /&gt;
* Fixed asserting when returning a string literal ({{pr|amxx|116}})&lt;br /&gt;
* Fixed return omission with else-after-return ({{pr|amxx|116}})&lt;br /&gt;
* Fixed crash when using {{TT|tagof(tagname:)}} ({{pr|amxx|116}})&lt;br /&gt;
* Fixed the {{TT|@}} character not being allowed in macro definitions ({{pr|amxx|116}})&lt;br /&gt;
* Fixed {{TT|&amp;lt;nowiki&amp;gt;#elseif&amp;lt;/nowiki&amp;gt;}} handling not working as expected ({{pr|amxx|116}})&lt;br /&gt;
* Fixed {{TT|enum}} field size was not taken into account when implicitly passed to a function ({{pr|amxx|116}})&lt;br /&gt;
* Fixed trailing commas in array literals changing the result of {{TT|sizeof}} ({{pr|amxx|163}})&lt;br /&gt;
* Fixed regression with member tag of {{TT|enum}} is not being checked on assignment ({{pr|amxx|164}})&lt;br /&gt;
* Fixed {{TT|tagof}} operator used as a default value for function arguments ({{pr|amxx|191}})&lt;br /&gt;
* Fixed issue where native functions returning an array would not compile ({{pr|amxx|351}})&lt;br /&gt;
* Fixed compilation error for GCC 6 ({{pr|amxx|372}})&lt;br /&gt;
* Fixed compilation for Clang 3.5+ ({{pr|amxx|177}}, {{pr|amxx|361}})&lt;br /&gt;
* Fixed inc/dec operators not returning an iEXPRESSION ({{pr|amxx|429}})&lt;br /&gt;
&lt;br /&gt;
=== Modules ===&lt;br /&gt;
&lt;br /&gt;
==== CStrike ====&lt;br /&gt;
&lt;br /&gt;
* Added {{tt|CS_OnBuy}} forward, called right before an item is received ({{pr|amxx|25}}, {{pr|amxx|68}}, {{pr|amxx|124}}, {{pr|amxx|183}},  {{pr|amxx|263}}, {{pr|amxx|315}}, {{pr|amxx|340}}, {{pr|amxx|334}})&lt;br /&gt;
* Added {{tt|CS_OnBuyAttempt}} forward, called right after a command is issued ({{pr|amxx|68}}, {{pr|amxx|263}}, {{pr|amxx|334}})&lt;br /&gt;
* Added {{tt|cs_create_entity}} native ({{pr|amxx|189}}, {{pr|amxx|193}})&lt;br /&gt;
* Added {{tt|cs_find_ent_by_class}} native ({{pr|amxx|189}}, {{pr|amxx|193}})&lt;br /&gt;
* Added {{tt|cs_find_ent_by_owner}} ({{pr|amxx|278}})&lt;br /&gt;
* Added {{tt|cs_set_ent_class native}} ({{pr|amxx|332}}, {{pr|amxx|519}})&lt;br /&gt;
* Added {{tt|cs_get_user_weapon_entity}} and {{tt|cs_get_user_weapon}} natives ({{pr|amxx|330}}, {{pr|amxx|353}})&lt;br /&gt;
* Added {{tt|cs_get_weapon_class}} and {{tt|cs_is_valid_itemid}} stocks for convenience ({{pr|amxx|278}})&lt;br /&gt;
* Added {{tt|cs_get_item_id}} native to get a {{tt|CSI_}} value from a given alias, {{tt|weapon_}} or {{tt|item_}}  ({{pr|amxx|278}}, {{pr|amxx|342}})&lt;br /&gt;
* Added {{tt|cs_get_translated_item_alias}} native to get an item name (classname) from a given alias ({{pr|amxx|278}}, {{pr|amxx|356}})&lt;br /&gt;
* Added {{tt|cs_get_item_alias}} ({{pr|amxx|342}})&lt;br /&gt;
* Added {{tt|cs_get_weapon_info}} native which gives various information about a weapon (only) ({{pr|amxx|278}}, {{pr|amxx|356}})&lt;br /&gt;
* Added {{tt|cs_get_weaponbox_item}} native ({{pr|amxx|548}})&lt;br /&gt;
* Added a param to {{tt|cs_set_user_deaths}} native to choose whether the scoreboard should be updated ({{pr|amxx|255}})&lt;br /&gt;
* Added support for {{tt|monster_scientist}} entity (alias of {{tt|hostage_entity}}) to hostage natives  ({{pr|amxx|255}})&lt;br /&gt;
* Added a {{tt|count}} param to {{tt|cs_get/set_armoury_type}} to get/set the number of weapons inside an armoury ({{pr|amxx|255}})&lt;br /&gt;
* Added a {{tt|update_index}} param in {{tt|cs_set_user_model}} to choose whether the model index should be updated ({{pr|amxx|255}}, {{pr|amxx|300}}, {{pr|amxx|370}})&lt;br /&gt;
* Added a {{tt|CS_NORESET}} constant for use with {{tt|cs_set_user_team}} for skipping the model reset ({{pr|amxx|287}}, {{pr|amxx|400}})&lt;br /&gt;
* Added a new value for {{tt|draw_animation}} in {{tt|cs_set_weapon_silen}} which follows game behavior ({{pr|amxx|255}})&lt;br /&gt;
* Added the associated {{tt|TRAIN_*}} constants from HLSDK for use with {{tt|cs_get_user_driving}} ({{pr|amxx|255}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Moved all hardcoded data to its own gamedata files ({{pr|amxx|255}}, {{pr|amxx|352}}, {{pr|amxx|356}})&lt;br /&gt;
* Done some cleanup for the sake of consistency and readability ({{pr|amxx|255}})&lt;br /&gt;
* Added some known constants from CS, a {{tt|cstrike_const.inc}} has been created for the occasion ({{pr|amxx|278}})&lt;br /&gt;
* Cached {{tt|GET_USER_MSG_ID}} calls ({{pr|amxx|255}})&lt;br /&gt;
* Improved {{tt|cs_set_no_knives}} internal code by hooking {{tt|pfnCreateNamedEntity}} only when necessary ({{pr|amxx|255}})&lt;br /&gt;
* Made {{tt|cs_get_user_armor}} {{tt|armortype}} param optional ({{pr|amxx|255}})&lt;br /&gt;
* Improved {{tt|cs_set_user_zoom}} by using an event-based approach rather than enforcing on-frame basis when {{tt|mode}} is 0 ({{pr|amxx|255}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed {{tt|cs_user_spawn}} to properly respawn players ({{bz|3752}})&lt;br /&gt;
* Fixed {{tt|cs_set_user_team}} not telling core spectator team change ({{pr|amxx|13}})&lt;br /&gt;
* Fixed {{tt|cs_get_hostage_id}} error check: a hostage can't be a player ({{pr|amxx|255}})&lt;br /&gt;
* Fixed {{tt|cs_set_user_[model/team]}} and {{tt|cs_reset_user_[model/team]}} overflow issue by staggering user's info updates across multiple frames ({{pr|amxx|255}})&lt;br /&gt;
* Fixed missing meta return in {{tt|ServerActivate}} ({{pr|amxx|308}})&lt;br /&gt;
&lt;br /&gt;
==== CSX ====&lt;br /&gt;
&lt;br /&gt;
* Added {{tt|get_map_objectives}} native ({{bz|5820}}, {{pr|amxx|149}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Modified {{tt|csstats_rank}} value to match {{tt|amxx.cfg}} default value ({{pr|amxx|170}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed {{tt|client_death/damage}} forwards passing alive victims on {{tt|ClientKill}} ({{bz|5812}})&lt;br /&gt;
* Fixed {{tt|client_death}} forward called on {{tt|kill}} command if sent by a spectator ({{pr|amxx|404}})&lt;br /&gt;
&lt;br /&gt;
==== DoDX ====&lt;br /&gt;
&lt;br /&gt;
* Fixed grenade_throw incorrect calling behavior and wrong returned weapon IDs ({{bz|5785}})&lt;br /&gt;
* Fixed a potential crash ({{pr|amxx|277}})&lt;br /&gt;
&lt;br /&gt;
==== DoDFun ====&lt;br /&gt;
&lt;br /&gt;
* Fixed a potential issue  ({{pr|amxx|277}})&lt;br /&gt;
&lt;br /&gt;
==== Engine ====&lt;br /&gt;
&lt;br /&gt;
* Added {{tt|client_cmdStart}} forward ({{bz|5779}})&lt;br /&gt;
* Added {{tt|set_ent_rendering}} native ({{bz|5773}})&lt;br /&gt;
* Added {{tt|entity_intersects}} native ({{bz|6172}}, {{pr|amxx|70}}, {{pr|amxx|367}})&lt;br /&gt;
* Added {{tt|unregister_touch/think/impulse}} ({{pr|amxx|250}})&lt;br /&gt;
* Added safe {{tt|get_global_edict2}} and {{tt|entity_get_edict2}} ({{pr|amxx|250}}, {{pr|amxx|367}})&lt;br /&gt;
* Added a destination parameter to {{tt|trace_hull}} to make it useful using {{tt|NULL_VECTOR}} ({{pr|amxx|250}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Improved {{tt|set_lights}} internal working, only hook server frame when {{tt|pfnLightStyle}} has been called ({{pr|amxx|250}})&lt;br /&gt;
* Moved {{tt|precache_event}} to core ({{pr|amxx|250}}, {{pr|amxx|490}})&lt;br /&gt;
* Removed inconsistent error path from {{tt|entity_get_int}} ({{pr|amxx|250}})&lt;br /&gt;
* Added error path for {{tt|remove_entity}} and unsafe entity ids ({{pr|amxx|250}})&lt;br /&gt;
* Added a bunch of missing entity checks ({{pr|amxx|250}}, {{pr|amxx|345}}, {{pr|amxx|346}}, {{pr|amxx|355}})&lt;br /&gt;
* Used UTF-8 functions where {{tt|KeyValueData}} is touched ({{pr|amxx|250}})&lt;br /&gt;
* Allowed {{tt|find_ent_by_owner}} native to work in {{tt|client_disconnect}} forward ({{pr|amxx|152}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed a crash when using {{tt|get/set_usercmd}} ({{bz|5744}})&lt;br /&gt;
* Fixed {{tt|set_view}} altering {{tt|pev}} properties instead of {{tt|entity_state}} for rendering players ({{bz|5382}})&lt;br /&gt;
* Fixed incorrect behavior of impulse forwards ({{bz|3243}})&lt;br /&gt;
* Fixed {{tt|pfn_spawn}} metamod return to follow engine behavior ({{bz|5807}})&lt;br /&gt;
* Fixed {{tt|set_ent_rendering}} not working on non-player entities ({{pr|amxx|71}})&lt;br /&gt;
* Fixed {{tt|get_info_keybuffer}} not being able to retrieve local key buffer ({{pr|amxx|250}})&lt;br /&gt;
* Fixed an entity check logic error ({{pr|amxx|250}}, {{pr|amxx|259}})&lt;br /&gt;
* Fixed {{tt|is_visible}} native not working on players ({{pr|amxx|392}})&lt;br /&gt;
* Fixed a {{tt|set_lights}} buffer issue which was resulting in an incorrect light ({{pr|amxx|464}}, {{pr|amxx|508}})&lt;br /&gt;
&lt;br /&gt;
==== Fakemeta ====&lt;br /&gt;
&lt;br /&gt;
* Added {{tt|create_kvd}} and {{tt|free_kvd}} allowing creation of new KVD structures that can be used with Hamsandwich.&lt;br /&gt;
* Added new {{tt|get}}/{{tt|set_pdata_*}} natives for the following types: {{tt|bool}}, {{tt|byte}}, {{tt|short}}, {{tt|vector}}, {{tt|ehandle}} and {{tt|ent}} ({{bz|5770}})&lt;br /&gt;
* Introduced new natives to read/write on entity's private data based off class/member name using gamedata files ({{pr|amxx|284}})&lt;br /&gt;
** {{tt|get}}/{{tt|set_ent_data}}&lt;br /&gt;
** {{tt|get}}/{{tt|set_ent_data_float}}&lt;br /&gt;
** {{tt|get}}/{{tt|set_ent_data_vector}}&lt;br /&gt;
** {{tt|get}}/{{tt|set_ent_data_entity}}&lt;br /&gt;
** {{tt|get}}/{{tt|set_ent_data_string}}&lt;br /&gt;
** {{tt|get_ent_data_size}}&lt;br /&gt;
** {{tt|find_ent_data_info}}&lt;br /&gt;
** {{tt|get_field_basetype}}&lt;br /&gt;
* Introduced natives to read/write on the gamerules object ({{pr|amxx|298}}, {{pr|amxx|309}}, {{pr|amxx|316}})&lt;br /&gt;
** {{tt|get}}/{{tt|set_gamerules_int}}&lt;br /&gt;
** {{tt|get}}/{{tt|set_gamerulesa_float}}&lt;br /&gt;
** {{tt|get}}/{{tt|set_gamerules_vector}}&lt;br /&gt;
** {{tt|get}}/{{tt|set_gamerules_entity}}&lt;br /&gt;
** {{tt|get}}/{{tt|set_gamerules_string}}&lt;br /&gt;
** {{tt|get_gamerules_size}}&lt;br /&gt;
** {{tt|find_gamerules_info}}&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Allowed {{tt|get/set_pdata_cbase}} usage at map end whereas player's private data is still valid ({{bz|5787}})&lt;br /&gt;
* Improved handling of {{tt|KeyValueData}} and made it compatible with Hamsandwich ({{pr|amxx|240}})&lt;br /&gt;
* Allowed null invoker to be passed in {{tt|EngFunc_PlayBackEvent}} ({{pr|amxx|358}}, {{bz|6467}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed {{tt|pev_blending}} not working with set_pev ({{bz|5758}})&lt;br /&gt;
* Fixed broken {{tt|EngFunc_ChangeLevel}} ({{pr|amxx|244}})&lt;br /&gt;
* Fixed a bug with recursive pre hooks ({{pr|amxx|341}})&lt;br /&gt;
* Fixed memory leak in {{tt|unregister_forward}} ({{pr|amxx|388}})&lt;br /&gt;
&lt;br /&gt;
==== Fun ====&lt;br /&gt;
&lt;br /&gt;
* Internal changes: ({{pr|amxx|421}})&lt;br /&gt;
** Made {{tt|pfnTraceLine}} a post forward to avoid breaking plugins hooking this forward as well (e.g. {{tt|FM_TraceLine}}). Related to {{tt|set_user_hitzones}} native.&lt;br /&gt;
** {{tt|pfnTraceLine}} and {{tt|pfnPlayerPreThink}} used by {{tt|set_user_hitzones}} and {{tt|set_user_footsteps}} are now toggled on-demand.&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Added {{tt|HITZONE_*}} constants for use with {{tt|get_user_hitzones}} and {{tt|set_user_hitzones}} ({{pr|amxx|421}})&lt;br /&gt;
&lt;br /&gt;
==== GeoIP ====&lt;br /&gt;
&lt;br /&gt;
* Module now uses the latest MaxMind GeoIP2 API ({{pr|amxx|99}}, {{pr|amxx|104}}, {{pr|amxx|132}})&lt;br /&gt;
* Added new (UTF-8 safe) {{tt|geoip_*}} natives to retrieve the city, region, continent and more ({{pr|amxx|99}}, {{pr|amxx|198}}, {{pr|amxx|200}})&lt;br /&gt;
* Added a {{tt|geoip}} command mainly for debugging purposes (version, dump an ip data) ({{pr|amxx|99}})&lt;br /&gt;
* Marked {{tt|geoip_country}} as deprecated in favor of the new {{tt|geoip_country_ex}} native ({{pr|amxx|99}})&lt;br /&gt;
&lt;br /&gt;
==== Hamsandwich ====&lt;br /&gt;
&lt;br /&gt;
* Added support for the following mods:&lt;br /&gt;
** Deathmatch Classic&lt;br /&gt;
** Adrenaline Gamer&lt;br /&gt;
** Opposing Forces&lt;br /&gt;
** Sven Coop v5.17&lt;br /&gt;
* Added several functions which required different handlers&lt;br /&gt;
* Added a lot of missing virtual functions for all mods&lt;br /&gt;
* Added natives to deal with the {{tt|ItemInfo}} structure&lt;br /&gt;
* Added support for bots without {{tt|player}} classname ({{bz|6111}}, {{bz|6323}}, {{pr|amxx|153}}, {{pr|amxx|228}})&lt;br /&gt;
* Added {{tt|SetParamEntity2}} native to fix entity param not changing in post hook ({{pr|amxx|395}}, {{pr|amxx|463}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Updated offsets for all mods ({{pr|amxx|354}})&lt;br /&gt;
* Aligned stack on 16 byte boundary in hamsandwich trampolines ({{pr|amxx|24}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed crash for functions returning a vector&lt;br /&gt;
* Fixed crash when {{tt|Ham_TakeHealth}} is called&lt;br /&gt;
* Fixed various typos&lt;br /&gt;
* Fixed misaligned offsets in {{tt|hamdata.ini}}&lt;br /&gt;
* Fixed vtable patching on Linux for newer GCC binaries&lt;br /&gt;
* Fixed resource leak when reading {{tt|hamdata.ini}} ({{pr|amxx|274}})&lt;br /&gt;
* Fixed {{tt|ham hooks}} command not displaying all current hooks of a plugin ({{pr|amxx|276}})&lt;br /&gt;
* Fixed {{tt|HAM_OVERRIDE}} in post hooks ({{bz|6443}}, {{pr|amxx|317}})&lt;br /&gt;
* Fixed a buffer issue in {{tt|RegisterHam}} ({{pr|amxx|495}})&lt;br /&gt;
&lt;br /&gt;
==== MySQL ====&lt;br /&gt;
&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Added {{tt|SQL_SetCharset}} native to (re)set character set ({{bz|5999}})&lt;br /&gt;
* Added MySQL Reconnect feature ({{pr|amxx|154}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Bumped MySQL version to 5.5 ({{pr|amxx|466}}, {{pr|amxx|468}})&lt;br /&gt;
* Established a default timeout for MySQL connectivity ({{pr|amxx|188}})&lt;br /&gt;
* Improved module threading to be more responsive ({{pr|amxx|207}})&lt;br /&gt;
&lt;br /&gt;
==== NVault ====&lt;br /&gt;
&lt;br /&gt;
* Fixed a potential crash at map change if an empty key or value is saved ({{pr|amxx|112}}, {{pr|amxx|130}})&lt;br /&gt;
* Fixed potential formatting issue with {{tt|nvault_[p]set}} ({{pr|amxx|187}})&lt;br /&gt;
&lt;br /&gt;
==== NS ====&lt;br /&gt;
&lt;br /&gt;
* Fixed {{tt|ns_remove_upgrade}} native ({{bz|3394}}, {{pr|amxx|271}})&lt;br /&gt;
&lt;br /&gt;
==== RegEx ====&lt;br /&gt;
&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Added {{tt|regex_compile_ex}}, mainly to allow direct use of {{tt|PCRE_*}} flags ({{pr|amxx|69}})&lt;br /&gt;
* Added {{tt|regex_match_all_c}} and {{tt|regex_match_all}} to retrieve all matches ({{pr|amxx|69}})&lt;br /&gt;
* Added {{tt|regex_replace}} to search and replace ({{pr|amxx|69}})&lt;br /&gt;
* Added {{tt|regex_match_simple}} stock ({{pr|amxx|69}}, {{pr|amxx|156}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Updated {{texttip|PCRE|Perl Compatible Regular Expressions}} to {{tt|v8.35|bgcolor=none}} with UTF-8 support ({{pr|amxx|69}})&lt;br /&gt;
* Updated {{tt|regex_subtr}} to increase static buffer size same as core and to make it UTF-8 safe ({{pr|amxx|69}})&lt;br /&gt;
&lt;br /&gt;
==== SQLite ====&lt;br /&gt;
&lt;br /&gt;
* Added {{tt|SQL_SetCharset}} native to (re)set character set ({{bz|5999}}, {{pr|amxx|236}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Updated library version from {{tt|3.3.13|bgcolor=none}} to {{tt|3.24.0|bgcolor=none}} ({{pr|amxx|148}}, {{pr|amxx|527}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Fixed missing ''queuetime'' {{tt|FP_CELL}} parameter in {{tt|SQL_ThreadQuery}} callback ({{pr|amxx|205}})&lt;br /&gt;
* Fixed missing buffer size check to {{tt|QuoteString}} implementation ({{pr|amxx|411}})&lt;br /&gt;
&lt;br /&gt;
==== Socket ====&lt;br /&gt;
&lt;br /&gt;
* Added a new {{tt|_flags}} parameter to allow non-blocking mode and return libc error ({{pr|amxx|301}})&lt;br /&gt;
* Added {{tt|socket_is_writable}} native to check whether a socket is ready to write  ({{pr|amxx|301}})&lt;br /&gt;
* Added {{tt|socket_is_readable}} as an alias to {{tt|socket_change}} ({{pr|amxx|301}})&lt;br /&gt;
{{margin|10px|}}&lt;br /&gt;
* Updated WinSock version from {{tt|1.1}} to {{tt|2.2}} ({{pr|amxx|301}})&lt;br /&gt;
* Properly checked for WinSock initialization on {{tt|OnAmxxAttach}}/{{tt|Detach}} ({{pr|amxx|301}})&lt;br /&gt;
* Ignored natives registration if WinSock can't be started ({{pr|amxx|301}})&lt;br /&gt;
* Made {{tt|socket_open}} IP version agnostic (both IPv4 and IPv6 are supported) ({{pr|amxx|301}})&lt;br /&gt;
* Made {{tt|socket_close}} to return a value on success/failure ({{pr|amxx|301}})&lt;br /&gt;
&lt;br /&gt;
==== NVault ====&lt;br /&gt;
&lt;br /&gt;
* Fixed server crash when nvault is writing to journal file without write permission ({{bz|3231}})&lt;br /&gt;
&lt;br /&gt;
==== TFCX ====&lt;br /&gt;
&lt;br /&gt;
* Fixed {{tt|tfcstats_rankbots}} not working as expected when disabled ({{bz|3192}})&lt;br /&gt;
* Fixed {{tt|tfcstats_pause}} imcomplete implementation ({{bz|5836}})&lt;br /&gt;
* Fixed {{tt|tfc_setbammo}} not working under Linux ({{bz|5845}})&lt;br /&gt;
* Fixed {{tt|TFC_PC_CIVILIAN}} value ({{bz|6042}})&lt;br /&gt;
* Fixed crash when Infection weapon is used ({{pr|amxx|232}}, {{bz|6333}})&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation (AMX Mod X)]]&lt;/div&gt;</summary>
		<author><name>Shooting King</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Managing_your_Sourcemod_installation/zh&amp;diff=11237</id>
		<title>Managing your Sourcemod installation/zh</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Managing_your_Sourcemod_installation/zh&amp;diff=11237"/>
		<updated>2021-09-28T22:39:51Z</updated>

		<summary type="html">&lt;p&gt;Shooting King: Using proper table header&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== 入门 ==&lt;br /&gt;
=== 服务器控制台 ===&lt;br /&gt;
你刚刚[[Installing_SourceMod/zh|安装了sourcemod]]并保证它正常运行。为此你执行了[[Installing_SourceMod#Checking_the_Install|Checking the Install]]章节中的指令并且在服务器控制台中第一次尝试了命令。&lt;br /&gt;
&lt;br /&gt;
要熟悉控制台，可以直接用服务器控制台或者rcon指令。(例如使用[http://www.hlsw.org/ HLSW]).&lt;br /&gt;
&lt;br /&gt;
至少尝试以下指令&lt;br /&gt;
* sm&lt;br /&gt;
* sm version&lt;br /&gt;
* sm plugins&lt;br /&gt;
* sm plugins list&lt;br /&gt;
* sm plugins reload 1&lt;br /&gt;
* sm plugins refresh&lt;br /&gt;
* sm plugins unload funvotes&lt;br /&gt;
* sm plugins load funvotes&lt;br /&gt;
* sm exts list&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 文件结构 ===&lt;br /&gt;
你也要熟悉sourcemod的文件结构，这意味着&lt;br /&gt;
Also get to know the directory layout sourcemod is using, this means:&lt;br /&gt;
# 看看有哪些文件夹&lt;br /&gt;
# 文件夹中有什么文件&lt;br /&gt;
# 文件中有什么&amp;lt;span style=&amp;quot;font-size:80%&amp;quot;&amp;gt;(使用记事本打开 (推荐: notepad++[https://notepad-plus-plus.org] 或者其他第三方编辑器)).&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;width:600px;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
 !文件夹&lt;br /&gt;
 !描述&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/bin'''&lt;br /&gt;
 | 忽略这个文件夹，这里面是sourcemod的二进制文件&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/configs'''&lt;br /&gt;
 | 这是sourcemod和插件默认放置配置文件的地方。&lt;br /&gt;
查看里面所有文件至少一次，尝试去理解它们&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/data'''&lt;br /&gt;
 | 暂时忽略这个文件夹&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/extensions'''&lt;br /&gt;
 | 这是拓展安装的位置。你可能注意到了许多拓展出现了多次，这是因为不同的游戏引擎需要基于他们SDK的独特的拓展。&lt;br /&gt;
拿bintools举例：&lt;br /&gt;
{| style=&amp;quot;width:450px;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
 |- class=&amp;quot;t1td&amp;quot;&lt;br /&gt;
 | '''bintools.ext.dll'''&lt;br /&gt;
 | 这是原版的source引擎拓展&lt;br /&gt;
 |- class=&amp;quot;t1td&amp;quot;&lt;br /&gt;
 | '''bintools.ext.1.ep1.dll'''&lt;br /&gt;
 | &amp;quot;老版Metamod&amp;quot; (Insurgency，Eternal Silence和其他EP1的mods)&lt;br /&gt;
 |- class=&amp;quot;t1td&amp;quot;&lt;br /&gt;
 | '''bintools.ext.2.darkm.dll'''&lt;br /&gt;
 | 这是Dark Messiah的拓展&lt;br /&gt;
 |- class=&amp;quot;t1td&amp;quot;&lt;br /&gt;
 | '''bintools.ext.2.ep2.dll'''&lt;br /&gt;
 | 这是&amp;quot;OrangeBox&amp;quot;引擎下的ZPS, AOC, PVKII之类的拓展&lt;br /&gt;
 |- class=&amp;quot;t1td&amp;quot;&lt;br /&gt;
 | '''bintools.ext.2.ep2v.dll'''&lt;br /&gt;
 | 这是&amp;quot;OrangeBoxValve&amp;quot;引擎下的CSS,TF2,DODS,HL2DM,GMOD之类的拓展&lt;br /&gt;
 |- class=&amp;quot;t1td&amp;quot;&lt;br /&gt;
 | '''bintools.ext.2.l4d.dll'''&lt;br /&gt;
 | 这是L4D的拓展&lt;br /&gt;
 |- class=&amp;quot;t1td&amp;quot;&lt;br /&gt;
 | '''bintools.ext.2.l4d2.dll'''&lt;br /&gt;
 | 这是L4D2的拓展&lt;br /&gt;
 |- class=&amp;quot;t1td&amp;quot;&lt;br /&gt;
 | '''bintools.ext.2.swarm.dll'''&lt;br /&gt;
 | 这是Alien Swarm的拓展&lt;br /&gt;
|}&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/gamedata'''&lt;br /&gt;
 | 有拓展或者插件使用了游戏引擎提供的功能。例如，如果要重生玩家或者给玩家装备武器，sourcemod需要知道一些函数的前提条件（具体地，偏移和签名这些参数）。这些数据每次更新都会改变，你目前不需要知道更多信息，因为sourcemod有内置的更新其，它会自动的从新的游戏数据文件夹中获取这些数据。&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/logs'''&lt;br /&gt;
 | debug的神器。一切都被记录在这里。如果有人问你日志文件在说什么，或者你遇到了任何错误：复现你的问题，然后看看日志文件然后复制粘贴这些信息。如果你不了解错误原因，发给相关人士处理。&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/plugins'''&lt;br /&gt;
 | 所有插件（.smx文件）都会在sourcemod启动时自动加载。当地图更改时如果文件发生了改变，也会重新加载。&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/plugins/disabled'''&lt;br /&gt;
 | 在这个子文件夹中的插件不会被加载。如果你想要禁用一个插件，就把它从父文件夹中剪切进去。反之亦然。你会发现这个文件夹中有一些你可能想安装的官方插件（例如，rtv换图插件）。&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/scripting'''&lt;br /&gt;
 | 你能看到一些插件的源码。安装插件并不需要放置任何文件在这里，但是我们强烈推荐不要仅仅安装smx文件，最好也带上相应的sp文件。&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/translations'''&lt;br /&gt;
 | 无需多言，这里有许多语言的翻译。我们鼓励插件提供翻译文件，所有你安装插件时也许需要拷贝一些文件到这。&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 将自己设为管理员 ===&lt;br /&gt;
为了便于管理，你应该把自己设为root管理员。&lt;br /&gt;
有许多方法来获取服务器权限。这里我们用最简单暴力的方式，但你可能需要查看[[Zh_cn:Adding_Admins_(SourceMod)|增加管理员]] and [[Adding_Groups_(SourceMod)|增加组]]，然后创建一组系统管理员并设置自己的权限。&lt;br /&gt;
&lt;br /&gt;
我们使用最简单的方式，只需要在&amp;lt;tt&amp;gt;sourcemod/configs/&amp;lt;/tt&amp;gt;文件夹下的&amp;lt;tt&amp;gt;admins_simple.cfg&amp;lt;/tt&amp;gt;文件中加一行：&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;quot;你的steamid&amp;quot; &amp;quot;99:z&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
然后在服务器控制台输入'''sm_reloadadmins'''，你会收到以下回复&amp;lt;tt&amp;gt;[SM] Admin cache has been refreshed.&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 尝试启用/禁用插件 ===&lt;br /&gt;
如果你看了上面的内容，你应该已经知道如何做了。&lt;br /&gt;
&lt;br /&gt;
如果你看了关于服务器控制台的内容，你也知道了如何测试它了。&lt;br /&gt;
&lt;br /&gt;
但让我们再解释一次，我们想要启用mapchooser（选择地图）插件:&lt;br /&gt;
# 复制 &amp;lt;tt&amp;gt;plugins/disabled/mapchooser.smx&amp;lt;/tt&amp;gt; 到 &amp;lt;tt&amp;gt;plugins/mapchooser.smx&amp;lt;/tt&amp;gt;&lt;br /&gt;
# 你可以使用&amp;lt;tt&amp;gt;sm plugins load mapchooser&amp;lt;/tt&amp;gt;&amp;lt;br&amp;gt; 或者换图来启用。&lt;br /&gt;
# 输入&amp;lt;tt&amp;gt;sm plugins list&amp;lt;/tt&amp;gt;来看看当前启用的插件。&lt;br /&gt;
&lt;br /&gt;
如果失败了，查看 [[#怎样检查你的插件是否安装好了|怎样检查sourcemod插件的安装]]?&lt;br /&gt;
&lt;br /&gt;
== 安装插件 ==&lt;br /&gt;
=== 基础 ===&lt;br /&gt;
对于一些只有源码和二进制文件的插件，例如[http://forums.alliedmods.net/showthread.php?t=74531 Basic AFK Manager]，安装起来十分直接，并且基本和启用官方插件一样。(参考[[#尝试启用/禁用插件|1.4]]). 你复制&amp;lt;tt&amp;gt;.smx&amp;lt;/tt&amp;gt; 文件去 &amp;lt;tt&amp;gt;plugins&amp;lt;/tt&amp;gt;文件夹， &amp;lt;tt&amp;gt;.sp&amp;lt;/tt&amp;gt;文件去&amp;lt;tt&amp;gt;scripting&amp;lt;/tt&amp;gt;文件夹。&lt;br /&gt;
&lt;br /&gt;
对于一些复杂的插件，例如[http://forums.alliedmods.net/showthread.php?t=59147 SM Bot Tools],可能需要赋值翻译或者游戏数据到相应的文件夹。但是聪明的开发者会给你一个完美的压缩文件，所有的文件都放在了对应的文件夹中，你只需要将所有东西直接复制到sourcemod文件夹。&lt;br /&gt;
'''插件自己的说明永远是第一位的'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 依赖 ===&lt;br /&gt;
有一部分插件依赖于其他插件，但是很多插件依赖于一个或多个拓展。拓展通常提供了一些能让插件做更多事情的特性。如果一个插件有依赖项，肯定会在描述页提及，这就需要你自己去找了。&lt;br /&gt;
&lt;br /&gt;
在第三章[[#安装拓展|如何安装拓展]]中学习如何安装拓展。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 怎样检查你的插件是否安装好了 ===&lt;br /&gt;
当你遇到了插件或者拓展的问题，永远用服务器客户端来解决，不需要管客户端控制台的事情，SourceMod是一个服务器端的插件。&lt;br /&gt;
&lt;br /&gt;
只需要在安装后换图，然后再服务器控制台输入&amp;lt;tt&amp;gt;sm plugins list&amp;lt;/tt&amp;gt;。你应该看到了改变。如果你安装的插件没有被列出来，这意味着插件没有被正确地安装。（这意味着这不是插件的错，而是你的错），并且你需要想清楚什么地方做错了。一般而言，你没有把编译后的插件(the &amp;lt;tt&amp;gt;.smx&amp;lt;/tt&amp;gt; 文件)放在sourcemod下的&amp;lt;tt&amp;gt;/plugins&amp;lt;/tt&amp;gt;文件夹中。&lt;br /&gt;
&lt;br /&gt;
如果插件被列了出来，但是有&amp;lt;tt&amp;gt;&amp;lt;Failed&amp;gt;&amp;lt;/tt&amp;gt;前缀，那就是发生了其他错误。为了获取问题的类型，输入&amp;lt;tt&amp;gt;sm plugins info &amp;lt;plugin id&amp;gt;&amp;lt;/tt&amp;gt;, replace &amp;lt;tt&amp;gt;&amp;lt;plugin id&amp;gt;&amp;lt;/tt&amp;gt;加上列表中问题插件的名字。你可能会看到&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;width:600px;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; width=&amp;quot;80&amp;quot; | &lt;br /&gt;
! scope=&amp;quot;col&amp;quot; width=&amp;quot;180&amp;quot; |&lt;br /&gt;
 |- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
 |错误 || 描述&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''Could not find translation file'''&lt;br /&gt;
 | 你没有把翻译文件放到正确的位置。请再一次检查插件页的内容，再一次检查提供的压缩文件。如果真的缺失了翻译文件，报告给开发者，否则自行放置到相应的文件夹。&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''Native 'xyz' was not found'''&amp;lt;br&amp;gt;或者&amp;lt;br&amp;gt;'''Required extension &amp;quot;xyz&amp;quot; file(&amp;quot;xyz.ext&amp;quot;) not running.'''&lt;br /&gt;
 | 你安装了旧版本的拓展，或者没有安装需要的拓展。检查你的拓展版本（输入sm exts list）并更新它。&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''Wrong game'''&lt;br /&gt;
 | 你用的是其他游戏的插件。停用这个插件。&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 帮助开发者 ===&lt;br /&gt;
如果你竭尽所能，依然无法让插件正常工作，那是相当不正常的事情。插件开发者会认为你没有正常安装这个插件并给你这个页面的链接。'''请避免这样的事情发生''' 给他们充分的证据证明你已经到了无法独自处理问题的地步.告诉他们你已经试过了，并给他控制台的日志文件（如果你无法复制粘贴，也可以给截图）和一切有关信息。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 安装拓展 ==&lt;br /&gt;
=== 基础 ===&lt;br /&gt;
拓展和插件类似，但是更加有力。在有插件需要的情况下才会被启用。这意味着，一个拓展如果没有被任何插件依赖，你输入&amp;lt;tt&amp;gt;sm exts list&amp;lt;/tt&amp;gt;后看不到它。&lt;br /&gt;
&lt;br /&gt;
一些拓展给其他插件提供了功能(例‘’'如[http://forums.alliedmods.net/showthread.php?t=106748 SDKHooks])，一些拓展直接影响游戏本身。(例如[http://forums.alliedmods.net/showthread.php?t=145218 UnlockBlock]).&lt;br /&gt;
&lt;br /&gt;
=== 拓展名和版本 ===&lt;br /&gt;
一些拓展只有一个版本。它们的文件名类似&amp;lt;tt&amp;gt;bintools.ext.dll&amp;lt;/tt&amp;gt; for Windows, &amp;lt;tt&amp;gt;bintools.ext.so&amp;lt;/tt&amp;gt; for Linux, or &amp;lt;tt&amp;gt;bintools.ext.dylib&amp;lt;/tt&amp;gt; for OSX.&lt;br /&gt;
&lt;br /&gt;
另一些拓展基于不同的引擎有多个版本。它们的文件名通常像&amp;lt;tt&amp;gt;[extension name].ext.[MetaMod: Source API version].[Game engine string].[extension]&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
例如，SDKTools在Windows SourceMod中有以下文件&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! 游戏 !! 文件名&lt;br /&gt;
|-&lt;br /&gt;
| Alien Swarm || &amp;lt;tt&amp;gt;sdktools.ext.2.swarm.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Bloody Good Time || &amp;lt;tt&amp;gt;sdktools.ext.2.bgt.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Dark Messiah || &amp;lt;tt&amp;gt;sdktools.ext.2.darkm.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Episode 1 / Generic non-OB mods || &amp;lt;tt&amp;gt;sdktools.ext.1.ep1.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Episode 2 / Orange Box / Source 2007 / Generic OB mods || &amp;lt;tt&amp;gt;sdktools.ext.2.ep2.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| E.Y.E: Divine Cybermancy || &amp;lt;tt&amp;gt;sdktools.ext.2.eye.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead || &amp;lt;tt&amp;gt;sdktools.ext.2.l4d.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead 2 || &amp;lt;tt&amp;gt;sdktools.ext.2.l4d2.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Source 2009 / Half-Life 2: DeathMatch / Day of Defeat: Source / Counter-Strike: Source / Team Fortress 2 || &amp;lt;tt&amp;gt;sdktools.ext.2.ep2v.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== 安装一个拓展 ===&lt;br /&gt;
这和安装插件很像，所以没必要再说一遍，但我还是做了😂。&lt;br /&gt;
安装拓展你只需要复制到&amp;lt;tt&amp;gt;/extensions&amp;lt;/tt&amp;gt;文件夹。&lt;br /&gt;
'''拓展也可能需要翻译文件和游戏数据，不要遗漏了它们'''&lt;br /&gt;
&lt;br /&gt;
要自动加载拓展，只需要换图或者输入&amp;lt;tt&amp;gt;sm exts load &amp;lt;name of your extension&amp;gt;&amp;lt;/tt&amp;gt;。谨记，没有被依赖的拓展是不会被自动加载的。&lt;br /&gt;
&lt;br /&gt;
强制加载拓展只需要创建一个空文件，名字为拓展名加上&amp;lt;tt&amp;gt;.autoload&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* 例如:&lt;br /&gt;
** 拓展名是&amp;lt;tt&amp;gt;extensions/sdkhooks.ext.2.ep2v.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
** 空文件为&amp;lt;tt&amp;gt;extensions/sdkhooks.autoload&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''注意：''' 你不能更新一个正在运行的拓展，你需要首先通过&amp;lt;tt&amp;gt;sm unload &amp;lt;拓展名&amp;gt;&amp;lt;/tt&amp;gt;停用拓展或关闭服务器。否则，你的Linux服务器很容易崩溃，你的Windows服务器则禁止你这样操作。&lt;br /&gt;
&lt;br /&gt;
=== 处理拓展问题 ===&lt;br /&gt;
和你之前学到的方式类似。&lt;br /&gt;
&lt;br /&gt;
如何查看拓展是否加载了，或者加载失败了? sm exts list&lt;br /&gt;
如何在运行时加载拓展? sm exts load &amp;lt;extension name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
以上都会告诉你 '''为什么''' 失败了。这和[[#怎样检查你的插件是否安装好了|怎样检查你的插件是否安装好了]]章节类似，请确保你看了里面的内容。&lt;br /&gt;
至少它会告诉你如何继续。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Documentation]]&lt;/div&gt;</summary>
		<author><name>Shooting King</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Managing_your_Sourcemod_installation&amp;diff=11236</id>
		<title>Managing your Sourcemod installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Managing_your_Sourcemod_installation&amp;diff=11236"/>
		<updated>2021-09-28T22:37:45Z</updated>

		<summary type="html">&lt;p&gt;Shooting King: Using proper table header&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Languages|Managing your Sourcemod installation}}&lt;br /&gt;
== Getting Familiar ==&lt;br /&gt;
=== Server console ===&lt;br /&gt;
You've just [[Installing_SourceMod|installed sourcemod]] and made sure that it's working. For that you did the instructions in the [[Installing_SourceMod#Checking_the_Install|Checking the Install]] chapter and issued some first commands in the server console.&lt;br /&gt;
&lt;br /&gt;
Get more familiar with the console, either directly or preferably via rcon (e.g. by using [http://www.hlsw.org/ HLSW]).&lt;br /&gt;
&lt;br /&gt;
Try at least these commands:&lt;br /&gt;
* sm&lt;br /&gt;
* sm version&lt;br /&gt;
* sm plugins&lt;br /&gt;
* sm plugins list&lt;br /&gt;
* sm plugins reload 1&lt;br /&gt;
* sm plugins refresh&lt;br /&gt;
* sm plugins unload funvotes&lt;br /&gt;
* sm plugins load funvotes&lt;br /&gt;
* sm exts list&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Directory Layout ===&lt;br /&gt;
Also get to know the directory layout sourcemod is using, this means:&lt;br /&gt;
# look and see what folders are there&lt;br /&gt;
# what files are in them&lt;br /&gt;
# and what's in those files &amp;lt;span style=&amp;quot;font-size:80%&amp;quot;&amp;gt;(open them with notepad (better: notepad++ or some other custom text editor)).&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;width:600px;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
 !Directory&lt;br /&gt;
 !Description&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/bin'''&lt;br /&gt;
 | ignore this folder, it has the actual sourcemod binaries in it&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/configs'''&lt;br /&gt;
 | This is the default place where sourcemod and its plugins put their configuration files.&lt;br /&gt;
Look at every file in this folder at least once, try to understand them.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/data'''&lt;br /&gt;
 | ignore this folder for now&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/extensions'''&lt;br /&gt;
 | This is the directory where extensions must be installed. You might notice that many extensions exist multiple times, this is due to the fact that the different game engines each need their own extension based on their SDK.&lt;br /&gt;
Lets take a look at the bintools extension for example:&lt;br /&gt;
{| style=&amp;quot;width:450px;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
 |- class=&amp;quot;t1td&amp;quot;&lt;br /&gt;
 | '''bintools.ext.dll'''&lt;br /&gt;
 | This is for the original source engine&lt;br /&gt;
 |- class=&amp;quot;t1td&amp;quot;&lt;br /&gt;
 | '''bintools.ext.1.ep1.dll'''&lt;br /&gt;
 | &amp;quot;Old Metamod&amp;quot; (Insurgency, Eternal Silence and other EP1 mods)&lt;br /&gt;
 |- class=&amp;quot;t1td&amp;quot;&lt;br /&gt;
 | '''bintools.ext.2.darkm.dll'''&lt;br /&gt;
 | This is for Dark Messiah.&lt;br /&gt;
 |- class=&amp;quot;t1td&amp;quot;&lt;br /&gt;
 | '''bintools.ext.2.ep2.dll'''&lt;br /&gt;
 | This is for the &amp;quot;OrangeBox&amp;quot;-Engine used by mods, e.g. ZPS, AOC, PVKII etc&lt;br /&gt;
 |- class=&amp;quot;t1td&amp;quot;&lt;br /&gt;
 | '''bintools.ext.2.ep2v.dll'''&lt;br /&gt;
 | This is for the &amp;quot;OrangeBoxValve&amp;quot;-Engine e.g. CSS,TF2,DODS,HL2DM,GMOD.&lt;br /&gt;
 |- class=&amp;quot;t1td&amp;quot;&lt;br /&gt;
 | '''bintools.ext.2.l4d.dll'''&lt;br /&gt;
 | This is for L4D&lt;br /&gt;
 |- class=&amp;quot;t1td&amp;quot;&lt;br /&gt;
 | '''bintools.ext.2.l4d2.dll'''&lt;br /&gt;
 | This is for L4D2&lt;br /&gt;
 |- class=&amp;quot;t1td&amp;quot;&lt;br /&gt;
 | '''bintools.ext.2.swarm.dll'''&lt;br /&gt;
 | This is for Alien Swarm&lt;br /&gt;
|}&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/gamedata'''&lt;br /&gt;
 | If an extension or a plugin is using functionality provided by the game engine, e.g. Respawn a player or equipping a player with a weapon, sourcemod needs to know a few &amp;quot;facts&amp;quot; (to be precise: offsets and signatures) about the function. These can change after valve releases an update. At this point you don't need to know more about this, because sourcemod has an integrated updater, which automatically fetches the new gamedata files for you.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/logs'''&lt;br /&gt;
 | The holy grail of debugging your actions. Everything will be logged here. If someone asks you what the logfiles are saying or whether you get any errors: reproduce your problem, then take a look at the logfiles and just copy&amp;amp;paste the messages. Don't try to be smart here and post what you think the given errors are saying, just post the lines. Or fix the problem yourself if you understand the error.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/plugins'''&lt;br /&gt;
 | All plugins (.smx files) in this directory will be loaded automatically when sourcemod starts. Plugins will also be reloaded on mapchange if their file has changed.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/plugins/disabled'''&lt;br /&gt;
 | Plugins in this sub-folder won't be loaded. Move plugins from the parent directory to this one to disable a plugin and vice-a-versa. You will find some official alliedmods plugins in this directory you might want to install (e.g. rockthevote) and some others you want to disable by moving them here (e.g. funvotes).&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/scripting'''&lt;br /&gt;
 | You can find the sourcecode to plugins in this directory, at least the original alliedmods ones. You don't need to place any files here to install a plugin, but it is highly recommended to not only install the smx files, but also their corresponding sp file.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''/translations'''&lt;br /&gt;
 | Not much to say about this folder, it contains translations for many languages. Plugins are encouraged to provide translation files, so you might need to copy some files in here when installing a plugin.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Adding yourself as an admin ===&lt;br /&gt;
To make things easier from now on, you should add yourself as an root-admin.&lt;br /&gt;
There are several ways to manage access rights on your server. In this step we do it quick and dirty, but you might want to read the chapter about [[Adding_Admins_(SourceMod)|Adding Admins]] and [[Adding_Groups_(SourceMod)|Adding Groups]], then create a group for system administrators and add yourself to it.&lt;br /&gt;
&lt;br /&gt;
We are using the simple approach and just add one line to the &amp;lt;tt&amp;gt;admins_simple.cfg&amp;lt;/tt&amp;gt; file in your &amp;lt;tt&amp;gt;sourcemod/configs/&amp;lt;/tt&amp;gt; directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;quot;yoursteamid&amp;quot; &amp;quot;99:z&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
Then enter '''sm_reloadadmins''' in the server console, you should get this as a response: &amp;lt;tt&amp;gt;[SM] Admin cache has been refreshed.&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Try to disable/enable a plugin ===&lt;br /&gt;
If you've read the subsection about the directory layout you should already know how to do this.&lt;br /&gt;
&lt;br /&gt;
And if you read the subsection about the server console you also know how to test if it worked.&lt;br /&gt;
&lt;br /&gt;
But lets explain this again. We want to enable the mapchooser plugin:&lt;br /&gt;
# Copy &amp;lt;tt&amp;gt;plugins/disabled/mapchooser.smx&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;plugins/mapchooser.smx&amp;lt;/tt&amp;gt;&lt;br /&gt;
# You can make this change active by either loading the plugin with &amp;lt;tt&amp;gt;sm plugins load mapchooser&amp;lt;/tt&amp;gt;&amp;lt;br&amp;gt;or by changing the map.&lt;br /&gt;
# Lets take a look at the plugin list and see if it is being listed. Type &amp;lt;tt&amp;gt;sm plugins list&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If not, read the chapter [[#How to test if your plugin is installed correctly|about testing sourcemod plugin installations]]?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Installing Plugins ==&lt;br /&gt;
=== The basics ===&lt;br /&gt;
For simple plugins that come only with the source and a binary like [http://forums.alliedmods.net/showthread.php?t=74531 Basic AFK Manager] installation is pretty straight forward and is basically the same as enabling one of the official plugins (see section [[#Try to disable/enable a plugin|1.4]]). You copy the &amp;lt;tt&amp;gt;.smx&amp;lt;/tt&amp;gt; to the &amp;lt;tt&amp;gt;plugins&amp;lt;/tt&amp;gt; folder and the &amp;lt;tt&amp;gt;.sp&amp;lt;/tt&amp;gt; to the &amp;lt;tt&amp;gt;scripting&amp;lt;/tt&amp;gt; folder.&lt;br /&gt;
&lt;br /&gt;
For more complex plugins like [http://forums.alliedmods.net/showthread.php?t=59147 SM Bot Tools] it might also be required to copy translations or gamedata to the corresponding folders, but the smart developer gives you a zip with the correct folder layout anyway, so you just need to copy everything to the sourcemod folder.&lt;br /&gt;
&lt;br /&gt;
'''Always follow instructions on the plugins page.'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
Rarely plugins have dependencies on other plugins, but it's quite common for a plugin to require one or more extensions. Extensions usually provide features that enable plugins to do stuff they couldnt otherwise. If a plugin has any dependencies it has to be noted somewhere in the plugin description. Look for it.&lt;br /&gt;
&lt;br /&gt;
Learn in chapter 3 [[#Installing an extension|how to install an extension]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How to test if your plugin is installed correctly ===&lt;br /&gt;
When you are troubleshooting plugin and/or extension issues always use the server console. Forget the client console. SourceMod is a server-side addon after all.&lt;br /&gt;
&lt;br /&gt;
Just change the map after the installation and type &amp;lt;tt&amp;gt;sm plugins list&amp;lt;/tt&amp;gt; in the server console. You should see the changes you've made. If the plugin you've installed is not listed, then it is not installed correctly (aka its not the plugins fault, but yours) and you need to figure out what you did wrong. Basically it has to be this: you didn't put the compiled plugin (the &amp;lt;tt&amp;gt;.smx&amp;lt;/tt&amp;gt; file) in the &amp;lt;tt&amp;gt;/plugins&amp;lt;/tt&amp;gt; directory of your sourcemod installation.&lt;br /&gt;
&lt;br /&gt;
If it is listed but prefixed with a &amp;lt;tt&amp;gt;&amp;lt;Failed&amp;gt;&amp;lt;/tt&amp;gt;, something else went wrong. To get details what exactly was the problem type &amp;lt;tt&amp;gt;sm plugins info &amp;lt;plugin id&amp;gt;&amp;lt;/tt&amp;gt;, replace &amp;lt;tt&amp;gt;&amp;lt;plugin id&amp;gt;&amp;lt;/tt&amp;gt; with the number of the plugin you've got in the list. It will probably say something like this:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;width:600px;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; width=&amp;quot;80&amp;quot; | &lt;br /&gt;
! scope=&amp;quot;col&amp;quot; width=&amp;quot;180&amp;quot; |&lt;br /&gt;
 |- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
 |Error || Description&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''Could not find translation file'''&lt;br /&gt;
 | You've forgot to put the translation files on the server or placed them in the wrong directory. Check the plugins thread again, check the provided zip again. If it is really missing from either of those, report it, otherwise: place them in the correct directory.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''Native 'xyz' was not found'''&amp;lt;br&amp;gt;or&amp;lt;br&amp;gt;'''Required extension &amp;quot;xyz&amp;quot; file(&amp;quot;xyz.ext&amp;quot;) not running.'''&lt;br /&gt;
 | You've installed an old version of an extension or did not install a required extension in the first place. Check the installed version (by typing sm exts list) against the version on alliedmods and update if possible.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''Wrong game'''&lt;br /&gt;
 | The plugin you are trying to use is not made for your game, but for another (e.g. [TF2] tHeadshotOnly is obviously only working on TF2). Disable the plugin to get rid of the error message.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Helping the developer ===&lt;br /&gt;
Ok, so you've tried everything to get a plugin to work, but it still won't load. This is pretty unusual. The plugin developer will think you did something wrong installing it and link you to this page. '''Prevent this from happening.''' Give them proof that you've reached a point where it is out of your hand to fix the problem. Tell them what you've tried, give them the console log (via screenshot if you can't copy+paste) and provide them with as much information as you can.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Installing Extensions ==&lt;br /&gt;
=== The basics ===&lt;br /&gt;
Extensions are like plugins, just more powerful. They load if required by a plugin and stay dormant if not. This means extensions that are not required by any of your plugins won't even load - you won't see them when typing &amp;lt;tt&amp;gt;sm exts list&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Some extensions provide features for other plugins to use (like [http://forums.alliedmods.net/showthread.php?t=106748 SDKHooks]), some extensions influence the game directly (like [http://forums.alliedmods.net/showthread.php?t=145218 UnlockBlock]).&lt;br /&gt;
&lt;br /&gt;
=== Extension versions and filenames ===&lt;br /&gt;
Some extensions will have just one version for all Source games.  These will have filenames like &amp;lt;tt&amp;gt;bintools.ext.dll&amp;lt;/tt&amp;gt; for Windows, &amp;lt;tt&amp;gt;bintools.ext.so&amp;lt;/tt&amp;gt; for Linux, or &amp;lt;tt&amp;gt;bintools.ext.dylib&amp;lt;/tt&amp;gt; for OSX.&lt;br /&gt;
&lt;br /&gt;
Other extensions will have multiple versions depending on the game engine being used.  These filenames are generally named like this: &amp;lt;tt&amp;gt;[extension name].ext.[MetaMod: Source API version].[Game engine string].[extension]&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For example, SDKTools has the following files in the Windows SourceMod release&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Games !! filename&lt;br /&gt;
|-&lt;br /&gt;
| Alien Swarm || &amp;lt;tt&amp;gt;sdktools.ext.2.swarm.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Bloody Good Time || &amp;lt;tt&amp;gt;sdktools.ext.2.bgt.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Dark Messiah || &amp;lt;tt&amp;gt;sdktools.ext.2.darkm.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Episode 1 / Generic non-OB mods || &amp;lt;tt&amp;gt;sdktools.ext.1.ep1.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Episode 2 / Orange Box / Source 2007 / Generic OB mods || &amp;lt;tt&amp;gt;sdktools.ext.2.ep2.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| E.Y.E: Divine Cybermancy || &amp;lt;tt&amp;gt;sdktools.ext.2.eye.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead || &amp;lt;tt&amp;gt;sdktools.ext.2.l4d.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead 2 || &amp;lt;tt&amp;gt;sdktools.ext.2.l4d2.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Source 2009 / Half-Life 2: DeathMatch / Day of Defeat: Source / Counter-Strike: Source / Team Fortress 2 || &amp;lt;tt&amp;gt;sdktools.ext.2.ep2v.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Installing an extension ===&lt;br /&gt;
This is pretty much the same as installing plugins, so it does not seem necessary to list the required steps, but i will do it anyway.&lt;br /&gt;
To install an extension you just copy it to the &amp;lt;tt&amp;gt;/extensions&amp;lt;/tt&amp;gt; directory.&lt;br /&gt;
'''Extensions can require gamedata and translations like plugins, so don't forget to install them too.'''&lt;br /&gt;
&lt;br /&gt;
To actually load the extension just change the map or type &amp;lt;tt&amp;gt;sm exts load &amp;lt;name of your extension&amp;gt;&amp;lt;/tt&amp;gt; in the server console. Remember that extensions wont load automatically if they are not required in the first place.&lt;br /&gt;
&lt;br /&gt;
To force an extension to always load, just create an empty file with the name of the extension itself and the file-extension &amp;lt;tt&amp;gt;.autoload&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Example:&lt;br /&gt;
** extension file name is &amp;lt;tt&amp;gt;extensions/sdkhooks.ext.2.ep2v.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
** to autoload this extension create an empty file &amp;lt;tt&amp;gt;extensions/sdkhooks.autoload&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note:''' You can't update a running extension, you need to disable it first via &amp;lt;tt&amp;gt;sm unload &amp;lt;extensionname&amp;gt;&amp;lt;/tt&amp;gt; or stop your server. Otherwise your server will most likely crash if you're on linux and block you from doing so on windows.&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting extension issues ===&lt;br /&gt;
Again, this is pretty much the same procedure that you've learned already.&lt;br /&gt;
&lt;br /&gt;
How to test if it is loaded or failed while loading? sm exts list&lt;br /&gt;
How to load an extension at runtime? sm exts load &amp;lt;extension name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both should give you an output '''why''' it failed. Those can be the same reasons as in chapter [[#How to test if your plugin is installed correctly|How to test if your plugin is installed correctly]], so make sure to read that if you haven't done already.&lt;br /&gt;
At the very least they should give you an indication on how to proceed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Documentation]]&lt;/div&gt;</summary>
		<author><name>Shooting King</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=CBasePlayer_(CS)&amp;diff=11235</id>
		<title>CBasePlayer (CS)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=CBasePlayer_(CS)&amp;diff=11235"/>
		<updated>2021-09-28T21:47:38Z</updated>

		<summary type="html">&lt;p&gt;Shooting King: Missing closing Table token&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:CS Class List]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CBaseEntity (CS)|CBaseEntity]]&lt;br /&gt;
** [[CBaseDelay (CS)|CBaseDelay]]&lt;br /&gt;
*** [[CBaseAnimating (CS)|CBaseAnimating]]&lt;br /&gt;
**** [[CBaseToggle (CS)|CBaseToggle]]&lt;br /&gt;
***** [[CBaseMonster (CS)|CBaseMonster]]&lt;br /&gt;
****** '''CBasePlayer''' ''(player)''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;''W = Windows'' |&amp;lt;/tt&amp;gt;&amp;lt;tt&amp;gt; ''L = Linux''&amp;lt;/tt&amp;gt;&lt;br /&gt;
{| cellpadding=&amp;quot;4&amp;quot;&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
! Name !! W. Offset !! L. Offset !! L. Diff !! Type !! Description&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| random_seed&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 96 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 101&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| See that is shared between client &amp;amp; server for shared weapons code.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| Unknown&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 97 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 102&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | Unknown&lt;br /&gt;
| Unknown&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_hSpecTarget&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 98 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 103&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | Unknown&lt;br /&gt;
| Not sure, maybe last spectated&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| Unknown&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | - &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | -&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | - &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | -&lt;br /&gt;
| EHANDLE takes place of 2 int, so nothing else here than previous data&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flNextSpecButtonTime&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 100&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 105&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| Next gametime pressing a button will take effect when spectating.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iSpectatedPlayerWeaponId&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 101&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 106&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| weapon type ( CSW_ ) the spectated player is holding&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_fHasSpectatedPlayerC4&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 102&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 107&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| &lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_fHasSpectatedPlayerDefuseKit&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 103&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 108&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| -&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iObserverMode&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 104&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 109&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| enum {OBS_NONE = 0, OBS_CHASE_LOCKED, OBS_CHASE_FREE, OBS_ROAMING, OBS_IN_EYE, OBS_MAP_FREE, OBS_MAP_CHASE}&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 105&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 110&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| ?&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 106&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 111&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| ?&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 107&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 112&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| ?&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flPainShock&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 108&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 113&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| set to 0.3 or 1.0 when take damage, slows down player untill progressively reset to 0 by timers.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iLastZoom&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 109&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 114&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Store zoomed value when player has just shot while zooming, so zoom can be restored&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_fResumeZoom&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 110&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 115&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | BOOL (int)&lt;br /&gt;
| Wheter zoom has to be restored or not after a shot&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flEjectBrass&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 111&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 116&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| &lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iKevlarType&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 112&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 117&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| 0-No Kevlar , 1-Vest , 2-Vest+Helmet&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_fHasBeenKilledLastRound&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 113&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 118&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Set to 1 if player has been killed last round, so game knows, for example, that default weapons has to be given.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iPlayerTeam&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 114&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 119&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Player team (0-NONE, 1-TT, 2-CT, 3-SPECTATOR, &amp;gt;3 Other teams)&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iAccount&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 115&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 120&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Player money amount&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_fHasPrimary&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 116&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 121&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| If set to 1, player can't pickup an armoury entity holding a primary weapon, may be used to check for shield pickup&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iDefaultItems&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 120&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 125&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Default items (knife, gun) given: 1&amp;lt;&amp;lt;0 =&amp;gt; Already given&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iJoinedState&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 121&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 126&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Join state for player (value of 5 will put the player in-game, other value will put the player on trigger_camera)&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_pLastCamera&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 122&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 127&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | CBaseEntity*&lt;br /&gt;
| use get_pdata_cbase&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flNextCameraTime&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 123&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 128&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| -&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flNextCameraTime&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 122&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 127&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| -&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flLastActivityTime&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 124&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 129&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| -&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_bHasBeenShownBriefing&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 125&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 130&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | bool&lt;br /&gt;
| Use get_pdata_int(playerIndex, m_bHasBeenShownBriefing) &amp;amp; (1&amp;lt;&amp;lt;0)&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_bHasChangeTeamThisRound&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 125&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 130&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | bool&lt;br /&gt;
| -Use get_pdata_int(playerIndex, m_bHasChangeTeamThisRound) &amp;amp; 1&amp;lt;&amp;lt;8&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iInternalModel&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 126&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 131&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | inf&lt;br /&gt;
| see cstrike.inc&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iPlayerSound&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 237&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 242&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| The index of the sound list slot reserved for this player.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iTargetVolume&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 238 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 243 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Ideal sound volume. &lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iWeaponVolume&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 239&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 244 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| How loud the player's weapon is right now.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iExtraSoundTypes&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 240&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 245&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Additional classification for this weapon's sound.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iWeaponFlash&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 241&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 246 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Brightness of the weapon flash.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flStopExtraSoundTime&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 242&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 247&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| None.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flFlashLightTime&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 243&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 248&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| Time until next battery draw/Recharge.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iFlashBattery&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 244&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 249&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Flashlight Battery Draw.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_afButtonLast&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 245&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 250&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| None.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_afButtonPressed&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 246&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 251&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| None.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_afButtonReleased&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 247&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 252&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| None.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_pentSndLast&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 248&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 253&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | edict_t*&lt;br /&gt;
| Last sound entity to modify player room type. ( get_pdata_ent() )&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flSndRoomtype&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 249&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 254&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| Last roomtype set by sound entity.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flSndRange&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 250&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 255&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| Dist from player to sound entity.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flFallVelocity&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 251&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 256&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| Player's fall speed.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_rgItems[item_antidote]&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 254&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 259&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| None.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_rgItems[item_security]&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 255&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 260&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| None.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_fKnownItem&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| True when a new item needs to be added.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_fNewAmmo&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| True when a new item has been added.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_afPhysicsFlags&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 257&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 263&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | unsigned int&lt;br /&gt;
| Physics flags - set when 'normal' physics should be revisited or overriden.&lt;br /&gt;
The following masks can be found in player.h:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#define     PFLAG_ONLADDER      ( 1&amp;lt;&amp;lt;0 )&lt;br /&gt;
#define     PFLAG_ONSWING       ( 1&amp;lt;&amp;lt;0 )&lt;br /&gt;
#define     PFLAG_ONTRAIN       ( 1&amp;lt;&amp;lt;1 )&lt;br /&gt;
#define     PFLAG_ONBARNACLE    ( 1&amp;lt;&amp;lt;2 )&lt;br /&gt;
#define     PFLAG_DUCKING       ( 1&amp;lt;&amp;lt;3 )        // In the process of ducking, but totally squatted yet&lt;br /&gt;
#define     PFLAG_USING         ( 1&amp;lt;&amp;lt;4 )        // Using a continuous entity&lt;br /&gt;
#define     PFLAG_OBSERVER      ( 1&amp;lt;&amp;lt;5 )        // player is locked in stationary cam mode. Spectators can move, observers can't.&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_fNextSuicideTime&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 258&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 263&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| The time after which the player can next use the suicide command.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flTimeStepSound&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 259&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 264&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| When the last stepping sound was made.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flTimeWeaponIdle&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 260&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 265&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| When to play another weapon idle animation.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flSwimTime&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 261&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 266&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| How long player has been underwater.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flDuckTime&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 262&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 267&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| How long we've been ducking.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flWallJumpTime&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 263&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 268&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| How long until next walljump.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flSuitUpdate&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 264&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 269&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| When to play next suit update.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_rgSuitPlayList&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 265&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 270&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int[CSUITPLAYLIST]&lt;br /&gt;
| Next sentencenum to play for suit update.&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#define CSUITPLAYLIST	4  // max of 4 suit sentences queued up at any time&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iSuitPlayNext&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 269&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 274&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Next sentence slot for queue storage.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_rgiSuitNoRepeat&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 270&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 275&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int[CSUITNOREPEAT]&lt;br /&gt;
| Suit sentence no repeat list.&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#define CSUITNOREPEAT  32&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_rgflSuitNoRepeatTime&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 302&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 207&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int[CSUITNOREPEAT]&lt;br /&gt;
| How long to wait before allowing repeat.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_lastDamageAmount&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 334&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 339&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5 &lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Last damage taken.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_tbdPrev&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 335&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 340&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| Time-based damage timer.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flgeigerRange&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 336&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 341&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| Range to nearest radiation source.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flgeigerDelay&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 337&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 342&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| Delay per update of range msg to client.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_igeigerRangePrev&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 338&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 343&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| None.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iStepLeft&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 339&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 344&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Alternate left/right foot stepping sound.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_szTextureName&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | char[CBTEXTURENAMEMAX]&lt;br /&gt;
| Current texture name we're standing on.&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#define CBTEXTURENAMEMAX  13 // only load first n chars of name&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_chTextureType&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | char&lt;br /&gt;
| Current texture type.&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#define CHAR_TEX_CONCRETE  'C'	// texture types&lt;br /&gt;
#define CHAR_TEX_METAL	   'M'&lt;br /&gt;
#define CHAR_TEX_DIRT	   'D'&lt;br /&gt;
#define CHAR_TEX_VENT	   'V'&lt;br /&gt;
#define CHAR_TEX_GRATE	   'G'&lt;br /&gt;
#define CHAR_TEX_TILE	   'T'&lt;br /&gt;
#define CHAR_TEX_SLOSH	   'S'&lt;br /&gt;
#define CHAR_TEX_WOOD	   'W'&lt;br /&gt;
#define CHAR_TEX_COMPUTER  'P'&lt;br /&gt;
#define CHAR_TEX_GLASS	   'Y'&lt;br /&gt;
#define CHAR_TEX_FLESH	   'F'&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_idrowndmg&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 345&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 350&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Track drowning damage taken.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_idrownrestored&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 346&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 351&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Track drowning damage restored.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_bitsHUDDamage&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 347&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 352&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Damage bits for the current fame. These get sent to the hud via the Damage message.&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
// these are the damage types that have client hud art&lt;br /&gt;
#define DMG_SHOWNHUD ( DMG_POISON | DMG_ACID | DMG_FREEZE | DMG_SLOWFREEZE | DMG_DROWN | DMG_BURN | DMG_SLOWBURN | DMG_NERVEGAS | DMG_RADIATION | DMG_SHOCK )&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_fInitHUD&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 348&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 353&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | BOOL&lt;br /&gt;
| True when deferred HUD restart msg needs to be sent.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_fInitHUD&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 349&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 354&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | BOOL&lt;br /&gt;
| None.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iTrain&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 350&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 355&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Train control position.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_fWeapon&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 351&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 356&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | BOOL&lt;br /&gt;
| Set this to FALSE to force a reset of the current weapon HUD info.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_pTank&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | EHANDLE&lt;br /&gt;
| The tank which the player is currently controlling,  NULL if no tank.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_fDeadTime&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 354&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 359&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| the time at which the player died  (used in PlayerDeathThink()).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_fNoPlayerSound&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 355&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 360&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | BOOL&lt;br /&gt;
| A debugging feature. Player makes no sound if this is true. &lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_fLongJump&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 356&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 361&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | BOOL&lt;br /&gt;
| Does this player have the longjump module?&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_tSneaking&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 357&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 362&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| None.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iUpdateTime&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 358&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 363&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Stores the number of frame ticks before sending HUD update messages.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iClientHealth&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 359&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 364&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| The health currently known by the client.  If this changes, send a new.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iClientBattery&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 360&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 365&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| The Battery currently known by the client.  If this changes, send a new.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iHideHUD&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 361&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 366&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| The players hud weapon info is to be hidden&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iClientHideHUD&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 362&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 367&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| None.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iFOV&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 363&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 368&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Field of view.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iClientFOV&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 364&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 369&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Client's known FOV.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iNumRespawns&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 365&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 370&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| &lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_pentRemoveOnDisconnect&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 366&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 370&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Not really used in CS. If you set an entity in this offset, when a player disconnects this entity will be removed.&lt;br /&gt;
Needs a better name.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_rgpPlayerItems&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 367&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 372&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | CBasePlayerItem*[MAX_ITEM_TYPES]&lt;br /&gt;
| (get_pdata_cbase)&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#define MAX_ITEM_TYPES 6&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_pActiveItem&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 373&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 378&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | CBasePlayerItem*&lt;br /&gt;
| (get_pdata_cbase)&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_pClientActiveItem&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 374&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 379&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | CBasePlayerItem*&lt;br /&gt;
| Client version of the active item. (get_pdata_cbase)&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_pLastItem&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 375&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 380&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | CBasePlayerItem*&lt;br /&gt;
| (get_pdata_cbase)&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_rgAmmo&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 376&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 381&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int[MAX_AMMO_SLOTS]&lt;br /&gt;
| Shared ammo slots.&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#define MAX_AMMO_SLOTS  32  // not really slots&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_rgAmmoLast&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 408&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 413&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int[MAX_AMMO_SLOTS]&lt;br /&gt;
| Shared ammo slots.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_vecAutoAim&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 440&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 445&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | Vector&lt;br /&gt;
| Shared ammo slots.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_fOnTarget&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 441&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 446&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | BOOL&lt;br /&gt;
| Shared ammo slots.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iDeaths&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 442&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 447&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Shared ammo slots.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iRespawnFrames&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 443&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 447&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| Used in PlayerDeathThink() to make sure players can always respawn.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_izSBarState&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 446&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 451&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int[SBAR_END]&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
enum sbar_data&lt;br /&gt;
{&lt;br /&gt;
	SBAR_ID_TARGETNAME = 1,&lt;br /&gt;
	SBAR_ID_TARGETHEALTH,&lt;br /&gt;
	SBAR_ID_TARGETARMOR,&lt;br /&gt;
	SBAR_END,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flNextSBarUpdateTime&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 449&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 454&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| None.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flStatusBarDisappearDelay&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 450&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 455&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| None.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_lastx&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 483&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 488&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| These are the previous update's crosshair angles.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_lasty&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 484&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 489&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| These are the previous update's crosshair angles.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_nCustomSprayFrames&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 485&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 490&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Custom clan logo frames for this player.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flNextDecalTime&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 486&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 491&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| Next time this player can spray a decal.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_szTeamName&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 487&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 492&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | char[TEAM_NAME_LENGTH]&lt;br /&gt;
| None.&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#define TEAM_NAME_LENGTH  16&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_szAnimExtention&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 492&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 497&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | char[32]&lt;br /&gt;
| None.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_SbarString0&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | char[ SBAR_STRING_SIZE ]&lt;br /&gt;
| &lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#define SBAR_STRING_SIZE 128&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_SbarString1&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | char[ SBAR_STRING_SIZE ]&lt;br /&gt;
| None.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_flNextChatTime&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | ?&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | float&lt;br /&gt;
| &lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#define CHAT_INTERVAL 1.0f&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iClAutoWepSwitch&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 509&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 514&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Last _cl_autowepswitch value of userinfo for this player&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| m_iVGUIMenus&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 510&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | 515&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | +5&lt;br /&gt;
| style=&amp;quot;text-align:center&amp;quot; | int&lt;br /&gt;
| Last _vgui_menus value of userinfo for this player&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Shooting King</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Base_Plugins_(SourceMod)/zh&amp;diff=11234</id>
		<title>Base Plugins (SourceMod)/zh</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Base_Plugins_(SourceMod)/zh&amp;diff=11234"/>
		<updated>2021-09-28T21:39:47Z</updated>

		<summary type="html">&lt;p&gt;Shooting King: Use proper table headers&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Languages|Base Plugins (SourceMod)}}&lt;br /&gt;
__FORCETOC__&lt;br /&gt;
这里会介绍[[SourceMod]]附带的基本插件和它们的用途。&lt;br /&gt;
&lt;br /&gt;
加粗的插件能在[[War_Mode_(SourceMod)|War Mode]]下安全使用，因为他们没有可滥用或者不公平的成分。&lt;br /&gt;
&lt;br /&gt;
=默认插件=&lt;br /&gt;
{| style=&amp;quot;width:600px;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
 !插件&lt;br /&gt;
 !用途&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''admin-flatfile'''&lt;br /&gt;
 | 从管理员配置文件中获取管理员信息&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''adminhelp'''&lt;br /&gt;
 | 提供了sm_help命令（显示其他的命令和它们的语法）&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''adminmenu'''&lt;br /&gt;
 | 提供了管理菜单的API和核心功能&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | antiflood&lt;br /&gt;
 | 防止客户端被各类信息骚扰&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''basebans'''&lt;br /&gt;
 | 提供了基础的封禁功能和封禁菜单&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | basechat&lt;br /&gt;
 | 提供了管理用户使用语音聊天或者聊天框的命令和菜单&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | basecomm&lt;br /&gt;
 | 提供了改变用户交流方式的功能（与sv_alltalk相比）&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''basecommands'''&lt;br /&gt;
 | 提供了不被用户滥用的基础管理指令（例如换图，踢人等）&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | basetriggers&lt;br /&gt;
 | 提供了对一些语句的回复（例如，&amp;quot;nextmap&amp;quot;, &amp;quot;thetime&amp;quot;, 和 &amp;quot;timeleft&amp;quot;）&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | basevotes&lt;br /&gt;
 | 提供了基础的投票指令，例如换图&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''clientprefs'''&lt;br /&gt;
 | 给客户端增加了一个基于控制台（sm_cookies）的和一个基于菜单的设置功能(sm_settings)&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | funcommands&lt;br /&gt;
 | 提供了类似拍打的有趣的命令（影响平衡）&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | funvotes&lt;br /&gt;
 | 提供基于funcommands的投票功能&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''nextmap'''&lt;br /&gt;
 | 允许客户或者其他插件换图&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | playercommands&lt;br /&gt;
 | 增加了sm_slap, sm_slay, 和sm_rename命令&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | reservedslots&lt;br /&gt;
 | 允许服务器保留通道给管理员或者特权人员，来保证他们可以加入服务器&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | sounds&lt;br /&gt;
 | 增加了命令“sm_play”&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=额外插件=&lt;br /&gt;
接下来是默认禁用了的插件。（位于&amp;lt;tt&amp;gt;addons/sourcemod/plugins/disabled&amp;lt;/tt&amp;gt;，你需要把它们移出到上一级文件夹来启用）&lt;br /&gt;
&lt;br /&gt;
如果一个插件有CVars（控制台变量，提供了在控制台修改部分属性的功能），你可以从加载一次来在&amp;lt;tt&amp;gt;cfg/sourcemod&amp;lt;/tt&amp;gt;生成配置文件。&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;width:600px;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
 !插件&lt;br /&gt;
 !用途&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''admin-sql-prefetch'''&lt;br /&gt;
 | 每次换图时，重新从数据库读取管理员信息。启用这个时，必须禁用&amp;lt;tt&amp;gt;admin-sql-threaded&amp;lt;/tt&amp;gt;。参考[[SQL_Admins_(SourceMod)|SQL Admins]]&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''admin-sql-threaded'''&lt;br /&gt;
 | 每次管理员连入时，重新从数据库读取管理员信息。启用这个时，必须禁用&amp;lt;tt&amp;gt;admin-sql-prefetch&amp;lt;/tt&amp;gt;。参考[[SQL_Admins_(SourceMod)|SQL Admins]]&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | mapchooser&lt;br /&gt;
 | 提供了一个便于玩家选图的系统。启用这个时，必须禁用&amp;lt;tt&amp;gt;randomcycle&amp;lt;/tt&amp;gt;。Cvars生成在&amp;lt;tt&amp;gt;mapchooser.cfg&amp;lt;/tt&amp;gt;&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | randomcycle&lt;br /&gt;
 | 随机换图。启用这个时，必须禁用&amp;lt;tt&amp;gt;mapchooser&amp;lt;/tt&amp;gt;。Cvars生成在&amp;lt;tt&amp;gt;randomcycle.cfg&amp;lt;/tt&amp;gt;&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | rockthevote&lt;br /&gt;
 | 提供玩家投票开启换图的功能。（也就是rtv）Cvars生成在&amp;lt;tt&amp;gt;rtv.cfg&amp;lt;/tt&amp;gt;.&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Documentation]]&lt;/div&gt;</summary>
		<author><name>Shooting King</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Base_Plugins_(SourceMod)&amp;diff=11233</id>
		<title>Base Plugins (SourceMod)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Base_Plugins_(SourceMod)&amp;diff=11233"/>
		<updated>2021-09-28T21:32:58Z</updated>

		<summary type="html">&lt;p&gt;Shooting King: Make a header&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Languages|Base Plugins (SourceMod)}}&lt;br /&gt;
__FORCETOC__&lt;br /&gt;
The following is a full list of [[SourceMod]]'s base plugins and the purpose of each one.&lt;br /&gt;
&lt;br /&gt;
Plugins with a bold name are safe to be used in [[War_Mode_(SourceMod)|War Mode]], as they do not contain anything that could be considered abusive or unfair.&lt;br /&gt;
&lt;br /&gt;
=Default Plugins=&lt;br /&gt;
{| style=&amp;quot;width:600px;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
 !Plugin&lt;br /&gt;
 !Purpose&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''admin-flatfile'''&lt;br /&gt;
 | Loads admins from the admin configuration files.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''adminhelp'''&lt;br /&gt;
 | Provides the sm_help command (lists other commands and their syntax).&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''adminmenu'''&lt;br /&gt;
 | Provides the admin menu API and core features.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | antiflood&lt;br /&gt;
 | Prevents clients from spamming messagemode/chat.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''basebans'''&lt;br /&gt;
 | Provides basic banning commands and menu options.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | basechat&lt;br /&gt;
 | Provides commands and menu options for managing player's abilities to use voice chat or say chat.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | basecomm&lt;br /&gt;
 | Provides functionality for tweaking how players can communicate (in comparison to sv_alltalk).&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''basecommands'''&lt;br /&gt;
 | Provides basic administrative commands unrelated to player abuse (for example, map changing, kicking, and cvar changing).&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | basetriggers&lt;br /&gt;
 | Provides automated responses to phrases such as &amp;quot;nextmap&amp;quot;, &amp;quot;thetime&amp;quot;, and &amp;quot;timeleft&amp;quot;.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | basevotes&lt;br /&gt;
 | Provides basic voting commands, such as map voting.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''clientprefs'''&lt;br /&gt;
 | Adds a console based (sm_cookies) and menu based (sm_settings) inteface for clients to access their settings.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | funcommands&lt;br /&gt;
 | Provides &amp;quot;fun&amp;quot; commands, like slapping.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | funvotes&lt;br /&gt;
 | Provides votes based on basefuncommands.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''nextmap'''&lt;br /&gt;
 | Allows admins or other plugins to dynamically alter or retrieve the effective mapcycle.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | playercommands&lt;br /&gt;
 | Adds commands sm_slap, sm_slay, and sm_rename&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | reservedslots&lt;br /&gt;
 | Allows the server to have slots that are reserved for administrators (or privileged people), to ensure prioritized entry.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | sounds&lt;br /&gt;
 | Adds command sm_play&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
=Extra Plugins=&lt;br /&gt;
The following plugins are in the &amp;lt;tt&amp;gt;addons/sourcemod/plugins/disabled&amp;lt;/tt&amp;gt; folder by default, and must be moved out of that folder to be enabled.&lt;br /&gt;
&lt;br /&gt;
If a plugin has cvars, you can load it once to generate its config file in &amp;lt;tt&amp;gt;cfg/sourcemod&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;width:600px;&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
 !Plugin File&lt;br /&gt;
 !Purpose&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''admin-sql-prefetch'''&lt;br /&gt;
 | Loads admins from an SQL database as a big lump every mapchange.  If enabled, &amp;lt;tt&amp;gt;admin-sql-threaded&amp;lt;/tt&amp;gt; must be disabled; see [[SQL_Admins_(SourceMod)|SQL Admins]].&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | '''admin-sql-threaded'''&lt;br /&gt;
 | Loads admins from an SQL database dynamically as each admin connects.  If enabled, &amp;lt;tt&amp;gt;admin-sql-prefetch&amp;lt;/tt&amp;gt; must be disabled; see [[SQL_Admins_(SourceMod)|SQL Admins]].&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | mapchooser&lt;br /&gt;
 | Provides an automated system for players to vote for map changes.  If enabled, &amp;lt;tt&amp;gt;randomcycle&amp;lt;/tt&amp;gt; should be disabled.  Cvars are generated in &amp;lt;tt&amp;gt;mapchooser.cfg&amp;lt;/tt&amp;gt;.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | randomcycle&lt;br /&gt;
 | Randomizes the map cycle.  If enabled, &amp;lt;tt&amp;gt;mapchooser&amp;lt;/tt&amp;gt; should be disabled.  Cvars are generated in &amp;lt;tt&amp;gt;randomcycle.cfg&amp;lt;/tt&amp;gt;.&lt;br /&gt;
 |- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
 | rockthevote&lt;br /&gt;
 | Provides a player-initiated system for players to vote for map changes.  Cvars are generated in &amp;lt;tt&amp;gt;rtv.cfg&amp;lt;/tt&amp;gt;.&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Documentation]]&lt;/div&gt;</summary>
		<author><name>Shooting King</name></author>
		
	</entry>
</feed>