<?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=Fyren</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=Fyren"/>
	<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/Special:Contributions/Fyren"/>
	<updated>2026-05-08T15:42:15Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.6</generator>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Handle_API_(SourceMod)&amp;diff=11718</id>
		<title>Handle API (SourceMod)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Handle_API_(SourceMod)&amp;diff=11718"/>
		<updated>2024-06-26T17:44:01Z</updated>

		<summary type="html">&lt;p&gt;Fyren: Undo revision 5690 by Zerak (talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The SourceMod [[Handles (SourceMod Scripting)|Handle System]] marshals pointers into typed, unique, 32-bit integers.  This makes coding in SourceMod more cross-platform compatible, type safe, and mistake safe than its predecessor, [[AMX Mod X]].  It also allows for safe object sharing and reference count based object destruction.&lt;br /&gt;
&lt;br /&gt;
The fundamental aspect of Handles is that they encapsulate a single pointer.  This pointer is private data, and can only be read by the Handle's creator.  When the Handle is freed, the pointer is automatically freed (via a special interface), thus ensuring that memory is not leaked.&lt;br /&gt;
&lt;br /&gt;
Handles also provide a simple &amp;quot;security&amp;quot; system for restricting which areas of SourceMod are allowed to directly call certain functions on Handles under a given type.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Basic Types=&lt;br /&gt;
==Handle_t==&lt;br /&gt;
The &amp;lt;tt&amp;gt;Handle_t&amp;lt;/tt&amp;gt; type is a 32bit integer.  Currently, it is composed of two 16-bit integers, a serial number and a handle index.  The serial number is private and used for integrity checking.  The index is the internal ID of the Handle, which is tied to the encapsulated pointer and security information.&lt;br /&gt;
&lt;br /&gt;
Each &amp;lt;tt&amp;gt;Handle_t&amp;lt;/tt&amp;gt; is a unique Handle, however, there are ''cloned'' Handles which are copies of another Handle.  They have their own unique signatures, but they refer to another Handle internally.  Each Handle is also associated with a ''type'', explained below.&lt;br /&gt;
&lt;br /&gt;
==HandleType_t==&lt;br /&gt;
The &amp;lt;tt&amp;gt;HandleType_t&amp;lt;/tt&amp;gt; describes a type under which Handles can be created.  Types can have up to 15 sub-types; sub-types cannot have their own sub-types, called child types.  When Handles are being read, they are &amp;quot;type checked,&amp;quot; to make sure they are being read under a given type.  When a type is destroyed, all Handles under the type are destroyed.  If the type has child types, each child type is also destroyed. &lt;br /&gt;
&lt;br /&gt;
Handle types also allow overloading of various Handle operations.  Currently, the only overloaded action is for overloading when a Handle is destroyed.  This allows the encapsulated pointer to be safely destroyed by the type interface.  The interface which overloads type operations is called &amp;lt;tt&amp;gt;IHandleTypeDispatch&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Lastly, types provide a &amp;quot;default security&amp;quot; system which lets programmers restrict which functions can be accessed by other areas in SourceMod.  This is explained later.&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
'''Note:''' Type defaults can be set via &amp;lt;tt&amp;gt;IHandleSys::InitAccessDefaults()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Type Security==&lt;br /&gt;
Often, extensions may want to share HandleType_t values with each other, so they can create Handles of external types.  However, the owner of the handle type may not want other extensions to perform certain actions.  Thus, types can be ''secured'' by an &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt; when created.  Unless the same &amp;lt;tt&amp;gt;IdentityToken&amp;lt;/tt&amp;gt; is provided, a function may fail if restricted.&lt;br /&gt;
&lt;br /&gt;
Type permissions are declared in a &amp;lt;tt&amp;gt;TypeAccess&amp;lt;/tt&amp;gt; struct, which has the following user-set members:&lt;br /&gt;
*&amp;lt;tt&amp;gt;ident&amp;lt;/tt&amp;gt;: The &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt; owner of this type.&lt;br /&gt;
*&amp;lt;tt&amp;gt;access&amp;lt;/tt&amp;gt;: An array where each index is a &amp;lt;tt&amp;gt;HTypeAccessRight&amp;lt;/tt&amp;gt; enumeration member.  If an index is set to false, functions requiring that right will fail unless the correct &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt; is passed in.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;HTypeAccessRight&amp;lt;/tt&amp;gt; enumeration has the following values:&lt;br /&gt;
*&amp;lt;tt&amp;gt;HTypeAccess_Create&amp;lt;/tt&amp;gt;: Handle creation using this type; default is false.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HTypeAccess_Inherit&amp;lt;/tt&amp;gt;: Inheriting this type for child types; default is false.&lt;br /&gt;
&lt;br /&gt;
Below is a list of each Handle System function that requires type permissions, and which permissions may be required:&lt;br /&gt;
*&amp;lt;tt&amp;gt;CreateType&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;&amp;lt;tt&amp;gt;HTypeAccess_Inherit&amp;lt;/tt&amp;gt; if a parent is specified&amp;lt;/i&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;RemoveType&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;(none, always secured)&amp;lt;/i&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;CreateHandle&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;&amp;lt;tt&amp;gt;HTypeAccess_Create&amp;lt;/tt&amp;gt;&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Handle Security==&lt;br /&gt;
Handle security permissions inherit from their parent type unless given an alternate set of permissions.  Handles are &amp;quot;secured&amp;quot; by two properties, unlike handle types, which just have one.  When verifying your identity with a secured Handle function, you must use the &amp;lt;tt&amp;gt;HandleSecurity&amp;lt;/tt&amp;gt; struct, which has two properties:&lt;br /&gt;
*&amp;lt;tt&amp;gt;pOwner&amp;lt;/tt&amp;gt;: The owner of the Handle, which is usually a plugin &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;pIdentity&amp;lt;/tt&amp;gt;: The owner of the Handle's type, or the &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt; securing its type.&lt;br /&gt;
&lt;br /&gt;
Handle permissions are specified via the &amp;lt;tt&amp;gt;HandleAccess&amp;lt;/tt&amp;gt; struct.  It is passed either through &amp;lt;tt&amp;gt;CreateType&amp;lt;/tt&amp;gt; for default settings in a given type, or through &amp;lt;tt&amp;gt;CreateHandleEx&amp;lt;/tt&amp;gt; for explicit per-Handle permissions.  This struct has the following members:&lt;br /&gt;
*&amp;lt;tt&amp;gt;access&amp;lt;/tt&amp;gt;: An array where each index is a &amp;lt;tt&amp;gt;HandleAccessRight&amp;lt;/tt&amp;gt; enumeration member.  If set to 0, an access right is allowed without a &amp;lt;tt&amp;gt;HandleSecurity&amp;lt;/tt&amp;gt; instance.  Otherwise, the following bitwise flags are checked:&lt;br /&gt;
**&amp;lt;tt&amp;gt;HANDLE_RESTRICT_IDENTITY&amp;lt;/tt&amp;gt;: If flagged, this access right is only granted if the &amp;lt;tt&amp;gt;pIdentity&amp;lt;/tt&amp;gt; member of the &amp;lt;tt&amp;gt;HandleSecurity&amp;lt;/tt&amp;gt; struct matches the Handle's '''type's''' owner.&lt;br /&gt;
**&amp;lt;tt&amp;gt;HANDLE_RESTRICT_OWNER&amp;lt;/tt&amp;gt;: If flagged, this access right is only granted if the &amp;lt;tt&amp;gt;pOwner&amp;lt;/tt&amp;gt; member of the &amp;lt;tt&amp;gt;Handlesecurity&amp;lt;/tt&amp;gt; struct matches the Handle's owner.&lt;br /&gt;
&lt;br /&gt;
The following access rights exist for Handles:&lt;br /&gt;
*&amp;lt;tt&amp;gt;HandleAccess_Read&amp;lt;/tt&amp;gt;: This Handle's encapsulated pointer can be retrieved.  Defaults to &amp;lt;tt&amp;gt;HANDLE_RESTRICT_IDENTITY&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HandleAccess_Delete&amp;lt;/tt&amp;gt;: This Handle can be removed or freed.  Defaults to &amp;lt;tt&amp;gt;HANDLE_RESTRICT_OWNER&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HandleAccess_Clone&amp;lt;/tt&amp;gt;: This Handle can be cloned.  Defaults to 0.&lt;br /&gt;
&lt;br /&gt;
Below is a list of each Handle system function that requires permissions, and which permissions may be required:&lt;br /&gt;
*&amp;lt;tt&amp;gt;FreeHandle&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;&amp;lt;tt&amp;gt;HandleAccess_Delete&amp;lt;/tt&amp;gt;&amp;lt;/i&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;CloneHandle/CloneHandleEx&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;&amp;lt;tt&amp;gt;HandleAccess_Clone&amp;lt;/tt&amp;gt;&amp;lt;/i&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;ReadHandle&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;&amp;lt;tt&amp;gt;HandleAccess_Read&amp;lt;/tt&amp;gt;&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
SourceMod's generic native wrappers assume follow these rules, however, they assume certain access rights, and will return &amp;lt;tt&amp;gt;INVALID_HANDLE&amp;lt;/tt&amp;gt; or 0 if these rights are denied.  Thus, you should make sure your permissions are compatible, unless you explicitly want to deny usage of these functions.&lt;br /&gt;
*&amp;lt;tt&amp;gt;CloneHandle()&amp;lt;/tt&amp;gt;: Passes &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;HandleSecurity&amp;lt;/tt&amp;gt;, meaning &amp;lt;tt&amp;gt;HandleAccess_Clone&amp;lt;/tt&amp;gt; must be 0.&lt;br /&gt;
*&amp;lt;tt&amp;gt;CloseHandle()&amp;lt;/tt&amp;gt;: Passes &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;HandleSecurity::pIdentity&amp;lt;/tt&amp;gt;, and the plugin's &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;HandleSecurity::pOwner&amp;lt;/tt/&amp;gt;.  This means that at most, the only restriction can be &amp;lt;tt&amp;gt;HANDLE_RESTRICT_OWNER&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;HandleAccess_Delete&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Usage Examples=&lt;br /&gt;
Here are some examples of Handle usages.&lt;br /&gt;
&lt;br /&gt;
==Basic Handles==&lt;br /&gt;
The most basic use of Handles is to encapsulate a data structure and allow &amp;lt;tt&amp;gt;CloseHandle&amp;lt;/tt&amp;gt; to universally destroy it.  Let's say we want to implement two natives - &amp;lt;tt&amp;gt;CreateFile&amp;lt;/tt&amp;gt; for creating an empty file, and &amp;lt;tt&amp;gt;WriteLine&amp;lt;/tt&amp;gt; for writing a line to this file.  How could we implement this using the Handle system?&lt;br /&gt;
&lt;br /&gt;
After reading this, it is tempting to think, &amp;quot;Why can't we just return the &amp;lt;tt&amp;gt;FILE&amp;lt;/tt&amp;gt; pointer as a &amp;lt;tt&amp;gt;cell_t&amp;lt;/tt&amp;gt;?&amp;quot;  The reason is that a &amp;lt;tt&amp;gt;cell_t&amp;lt;/tt&amp;gt; is guaranteed to be a 32bit integer.  There is no guarantee that a pointer will always be this size, however, and thus casting on future platforms could break.  This problem happened in [[AMX Mod X]] and greatly restricted flexibility.  &lt;br /&gt;
&lt;br /&gt;
===Creating the type===&lt;br /&gt;
First, we have to create the type and its Dispatch interface.&lt;br /&gt;
&amp;lt;cpp&amp;gt;HandleType_t g_FileType = 0;	/* Holds the HandleType ID */&lt;br /&gt;
&lt;br /&gt;
class FileTypeHandler : public IHandleTypeDispatch&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
	void OnHandleDestroy(HandleType_t type, void *object)&lt;br /&gt;
	{&lt;br /&gt;
		/* :TODO: implement this */&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* Create an instance of the handler */&lt;br /&gt;
FileTypeHandler g_FileTypeHandler;&lt;br /&gt;
&lt;br /&gt;
Initialize()&lt;br /&gt;
{&lt;br /&gt;
	/* Register the type with default security permissions */&lt;br /&gt;
	g_FileType = g_pHandleSys-&amp;gt;CreateType(&amp;quot;File&amp;quot;, &lt;br /&gt;
		&amp;amp;g_FileTypeHandler, &lt;br /&gt;
		0, &lt;br /&gt;
		NULL, &lt;br /&gt;
		NULL, &lt;br /&gt;
		myself-&amp;gt;GetIdentity(), &lt;br /&gt;
		NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Shutdown()&lt;br /&gt;
{&lt;br /&gt;
	/* Remove the type on shutdown */&lt;br /&gt;
	g_pHandleSys-&amp;gt;RemoveType(g_FileType, myself-&amp;gt;GetIdentity());&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creating Handles===&lt;br /&gt;
Creating the Handles is fairly easy once we have a valid pointer to stuff in it.&lt;br /&gt;
&amp;lt;cpp&amp;gt;/* native CreateFile(const String:file[]) */&lt;br /&gt;
static cell_t sm_CreateFile(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	char path[PLATFORM_MAX_PATH];&lt;br /&gt;
	char *filename;&lt;br /&gt;
&lt;br /&gt;
	/* Get the filename */&lt;br /&gt;
	pContext-&amp;gt;LocalToString(params[1], &amp;amp;filename);&lt;br /&gt;
	/* Build a full path */&lt;br /&gt;
	g_pSM-&amp;gt;BuildPath(Path_SM, path, sizeof(path), &amp;quot;%s&amp;quot;, filename);&lt;br /&gt;
	&lt;br /&gt;
	/* Open for writing */&lt;br /&gt;
	FILE *fp = fopen(path, &amp;quot;wt&amp;quot;);&lt;br /&gt;
	if (!fp)&lt;br /&gt;
	{&lt;br /&gt;
		return BAD_HANDLE;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Create the Handle with our type, the FILE pointer, the plugin's identity, and our identity */&lt;br /&gt;
	return g_pHandleSys-&amp;gt;CreateHandle(g_FileType, &lt;br /&gt;
		fp, &lt;br /&gt;
		pContext-&amp;gt;GetIdentity(), &lt;br /&gt;
		myself-&amp;gt;GetIdentity(), &lt;br /&gt;
		NULL);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Reading/Checking Handles===&lt;br /&gt;
Handles aren't very useful unless you have natives to use them.  Let's say we want to write lines of text to our File type.&lt;br /&gt;
&amp;lt;cpp&amp;gt;/* native bool WriteLine(Handle hndl, const char[] line); */&lt;br /&gt;
static cell_t sm_WriteLine(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	Handle_t hndl = static_cast&amp;lt;Handle_t&amp;gt;(params[1]);&lt;br /&gt;
	HandleError err;&lt;br /&gt;
	HandleSecurity sec;&lt;br /&gt;
&lt;br /&gt;
	/* Build our security descriptor */&lt;br /&gt;
	sec.pOwner = nullptr;	/* Not needed, owner access is not checked */&lt;br /&gt;
	sec.pIdentity = myself-&amp;gt;GetIdentity();	/* But only this extension can read */&lt;br /&gt;
&lt;br /&gt;
	/* Attempt to read the given handle as our type, using our security info.&lt;br /&gt;
	 * Note that we read the pointer directly in with a little cast.&lt;br /&gt;
	 * This type of cast is safe since sizeof(void **) == sizeof(void *) == sizeof(T *) in almost all cases.&lt;br /&gt;
	 */&lt;br /&gt;
	FILE *fp = nullptr;&lt;br /&gt;
	if ((err = g_pHandleSys-&amp;gt;ReadHandle(hndl, g_FileType, &amp;amp;sec, (void **)&amp;amp;fp))&lt;br /&gt;
	     != HandleError_None)&lt;br /&gt;
	{&lt;br /&gt;
		return pContext-&amp;gt;ThrowNativeError(&amp;quot;Invalid file handle %x (error %d)&amp;quot;, hndl, err);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get the text */&lt;br /&gt;
	char *text = nullptr;&lt;br /&gt;
	pContext-&amp;gt;LocalToString(params[2], &amp;amp;text);&lt;br /&gt;
&lt;br /&gt;
	/* Write it */&lt;br /&gt;
	fputs(text, fp);&lt;br /&gt;
&lt;br /&gt;
	return 1;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===CloseHandle Support===&lt;br /&gt;
Lastly, we need to make it so &amp;lt;tt&amp;gt;CloseHandle()&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FreeHandle()&amp;lt;/tt&amp;gt; will close our file pointer when removing the Handle, which we skipped before.&lt;br /&gt;
&amp;lt;cpp&amp;gt;class FileTypeHandler : public IHandleTypeDispatch&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
	void OnHandleDestroy(HandleType_t type, void *object)&lt;br /&gt;
	{&lt;br /&gt;
		fclose( (FILE *)object );&lt;br /&gt;
	}&lt;br /&gt;
};&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Restricting CloseHandle==&lt;br /&gt;
Let's say that, for various reasons, you don't want users to be able to call CloseHandle().  An example of this might be a data type that is non-temporary, or is being called from a forward, and thus should not be touched.  Or, you might have a special deconstructor that takes extra parameters, and thus you need a separate destroy function.&lt;br /&gt;
&lt;br /&gt;
For example, let's create a separate function called &amp;lt;tt&amp;gt;CloseFile&amp;lt;/tt&amp;gt;.  It doesn't do anything particularly special, but we are going to force its usage over CloseHandle().&lt;br /&gt;
&lt;br /&gt;
===New Security Rules===&lt;br /&gt;
&amp;lt;cpp&amp;gt;Initialize()&lt;br /&gt;
{&lt;br /&gt;
	/* Create default access rights */&lt;br /&gt;
	HandleAccess rules;&lt;br /&gt;
	g_pHandleSys-&amp;gt;InitAccessDefaults(NULL, &amp;amp;rules);&lt;br /&gt;
&lt;br /&gt;
	/* Restrict delete to only our identity */&lt;br /&gt;
	rules.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY;&lt;br /&gt;
&lt;br /&gt;
	/* Register the type with our security permissions */&lt;br /&gt;
	g_FileType = g_pHandleSys-&amp;gt;CreateType(&amp;quot;File&amp;quot;, &lt;br /&gt;
			&amp;amp;g_FileTypeHandler, &lt;br /&gt;
			0, &lt;br /&gt;
			NULL, &lt;br /&gt;
			&amp;amp;rules, &lt;br /&gt;
			myself-&amp;gt;GetIdentity(), &lt;br /&gt;
			NULL);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementing the Native===&lt;br /&gt;
&amp;lt;cpp&amp;gt;/* native Closefile(Handle:hndl); */&lt;br /&gt;
static cell_t sm_CloseFile(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	Handle_t hndl = static_cast&amp;lt;Handle_t&amp;gt;(params[1]);&lt;br /&gt;
	HandleError err;&lt;br /&gt;
	HandleSecurity sec;&lt;br /&gt;
&lt;br /&gt;
	/* Build our security descriptor */&lt;br /&gt;
	sec.pOwner = pContext-&amp;gt;GetIdentity();	/* Needed, HANDLE_RESTRICT_OWNER is default */&lt;br /&gt;
	sec.pIdentity = myself-&amp;gt;GetIdentity();	/* But only this extension can read */&lt;br /&gt;
&lt;br /&gt;
	/* Attempt to read the given handle as our type, using our security info.&lt;br /&gt;
	 * Note that we read the pointer directly in with a little cast.&lt;br /&gt;
	 * This type of cast is safe since sizeof(void **) == sizeof(void *) == sizeof(T *) in almost all cases.&lt;br /&gt;
	 */&lt;br /&gt;
	FILE *fp;&lt;br /&gt;
	if ((err = g_pHandleSys-&amp;gt;FreeHandle(hndl, &amp;amp;sec))&lt;br /&gt;
	     != HandleError_None)&lt;br /&gt;
	{&lt;br /&gt;
		return pContext-&amp;gt;ThrowNativeError(&amp;quot;Invalid file handle %x (error %d)&amp;quot;, hndl, err);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 1;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Restricting CloseHandle Per-Handle==&lt;br /&gt;
Taking our above example, it is possible that we might want some Handles to be closed via CloseHandle(), but others not.  Again, this is useful if you wish to pass a Handle as read-only to a plugin, commonly done when using non-temporary structures or Handles used in Forwards.&lt;br /&gt;
&lt;br /&gt;
In this example, we'll create a global instance of our file type, and this instance will be denied access to CloseHandle(), whereas files returned by OpenFile() will not.&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
&amp;lt;cpp&amp;gt;Handle_t g_GlobalFile;&lt;br /&gt;
&lt;br /&gt;
Initialize()&lt;br /&gt;
{&lt;br /&gt;
	/* Register the type with default security permissions */&lt;br /&gt;
	g_FileType = g_pHandleSys-&amp;gt;CreateType(&amp;quot;File&amp;quot;, &lt;br /&gt;
			&amp;amp;g_FileTypeHandler, &lt;br /&gt;
			0, &lt;br /&gt;
			NULL, &lt;br /&gt;
			NULL, &lt;br /&gt;
			myself-&amp;gt;GetIdentity(), &lt;br /&gt;
			NULL);&lt;br /&gt;
&lt;br /&gt;
	/* Create our 'global' file */&lt;br /&gt;
	FILE *fp = tmpfile();&lt;br /&gt;
&lt;br /&gt;
	/* Set up the security descriptor */&lt;br /&gt;
	HandleSecurity sec;&lt;br /&gt;
	sec.pOwner = NULL;		/* No owner for this Handle */&lt;br /&gt;
	sec.pIdentity = myself-&amp;gt;GetIdentity();	/* Only this identity will be allowed */&lt;br /&gt;
&lt;br /&gt;
	/* Set up the access permissions */&lt;br /&gt;
	HandleAccess rules;&lt;br /&gt;
	g_pHandleSys-&amp;gt;InitAccessDefaults(NULL, &amp;amp;rules);&lt;br /&gt;
	rules.access[HandleAccess_Delete] |= HANDLE_RESTRICT_IDENTITY;&lt;br /&gt;
&lt;br /&gt;
	/* Finally, create the Handle with our rules */&lt;br /&gt;
	g_GlobalFile = g_pHandleSys-&amp;gt;CreateHandleEx(g_FileType, fp, &amp;amp;sec, &amp;amp;rules, NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Shutdown()&lt;br /&gt;
{&lt;br /&gt;
	/* Remove our global Handle (not needed, but we do it for clarity */&lt;br /&gt;
	HandleSecurity sec;&lt;br /&gt;
	sec.pOwner = NULL;&lt;br /&gt;
	sec.pIdentity = myself-&amp;gt;GetIdentity();&lt;br /&gt;
&lt;br /&gt;
	g_pHandleSys-&amp;gt;FreeHandle(g_GlobalFile, &amp;amp;sec);&lt;br /&gt;
&lt;br /&gt;
	/* Remove the type on shutdown */&lt;br /&gt;
	g_pHandleSys-&amp;gt;RemoveType(g_FileType, myself-&amp;gt;GetIdentity());&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Development]]&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11330</id>
		<title>Releasing Products</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11330"/>
		<updated>2022-07-24T12:59:29Z</updated>

		<summary type="html">&lt;p&gt;Fyren: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Releasing SourceMod ==&lt;br /&gt;
&lt;br /&gt;
'''''Bold italic''''' values should be replaced as appropriate for the release.&lt;br /&gt;
* General&lt;br /&gt;
** Create a git branch&lt;br /&gt;
** Bump sourcemod/plugins/include/version.inc numbers for manual builds&lt;br /&gt;
* Buildbot&lt;br /&gt;
** Update master.cfg in buildbot buildmaster. Don't forget to push the change to github&lt;br /&gt;
** Force builds on the new dev and stable branches via pushbuild.txt&lt;br /&gt;
* Downloads&lt;br /&gt;
** Run &amp;lt;code&amp;gt;mount -orw /mnt/downloads&amp;lt;/code&amp;gt; on web01&lt;br /&gt;
** Run &amp;lt;code&amp;gt;mkdir /mnt/downloads/smdrop/'''''1.11'''''&amp;lt;/code&amp;gt;, chmod 775 it, fix ownership&lt;br /&gt;
** Run &amp;lt;code&amp;gt;mount -oro /mnt/downloads&amp;lt;/code&amp;gt;&lt;br /&gt;
** Fix sm_commit_log by updating last ~N master builds to be the new stable branch&lt;br /&gt;
** Update &amp;lt;code&amp;gt;~sourcemod/public_html/downloads.php&amp;lt;/code&amp;gt;&lt;br /&gt;
** Add an entry to &amp;lt;code&amp;gt;~sourcemod/web-commit-updater/updater.php&amp;lt;/code&amp;gt; for the new version&lt;br /&gt;
* Gamedata updater (run commands from inside &amp;lt;code&amp;gt;~sourcemod/update&amp;lt;/code&amp;gt;)&lt;br /&gt;
** Clone the new branch into &amp;lt;code&amp;gt;'''''1.11-dev'''''&amp;lt;/code&amp;gt;&lt;br /&gt;
** Create a &amp;lt;code&amp;gt;'''''update-1.11.sh'''''&amp;lt;/code&amp;gt; script for the new version&lt;br /&gt;
** Run &amp;lt;code&amp;gt;php add_version.php --version '''''1.11.0''''' --path '''''1.11-dev'''''&amp;lt;/code&amp;gt;&lt;br /&gt;
** Run &amp;lt;code&amp;gt;php update/add_version.php --version '''''1.12.0''''' --path master&amp;lt;/code&amp;gt;&lt;br /&gt;
** Run &amp;lt;code&amp;gt;./'''''update-1.11.sh'''''&amp;lt;/code&amp;gt;&lt;br /&gt;
** Run &amp;lt;code&amp;gt;./update-master.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
* Web compiler and forum&lt;br /&gt;
** Create a &amp;lt;code&amp;gt;~sourcemod/'''''compiler-1.11'''''&amp;lt;/code&amp;gt; directory, drop spcomp + includes there&lt;br /&gt;
** Change the &amp;lt;code&amp;gt;~sourcemod/compiler&amp;lt;/code&amp;gt; symlink to the new version&lt;br /&gt;
** Update hardcoded version in &amp;lt;code&amp;gt;~sourcemod/public_html/compiler.php&amp;lt;/code&amp;gt; and change the &amp;quot;you can use this to compile plugins for SourceMod '''''1.11''''' or higher&amp;quot; text if necessary&lt;br /&gt;
** Update &amp;lt;code&amp;gt;~sourcemod/public_html/vbcompiler.php&amp;lt;/code&amp;gt;&lt;br /&gt;
** Update forum's newthread.php and editpost.php (search for ccversion). Do this on staging, create a production PR in bitbucket, then pull&lt;br /&gt;
* SP docs&lt;br /&gt;
** Pull and rebuild &amp;lt;code&amp;gt;~sourcemod/scripts/sourcepawn/exp/tools/docparse&amp;lt;/code&amp;gt; if needed&lt;br /&gt;
** &amp;lt;code&amp;gt;git checkout&amp;lt;/code&amp;gt; new branch into &amp;lt;code&amp;gt;~sourcemod/scripts/sourcemod&amp;lt;/code&amp;gt;&lt;br /&gt;
** From &amp;lt;code&amp;gt;~sourcemod/scripts/sourcepawn/exp/docgen/generate/&amp;lt;/code&amp;gt;, run &amp;lt;code&amp;gt;python generate.py&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11329</id>
		<title>Releasing Products</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11329"/>
		<updated>2022-07-24T12:48:43Z</updated>

		<summary type="html">&lt;p&gt;Fyren: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Releasing SourceMod ==&lt;br /&gt;
&lt;br /&gt;
'''''Bold italic''''' values should be replaced as appropriate for the release.&lt;br /&gt;
* General&lt;br /&gt;
** Create a git branch&lt;br /&gt;
** Bump sourcemod/plugins/include/version.inc numbers for manual builds&lt;br /&gt;
* Buildbot&lt;br /&gt;
** Update master.cfg in buildbot buildmaster. Don't forget to push the change to github&lt;br /&gt;
** Force builds on the new dev and stable branches via pushbuild.txt&lt;br /&gt;
* Downloads&lt;br /&gt;
** mount -orw /mnt/downloads on web01&lt;br /&gt;
** mkdir /mnt/downloads/smdrop/'''''1.11''''', chmod 775 it, fix ownership&lt;br /&gt;
** mount -oro /mnt/downloads&lt;br /&gt;
** Fix sm_commit_log by updating last ~N master builds to be the new stable branch&lt;br /&gt;
** Update ~sourcemod/public_html/downloads.php&lt;br /&gt;
** Add an entry to web-commit-updater/updater.php for the new version&lt;br /&gt;
* Gamedata updater&lt;br /&gt;
** Clone the new branch into ~sourcemod/update/'''''1.11-dev'''''&lt;br /&gt;
** Create a ~sourcemod/update/'''''update-1.11.sh''''' script for the new version&lt;br /&gt;
** Run ~sourcemod/update/add_version.php --version '''''1.11.0''''' --path '''''1.11-dev'''''&lt;br /&gt;
** Run ~sourcemod/update/add_version.php --version '''''1.12.0''''' --path master&lt;br /&gt;
** Run ~sourcemod/update/'''''update-1.11.sh''''' and ~sourcemod/update/update-master.sh&lt;br /&gt;
* Web compiler and forum&lt;br /&gt;
** Create a ~sourcemod/'''''compiler-1.11''''' folder, drop spcomp + includes there&lt;br /&gt;
** Change the ~sourcemod/compiler symlink to the new version&lt;br /&gt;
** Update hardcoded version in ~sourcemod/public_html/compiler.php and change the &amp;quot;you can use this to compile plugins for SourceMod '''''1.11''''' or higher&amp;quot; text if necessary&lt;br /&gt;
** Update ~sourcemod/public_html/vbcompiler.php&lt;br /&gt;
** Update forums newthread.php and editpost.php (search for ccversion). Do this on staging, create a production PR in bitbucket, then pull&lt;br /&gt;
* SP docs&lt;br /&gt;
** Rebuild ~sourcemod/scripts/sourcepawn/exp/tools/docparse if needed&lt;br /&gt;
** git checkout new branch in ~sourcemod/scripts/sourcemod, then run generate.py in ~sourcemod/scripts/sourcepawn/exp/docgen/generate&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11328</id>
		<title>Releasing Products</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11328"/>
		<updated>2022-07-24T12:40:33Z</updated>

		<summary type="html">&lt;p&gt;Fyren: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Releasing SourceMod ==&lt;br /&gt;
&lt;br /&gt;
'''''Bold italic''''' values should be replaced as appropriate for the release.&lt;br /&gt;
* General&lt;br /&gt;
** Create a git branch&lt;br /&gt;
** Bump sourcemod/plugins/include/version.inc numbers for manual builds&lt;br /&gt;
* Buildbot&lt;br /&gt;
** Update master.cfg in buildbot buildmaster. Don't forget to push the change to github&lt;br /&gt;
** Force builds on the new dev and stable branches via pushbuild.txt&lt;br /&gt;
* Downloads&lt;br /&gt;
** mount -orw /mnt/downloads on web01&lt;br /&gt;
** mkdir /mnt/downloads/smdrop/'''''1.11''''', chmod 775 it, fix ownership&lt;br /&gt;
** mount -oro /mnt/downloads&lt;br /&gt;
** Fix sm_commit_log by updating last ~N master builds to be the new stable branch&lt;br /&gt;
** Update ~sourcemod/public_html/downloads.php&lt;br /&gt;
** Add an entry to web-commit-updater/updater.php for the new version&lt;br /&gt;
* Gamedata updater&lt;br /&gt;
** Clone the new branch into ~sourcemod/update/'''''1.11-dev'''''&lt;br /&gt;
** Add a ~sourcemod/update/'''''update-1.11.sh''''' script for the new version&lt;br /&gt;
** Run ~sourcemod/update/add_version.php --version '''''1.11.0''''' --path '''''1.11-dev'''''&lt;br /&gt;
** Run ~sourcemod/update/add_version.php --version '''''1.12.0''''' --path master&lt;br /&gt;
* Web compiler and forum&lt;br /&gt;
** Create a ~sourcemod/'''''compiler-1.11''''' folder, drop spcomp + includes there&lt;br /&gt;
** Change the ~sourcemod/compiler symlink to the new version&lt;br /&gt;
** Update hardcoded version in ~sourcemod/public_html/compiler.php and change the &amp;quot;you can use this to compile plugins for SourceMod '''''1.11''''' or higher&amp;quot; text if necessary&lt;br /&gt;
** Update ~sourcemod/public_html/vbcompiler.php&lt;br /&gt;
** Update forums newthread.php and editpost.php (search for ccversion). Do this on staging, create a production PR in bitbucket, then pull&lt;br /&gt;
* SP docs&lt;br /&gt;
** Rebuild ~sourcemod/scripts/sourcepawn/exp/tools/docparse if needed&lt;br /&gt;
** git checkout new branch in ~sourcemod/scripts/sourcemod, then run generate.py in ~sourcemod/scripts/sourcepawn/exp/docgen/generate&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11327</id>
		<title>Releasing Products</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11327"/>
		<updated>2022-07-15T10:00:25Z</updated>

		<summary type="html">&lt;p&gt;Fyren: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Releasing SourceMod ==&lt;br /&gt;
&lt;br /&gt;
'''''Bold italic''''' values should be replaced as appropriate for the release.&lt;br /&gt;
* General&lt;br /&gt;
** Create a git branch&lt;br /&gt;
** Bump sourcemod/plugins/include/version.inc numbers for manual builds&lt;br /&gt;
* Buildbot&lt;br /&gt;
** Update master.cfg in buildbot buildmaster. Don't forget to push the change to github&lt;br /&gt;
** Force builds on the new dev and stable branches via pushbuild.txt&lt;br /&gt;
* Downloads&lt;br /&gt;
** mount -orw /mnt/downloads on web01&lt;br /&gt;
** mkdir /mnt/downloads/smdrop/'''''1.11''''', chmod 775 it, fix ownership&lt;br /&gt;
** mount -oro /mnt/downloads&lt;br /&gt;
** Fix sm_commit_log by updating last ~N master builds to be the new stable branch&lt;br /&gt;
** Update ~sourcemod/public_html/downloads.php&lt;br /&gt;
** Add an entry to web-commit-updater/updater.php for the new version&lt;br /&gt;
* Gamedata updater&lt;br /&gt;
** Clone the new branch into ~sourcemod/update/'''''1.11-dev'''''&lt;br /&gt;
** Add a ~sourcemod/update/'''''update-1.11.sh''''' script for the new version&lt;br /&gt;
** Run ~sourcemod/update/add_version.php --version '''''1.11''''' --path '''''1.11-dev'''''&lt;br /&gt;
* Web compiler and forum&lt;br /&gt;
** Create a ~sourcemod/'''''compiler-1.11''''' folder, drop spcomp + includes there&lt;br /&gt;
** Change the ~sourcemod/compiler symlink to the new version&lt;br /&gt;
** Update hardcoded version in ~sourcemod/public_html/compiler.php and change the &amp;quot;you can use this to compile plugins for SourceMod '''''1.11''''' or higher&amp;quot; text if necessary&lt;br /&gt;
** Update ~sourcemod/public_html/vbcompiler.php&lt;br /&gt;
** Update forums newthread.php and editpost.php (search for ccversion). Do this on staging, create a production PR in bitbucket, then pull&lt;br /&gt;
* SP docs&lt;br /&gt;
** Rebuild ~sourcemod/scripts/sourcepawn/exp/tools/docparse if needed&lt;br /&gt;
** git checkout new branch in ~sourcemod/scripts/sourcemod, then run generate.py in ~sourcemod/scripts/sourcepawn/exp/docgen/generate&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11326</id>
		<title>Releasing Products</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11326"/>
		<updated>2022-07-15T10:00:12Z</updated>

		<summary type="html">&lt;p&gt;Fyren: one more thing&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Releasing SourceMod ==&lt;br /&gt;
&lt;br /&gt;
'''''Bold italic''''' values should be replaced as appropriate for the release.&lt;br /&gt;
* General&lt;br /&gt;
** Create a git branch&lt;br /&gt;
** Bump sourcemod/plugins/include/version.inc numbers for manual builds&lt;br /&gt;
* Buildbot&lt;br /&gt;
** Update master.cfg in buildbot buildmaster. Don't forget to push the change to github&lt;br /&gt;
** Force builds on the new dev and stable branches via pushbuild.txt&lt;br /&gt;
* Downloads&lt;br /&gt;
** mount -orw /mnt/downloads on web01&lt;br /&gt;
** mkdir /mnt/downloads/smdrop/'''''1.11''''', chmod 775 it, fix ownership&lt;br /&gt;
** mount -oro /mnt/downloads&lt;br /&gt;
** Fix sm_commit_log by updating last ~N master builds to be the new stable branch&lt;br /&gt;
** Update ~sourcemod/public_html/downloads.php&lt;br /&gt;
** Add an entry to web-commit-updater/updater.php for the new version&lt;br /&gt;
* Gamedata updater&lt;br /&gt;
** Clone the new branch into ~sourcemod/update/'''''1.11-dev'''''&lt;br /&gt;
** Add a ~sourcemod/update/'''''update-1.11.sh''''' script for the new version&lt;br /&gt;
** Run ~sourcemod/update/add_version.php --version '''''1.11''''' --path '''''1.11-dev'''''&lt;br /&gt;
* Web compiler and forum&lt;br /&gt;
** Create a ~sourcemod/'''''compiler-1.11''''' folder, drop spcomp + includes there&lt;br /&gt;
** Change the ~sourcemod/compiler symlink to the new version&lt;br /&gt;
** Update hardcoded version in ~sourcemod/public_html/compiler.php and change the &amp;quot;you can use this to compile plugins for SourceMod '''''1.10'''' or higher&amp;quot; text if necessary&lt;br /&gt;
** Update ~sourcemod/public_html/vbcompiler.php&lt;br /&gt;
** Update forums newthread.php and editpost.php (search for ccversion). Do this on staging, create a production PR in bitbucket, then pull&lt;br /&gt;
* SP docs&lt;br /&gt;
** Rebuild ~sourcemod/scripts/sourcepawn/exp/tools/docparse if needed&lt;br /&gt;
** git checkout new branch in ~sourcemod/scripts/sourcemod, then run generate.py in ~sourcemod/scripts/sourcepawn/exp/docgen/generate&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11324</id>
		<title>Releasing Products</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11324"/>
		<updated>2022-07-04T05:02:12Z</updated>

		<summary type="html">&lt;p&gt;Fyren: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Releasing SourceMod ==&lt;br /&gt;
&lt;br /&gt;
'''''Bold italic''''' values should be replaced as appropriate for the release.&lt;br /&gt;
* General&lt;br /&gt;
** Create a git branch&lt;br /&gt;
** Bump sourcemod/plugins/include/version.inc numbers for manual builds&lt;br /&gt;
* Buildbot&lt;br /&gt;
** Update master.cfg in buildbot buildmaster. Don't forget to push the change to github&lt;br /&gt;
** Force builds on the new dev and stable branches via pushbuild.txt&lt;br /&gt;
* Downloads&lt;br /&gt;
** mount -orw /mnt/downloads on web01&lt;br /&gt;
** mkdir /mnt/downloads/smdrop/'''''1.11''''', chmod 775 it, fix ownership&lt;br /&gt;
** mount -oro /mnt/downloads&lt;br /&gt;
** Fix sm_commit_log by updating last ~N master builds to be the new stable branch&lt;br /&gt;
** Update ~sourcemod/public_html/downloads.php&lt;br /&gt;
** Add an entry to web-commit-updater/updater.php for the new version&lt;br /&gt;
* Gamedata updater&lt;br /&gt;
** Clone the new branch into ~sourcemod/update/'''''1.11-dev'''''&lt;br /&gt;
** Add a ~sourcemod/update/'''''update-1.11.sh''''' script for the new version&lt;br /&gt;
** Run ~sourcemod/update/add_version.php --version '''''1.11''''' --path '''''1.11-dev'''''&lt;br /&gt;
* Web compiler and forum&lt;br /&gt;
** Create a ~sourcemod/'''''compiler-1.11''''' folder, drop spcomp + includes there&lt;br /&gt;
** Change the ~sourcemod/compiler symlink to the new version&lt;br /&gt;
** Update hardcoded version in ~sourcemod/public_html/compiler.php.&lt;br /&gt;
** Update ~sourcemod/public_html/vbcompiler.php&lt;br /&gt;
** Update forums newthread.php and editpost.php (search for ccversion). Do this on staging, create a production PR in bitbucket, then pull&lt;br /&gt;
* SP docs&lt;br /&gt;
** Rebuild ~sourcemod/scripts/sourcepawn/exp/tools/docparse if needed&lt;br /&gt;
** git checkout new branch in ~sourcemod/scripts/sourcemod, then run generate.py in ~sourcemod/scripts/sourcepawn/exp/docgen/generate&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11323</id>
		<title>Releasing Products</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11323"/>
		<updated>2022-07-03T04:52:09Z</updated>

		<summary type="html">&lt;p&gt;Fyren: reorganize procedure&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Releasing SourceMod ==&lt;br /&gt;
&lt;br /&gt;
'''''Bold italic''''' values should be replaced as appropriate for the release.&lt;br /&gt;
* General&lt;br /&gt;
** Create a git branch&lt;br /&gt;
** Bump sourcemod/plugins/include/version.inc numbers for manual builds&lt;br /&gt;
* Buildbot&lt;br /&gt;
** Update master.cfg in buildbot buildmaster. Don't forget to push the change to github&lt;br /&gt;
** Force builds on the new dev and stable branches via pushbuild.txt&lt;br /&gt;
* Downloads&lt;br /&gt;
** mount -orw /mnt/downloads on web01&lt;br /&gt;
** mkdir /mnt/downloads/smdrop/'''''1.11''''', chmod 775 it, fix ownership&lt;br /&gt;
** mount -oro /mnt/downloads&lt;br /&gt;
** Fix sm_commit_log by updating last ~N master builds to be the new stable branch&lt;br /&gt;
** Update ~sourcemod/public_html/downloads.php&lt;br /&gt;
** Add an entry to web-commit-updater/updater.php for the new version&lt;br /&gt;
* Gamedata updater&lt;br /&gt;
** Clone the new branch into ~sourcemod/update/'''''1.11-dev'''''&lt;br /&gt;
** Add a ~sourcemod/update/'''''update-1.11.sh''''' script for the new version&lt;br /&gt;
** Run ~sourcemod/update/add_version.php --version '''''1.11''''' --path '''''1.11-dev'''''&lt;br /&gt;
* Web compiler and forum&lt;br /&gt;
** Create a ~sourcemod/'''''compiler-1.11''''' folder, drop spcomp + includes there&lt;br /&gt;
** Change the ~sourcemod/compiler symlink to the new version&lt;br /&gt;
** Update hardcoded version in ~sourcemod/public_html/compiler.php.&lt;br /&gt;
** Update ~sourcemod/public_html/vbcompiler.php&lt;br /&gt;
** Update forums newpost.php and editpost.php (search for ccversion). Do this on staging, create a production PR in bitbucket, then pull&lt;br /&gt;
* SP docs&lt;br /&gt;
** Rebuild ~sourcemod/scripts/sourcepawn/exp/tools/docparse if needed&lt;br /&gt;
** git checkout new branch in ~sourcemod/scripts/sourcemod, then run generate.py in ~sourcemod/scripts/sourcepawn/exp/docgen/generate&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11322</id>
		<title>Releasing Products</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11322"/>
		<updated>2022-07-03T03:32:05Z</updated>

		<summary type="html">&lt;p&gt;Fyren: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Releasing SourceMod ==&lt;br /&gt;
&lt;br /&gt;
'''''Bold italic''''' values should be replaced as appropriate for the release.&lt;br /&gt;
&lt;br /&gt;
* Create a git branch&lt;br /&gt;
* Update master.cfg in buildbot buildmaster. Don't forget to push the change to github&lt;br /&gt;
* mount -orw /mnt/downloads on web01&lt;br /&gt;
* mkdir /mnt/downloads/smdrop/'''''1.11''''', chmod 775 it, fix ownership&lt;br /&gt;
* mount -oro /mnt/downloads&lt;br /&gt;
* Fix sm_commit_log by updating last ~N master builds to be the new stable branch&lt;br /&gt;
* Update ~sourcemod/public_html/downloads.php&lt;br /&gt;
* Update ~sourcemod/public_html/vbcompiler.php&lt;br /&gt;
* Update forums newpost.php and editpost.php (search for ccversion). Do this on staging, create a production PR in bitbucket, then pull&lt;br /&gt;
* Create a ~sourcemod/'''''compiler-1.11''''' folder, drop spcomp + includes there&lt;br /&gt;
* Add an entry to web-commit-updater/updater.php for the new version&lt;br /&gt;
* Force builds on the new dev and stable branches via pushbuild.txt&lt;br /&gt;
* Add a ~sourcemod/update/'''''update-1.11.sh''''' script for the new version&lt;br /&gt;
* Clone the new branch into ~sourcemod/update/'''''1.11-dev'''''&lt;br /&gt;
* Run ~sourcemod/update/add_version.php --version '''''1.11''''' --path '''''1.11-dev'''''&lt;br /&gt;
* Change the ~sourcemod/compiler symlink to the new version&lt;br /&gt;
* Update hardcoded verison in ~sourcemod/public_html/compiler.php.&lt;br /&gt;
* git checkout new branch in ~sourcemod/scripts/sourcemod, then run generate.py in ~sourcemod/scripts/sourcepawn/exp/docgen/generate&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11321</id>
		<title>Releasing Products</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11321"/>
		<updated>2022-07-03T03:22:49Z</updated>

		<summary type="html">&lt;p&gt;Fyren: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Releasing SourceMod ==&lt;br /&gt;
&lt;br /&gt;
'''''Bold italic''''' values should be replaced as appropriate for the release.&lt;br /&gt;
&lt;br /&gt;
* Create a git branch&lt;br /&gt;
* Update master.cfg in buildbot buildmaster. Don't forget to push the change to github&lt;br /&gt;
* mount -orw /mnt/downloads on web01&lt;br /&gt;
* mkdir /mnt/downloads/smdrop/'''''1.11''''', chmod 775 it, fix ownership&lt;br /&gt;
* mount -oro /mnt/downloads&lt;br /&gt;
* Fix sm_commit_log by updating last ~N master builds to be the new stable branch&lt;br /&gt;
* Update ~sourcemod/public_html/downloads.php&lt;br /&gt;
* Update ~sourcemod/public_html/vbcompiler.php&lt;br /&gt;
* Update forums newpost.php and editpost.php (search for ccversion). Do this on staging, create a production PR in bitbucket, then pull&lt;br /&gt;
* Create a ~sourcemod/'''''compiler-1.11''''' folder, drop spcomp + includes there&lt;br /&gt;
* Add an entry to web-commit-updater/updater.php for the new version&lt;br /&gt;
* Force builds on the new dev and stable branches via pushbuild.txt&lt;br /&gt;
* Add a ~sourcemod/update/'''''update-1.11.sh''''' script for the new version&lt;br /&gt;
* Clone the new branch into ~sourcemod/update/'''''1.11-dev'''''&lt;br /&gt;
* Run ~sourcemod/update/add_version.php --version '''''1.11''''' --path '''''1.11-dev'''''&lt;br /&gt;
* Change the ~sourcemod/compiler symlink to the new version&lt;br /&gt;
* Update hardcoded verison in ~sourcemod/public_html/compiler.php.&lt;br /&gt;
* git checkout new branch in ~sourcemod/sourcemod, then generate.py in /scripts/sourcepawn/exp/docgen/generate&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11320</id>
		<title>Releasing Products</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11320"/>
		<updated>2022-07-03T03:22:13Z</updated>

		<summary type="html">&lt;p&gt;Fyren: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Releasing SourceMod ==&lt;br /&gt;
&lt;br /&gt;
'''''Bold italic''''' values should be replaced as appropriate for the release.&lt;br /&gt;
&lt;br /&gt;
* Create a git branch&lt;br /&gt;
* Update master.cfg in buildbot buildmaster. Don't forget to push the change to github&lt;br /&gt;
* mount -orw /mnt/downloads on web01&lt;br /&gt;
* mkdir /mnt/downloads/smdrop/'''''1.11''''', chmod 775 it, fix ownership&lt;br /&gt;
* mount -oro /mnt/downloads&lt;br /&gt;
* Fix sm_commit_log by updating last ~N master builds to be the new stable branch&lt;br /&gt;
* Update ~sourcemod/public_html/downloads.php&lt;br /&gt;
* Update ~sourcemod/public_html/vbcompiler.php&lt;br /&gt;
* Update forums newpost.php and editpost.php (search for ccversion). Do this on staging, create a production PR in bitbucket, then pull&lt;br /&gt;
* Create a ~sourcemod/'''''compiler-1.11''''' folder, drop spcomp + includes there&lt;br /&gt;
* Add an entry to web-commit-updater/updater.php for the new version&lt;br /&gt;
* Force builds on the new dev and stable branches via pushbuild.txt&lt;br /&gt;
* Add a ~sourcemod/update/'''''update-1.11.sh''''' script for the new version&lt;br /&gt;
* Clone the new branch into ~sourcemod/update/'''''1.11-dev'''''&lt;br /&gt;
* Run ~sourcemod/update_addversion.php --version '''''1.11''''' --path '''''1.11-dev'''''&lt;br /&gt;
* Change the ~sourcemod/compiler symlink to the new version&lt;br /&gt;
* Update hardcoded verison in ~sourcemod/public_html/compiler.php.&lt;br /&gt;
* git checkout new branch in ~sourcemod/sourcemod, then generate.py in /scripts/sourcepawn/exp/docgen/generate&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11319</id>
		<title>Releasing Products</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11319"/>
		<updated>2022-07-03T03:14:32Z</updated>

		<summary type="html">&lt;p&gt;Fyren: update instructions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Releasing SourceMod ==&lt;br /&gt;
&lt;br /&gt;
'''''Bold italic''''' values should be replaced as appropriate for the release.&lt;br /&gt;
&lt;br /&gt;
* Create a git branch&lt;br /&gt;
* Update master.cfg in buildbot buildmaster. Don't forget to push the change to github&lt;br /&gt;
* mount -orw /mnt/downloads on web01&lt;br /&gt;
* mkdir /mnt/downloads/smdrop/'''''1.11''''', chmod 775 it, fix ownership&lt;br /&gt;
* mount -oro /mnt/downloads&lt;br /&gt;
* Fix sm_commit_log by updating last ~N master builds to be the new stable branch&lt;br /&gt;
* Update ~sourcemod/public_html/downloads.php&lt;br /&gt;
* Update ~sourcemod/public_html/vbcompiler.php&lt;br /&gt;
* Update forums newpost.php and editpost.php (search for ccversion). Do this on staging, create a production PR in bitbucket, then pull&lt;br /&gt;
* Create a ~sourcemod/'''''compiler-1.11''''' folder, drop spcomp + includes there&lt;br /&gt;
* Add an entry to web-commit-updater/updater.php for the new version&lt;br /&gt;
* Force builds on the new dev and stable branches via pushbuild.txt&lt;br /&gt;
* Add a ~sourcemod/update/'''''update-1.11.sh''''' script for the new version&lt;br /&gt;
* Clone the new branch into ~sourcemod/update/'''''1.11-dev'''''&lt;br /&gt;
* Run ~sourcemod/update_addversion.php --version '''''1.11''''' --path '''''1.11-dev''''' (with appropriate values)&lt;br /&gt;
* Change the ~sourcemod/compiler symlink to the new version&lt;br /&gt;
* Update hardcoded verison in ~sourcemod/public_html/compiler.php.&lt;br /&gt;
* git checkout new branch in ~sourcemod/sourcemod, then generate.py in /scripts/sourcepawn/exp/docgen/generate&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11318</id>
		<title>Releasing Products</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=11318"/>
		<updated>2022-07-03T03:05:05Z</updated>

		<summary type="html">&lt;p&gt;Fyren: wiki markup instead of HTML&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Releasing SourceMod ==&lt;br /&gt;
* Create a git branch.&lt;br /&gt;
* Update master.cfg in buildbot buildmaster. Don't forget to push the change to github.&lt;br /&gt;
* mount -orw /mnt/downloads on web01.&lt;br /&gt;
* mkdir /mnt/downloads/smdrop/&amp;lt;new release folder&amp;gt;, chmod 775 it, fix ownership.&lt;br /&gt;
* mount -oro /mnt/downloads.&lt;br /&gt;
* Fix sm_commit_log by updating last ~N master builds to be the new stable branch.&lt;br /&gt;
* Update ~sourcemod downloads.php.&lt;br /&gt;
* Update ~sourcemod vbcompiler.php.&lt;br /&gt;
* Update forums newpost.php and editpost.php (search for ccversion). Do this on staging, create a production PR in bitbucket, then pull.&lt;br /&gt;
* Create a ~sourcemod/compiler-1.&amp;lt;version&amp;gt; folder, drop spcomp + includes there.&lt;br /&gt;
* Add an entry to web-commit-updater/updater.php for the new version.&lt;br /&gt;
* Force builds on the new dev and stable branches via pushbuild.txt.&lt;br /&gt;
* Add a script for the new version in ~sourcemod/update.&lt;br /&gt;
* Change the ~sourcemod/compiler symlink to the new version.&lt;br /&gt;
* Update hardcoded verison in ~sourcemod compiler.php.&lt;br /&gt;
* git checkout new branch in ~sourcemod/sourcemod, then generate.py in /scripts/sourcepawn/exp/docgen/generate&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Scripting_FAQ_(SourceMod)&amp;diff=11272</id>
		<title>Scripting FAQ (SourceMod)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Scripting_FAQ_(SourceMod)&amp;diff=11272"/>
		<updated>2022-03-06T12:33:24Z</updated>

		<summary type="html">&lt;p&gt;Fyren: /* Where can I find all the SourcePawn functions and other information? */ swap IRC link to Discord&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Yak.gif]]&lt;br /&gt;
yak wuz heer&lt;br /&gt;
&lt;br /&gt;
=How do I learn SourcePawn?=&lt;br /&gt;
A good start is on the [[Introduction_to_SourcePawn_1.7]] page, which will teach you the SourcePawn language. Then go through the [[Introduction to SourceMod Plugins]], which will teach you how to write your first plug-in.&lt;br /&gt;
&lt;br /&gt;
=Where can I find all the SourcePawn functions and other information?=&lt;br /&gt;
All SourceMod plug-ins have this line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line instructs the compiler to retrieve the file &amp;lt;tt&amp;gt;sourcemod.inc&amp;lt;/tt&amp;gt; from the &amp;lt;tt&amp;gt;sourcemod/scripting/include&amp;lt;/tt&amp;gt; folder. Every function, variable, and definition can be found in the &amp;lt;tt&amp;gt;.inc&amp;lt;/tt&amp;gt; files inside the &amp;lt;tt&amp;gt;sourcemod/scripting/include&amp;lt;/tt&amp;gt; folder.&lt;br /&gt;
&lt;br /&gt;
But searching through all those files can be quite tedious. Thankfully, the honourable [https://forums.alliedmods.net/member.php?u=9443 Nican] created an API reference viewable on the web, complete with searching and commenting: [https://sm.alliedmods.net/new-api/ https://sm.alliedmods.net/new-api/]&lt;br /&gt;
&lt;br /&gt;
Also, if you are in the AlliedMods Discord server (https://discord.gg/HUc67zN), you can use the &amp;lt;tt&amp;gt;/docs&amp;lt;/tt&amp;gt; command to search the API.&lt;br /&gt;
&lt;br /&gt;
=How do I find the classname of an entity? (e.g., &amp;quot;&amp;lt;tt&amp;gt;weapon_knife&amp;lt;/tt&amp;gt;&amp;quot; or &amp;quot;&amp;lt;tt&amp;gt;prop_physics&amp;lt;/tt&amp;gt;&amp;quot;)=&lt;br /&gt;
The classname of an entity (not to be confused with a netclass such as &amp;lt;tt&amp;gt;CCSPlayer&amp;lt;/tt&amp;gt;) is a unique identifier. It's the most well known of entity names. To find it, use the function [https://sm.alliedmods.net/new-api/entity/GetEdictClassname GetEdictClassname()]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;char classname[128];&lt;br /&gt;
GetEdictClassname(myentity, classname, sizeof(classname));&lt;br /&gt;
&lt;br /&gt;
PrintToServer(&amp;quot;myentity classname: %s&amp;quot;, classname);&lt;br /&gt;
// myentity classname: weapon_knife&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=How do I block regular commands, such as &amp;lt;tt&amp;gt;kill&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;say&amp;lt;/tt&amp;gt;?=&lt;br /&gt;
As of version 1.3, the recommended way to hook and block commands is with [https://sm.alliedmods.net/new-api/console/AddCommandListener AddCommandListener()]. Previously, using [https://sm.alliedmods.net/new-api/console/RegConsoleCmd RegConsoleCmd()] with the command name was the only way to hook commands, but this creates a whole new command for the command dispatch to check every time any command is executed. [https://sm.alliedmods.net/new-api/console/AddCommandListener AddCommandListener()] creates only a lightweight hook, processed only when the specific command is executed.&lt;br /&gt;
&lt;br /&gt;
Here's how to use it to block the &amp;lt;tt&amp;gt;say&amp;lt;/tt&amp;gt; command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
    AddCommandListener(SayCallback, &amp;quot;say&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action SayCallback(int client, const char[] command, int argc)&lt;br /&gt;
{&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=How do I hook +commands, such as &amp;lt;tt&amp;gt;+zoom&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;+attack&amp;lt;/tt&amp;gt;?=&lt;br /&gt;
Unlike regular commands, &amp;lt;tt&amp;gt;+commands&amp;lt;/tt&amp;gt; are handled on the client's computer, then sent to the server in a more compressed fashion. This means [https://sm.alliedmods.net/new-api/console/AddCommandListener AddCommandListener()] cannot be used to hook &amp;lt;tt&amp;gt;+commands&amp;lt;/tt&amp;gt;. As of version 1.3, the recommended solution is to use the global forward [https://sm.alliedmods.net/new-api/sdktools_hooks/OnPlayerRunCmd OnPlayerRunCmd()]. This forward is fired every time a player uses a movement button. To detect or block a &amp;lt;tt&amp;gt;+command&amp;lt;/tt&amp;gt;, you'll first have to find out its proper &amp;lt;tt&amp;gt;IN_&amp;lt;/tt&amp;gt; constant (see &amp;lt;tt&amp;gt;[https://sm.alliedmods.net/new-api/entity_prop_stocks/__raw entity_prop_stocks.inc]&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Here's how to use it to block crouching when attacking:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public Action OnPlayerRunCmd(int client, int &amp;amp;buttons, int &amp;amp;impulse, float vel[3], float angles[3], int &amp;amp;weapon)&lt;br /&gt;
{&lt;br /&gt;
    // Check if the player is attacking (+attack)&lt;br /&gt;
    if ((buttons &amp;amp; IN_ATTACK) == IN_ATTACK)&lt;br /&gt;
    {&lt;br /&gt;
        // If so, block their crouching (+duck)&lt;br /&gt;
        buttons &amp;amp;= ~IN_DUCK;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // We must return Plugin_Continue to let the changes be processed.&lt;br /&gt;
    // Otherwise, we can return Plugin_Handled to block the commands&lt;br /&gt;
    return Plugin_Continue;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=How do I get rid of loose indentation warnings?=&lt;br /&gt;
&amp;lt;pre&amp;gt;myplugin.sp(#) : warning 217: loose indentation&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Loose indentation warnings arise when indentation in your code is inconsistent. This usually means using both tabs and spaces as indentation. However, it can also mean a different amount of spaces or tabs are being used. Therefore, to correct it, use just one type of indentation. Because different editors have different settings for the size of tab stops, it is recommended you use 4 spaces to indent.&lt;br /&gt;
&lt;br /&gt;
Good:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
    int myvar = 5;&lt;br /&gt;
    if (myvar == (2 + 3))&lt;br /&gt;
        PrintToServer(&amp;quot;myvar is %d&amp;quot;, myvar);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bad:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public voidOnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	int myvar = 5;&lt;br /&gt;
    if (myvar == (2 + 3))&lt;br /&gt;
		PrintToServer(&amp;quot;myvar is %d&amp;quot;, myvar);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=How do I get rid of tag mismatch warnings?=&lt;br /&gt;
Though every variable in SourcePawn is one cell (4 bytes), with the exception of strings, there are many different ways to interpret what's inside a cell. To signify a cell's contents, tags are used. The most common are &amp;lt;tt&amp;gt;_&amp;lt;/tt&amp;gt; (the default tag: a vanilla cell. This tag is implied when no other tag is specified.), &amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;bool&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;char&amp;lt;/tt&amp;gt;. See [[Introduction_to_SourcePawn_1.7#Variables_2]] for more information.&lt;br /&gt;
&lt;br /&gt;
Functions wear these tags on their parameters so you can tell what needs to be passed to the function:&lt;br /&gt;
&amp;lt;pawn&amp;gt;native int SetEntPropFloat(int entity, PropType type, const char[] prop, float value, int element)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function calls for '''&amp;lt;tt&amp;gt;entity&amp;lt;/tt&amp;gt;''', a cell with the implied tag '''''&amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;'''''; '''&amp;lt;tt&amp;gt;type&amp;lt;/tt&amp;gt;''', with the developer-defined tag '''''&amp;lt;tt&amp;gt;PropType&amp;lt;/tt&amp;gt;'''''; '''&amp;lt;tt&amp;gt;prop&amp;lt;/tt&amp;gt;''', with the built-in tag '''''&amp;lt;tt&amp;gt;char&amp;lt;/tt&amp;gt;'''''; and '''&amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;''', with the built-in tag '''''&amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt;'''''.&lt;br /&gt;
To call this function, then, you must pass values with the specified tags. For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;SetEntPropFloat(1234, Prop_Send, &amp;quot;m_fNumber&amp;quot;, 1.0);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This calls the function correctly: &amp;lt;tt&amp;gt;1234&amp;lt;/tt&amp;gt; is a regular cell ('''''&amp;lt;tt&amp;gt;_&amp;lt;/tt&amp;gt;'''''), &amp;lt;tt&amp;gt;Prop_Send&amp;lt;/tt&amp;gt; is a variable defined in the enum '''''&amp;lt;tt&amp;gt;PropType&amp;lt;/tt&amp;gt;''''' in [https://sm.alliedmods.net/new-api/entity/__raw entity.inc], &amp;lt;tt&amp;gt;&amp;quot;m_fNumber&amp;quot;&amp;lt;/tt&amp;gt; is a '''''&amp;lt;tt&amp;gt;char&amp;lt;/tt&amp;gt;''''', and &amp;lt;tt&amp;gt;1.0&amp;lt;/tt&amp;gt; is a '''''&amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt;'''''. For a nonexample:&lt;br /&gt;
&amp;lt;pawn&amp;gt;SetEntPropFloat(1234.0, 1, &amp;quot;m_fNumber&amp;quot;, 1337);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is incorrect! &amp;lt;tt&amp;gt;1234.0&amp;lt;/tt&amp;gt; is a '''''&amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt;''''' that should be a regular cell ('''''&amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;'''''); &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; is a regular cell ('''''&amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;''''') that should be a '''''&amp;lt;tt&amp;gt;PropType&amp;lt;/tt&amp;gt;'''''; and &amp;lt;tt&amp;gt;1337&amp;lt;/tt&amp;gt; is a regular cell ('''''&amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;''''') that should be a '''''&amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt;'''''. This call will generate a tag mismatch warning. To correct it, simply use a value with the correct tag. Most of the time, tags that are not built-in (such as '''''&amp;lt;tt&amp;gt;PropType&amp;lt;/tt&amp;gt;''''') can be found in the same file where a function uses them (you can find '''''&amp;lt;tt&amp;gt;PropType&amp;lt;/tt&amp;gt;''''' in [https://sm.alliedmods.net/new-api/entity/__raw entity.inc]).&lt;br /&gt;
&lt;br /&gt;
=How do I add color to my messages?=&lt;br /&gt;
Though the actual colors will vary depending on the mod, you can add color to any chat message using the characters &amp;lt;tt&amp;gt;0x01&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;0x08&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;PrintToChatAll (&amp;quot;\x01 1 .. \x02 2 .. \x03 3 .. \x04 4 .. \x05 5 .. \x06 6 .. \x07 7 .. \x08 8&amp;quot;);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example output from Left 4 Dead:&lt;br /&gt;
&lt;br /&gt;
[[Image:Left_4_Dead_Colors.png]]&lt;br /&gt;
&lt;br /&gt;
With a little experimenting, you can learn the colors for a mod. However, the meaning behind the colors is generally as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt style=&amp;quot;color: blue;&amp;quot;&amp;gt;0x01&amp;lt;/tt&amp;gt; = Normal color&lt;br /&gt;
* &amp;lt;tt style=&amp;quot;color: blue;&amp;quot;&amp;gt;0x02&amp;lt;/tt&amp;gt; = Use team color to the end of a player's name. When used, it can be the only color used, and it must be at the start of the message.&lt;br /&gt;
* &amp;lt;tt style=&amp;quot;color: blue;&amp;quot;&amp;gt;0x03&amp;lt;/tt&amp;gt; = Team color&lt;br /&gt;
* &amp;lt;tt style=&amp;quot;color: blue;&amp;quot;&amp;gt;0x04&amp;lt;/tt&amp;gt; = Location color&lt;br /&gt;
&lt;br /&gt;
This data comes from Counter-Strike: Source.&lt;br /&gt;
&lt;br /&gt;
For CS:GO, here are some colors:&lt;br /&gt;
&amp;lt;pawn&amp;gt;PrintToChat(&amp;quot;\x011\x022\x033\x044\x055\x066\x077\x088\x099\x0AA\x0BB\x0CC\x0DD\x0EE\x0FF&amp;quot;);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unfortunately, to use players' team colors, you must use UserMessages, because there is no way for the current SourceMod functions to know which team color to use. Here's an example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;Handle hBf;&lt;br /&gt;
hBf = StartMessageOne(&amp;quot;SayText2&amp;quot;, player_to); // To send the message to all players, use StartMessageAll(&amp;quot;SayText2&amp;quot;);&lt;br /&gt;
if (hBf != null)&lt;br /&gt;
{&lt;br /&gt;
    BfWriteByte(hBf, player_from); &lt;br /&gt;
    BfWriteByte(hBf, 0); &lt;br /&gt;
    BfWriteString(hBf, &amp;quot;&amp;lt;\x03player_from team color\x01&amp;gt; My message&amp;quot;);&lt;br /&gt;
    EndMessage();&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;player_to&amp;lt;/tt&amp;gt; is the client index to send the message to (or use [https://sm.alliedmods.net/new-api/usermessages/StartMessageAll StartMessageAll()] instead of [https://sm.alliedmods.net/new-api/usermessages/StartMessageOne StartMessageOne()] to send the message to all players). &amp;lt;tt&amp;gt;player_from&amp;lt;/tt&amp;gt; is the client index of the player whose team color will be utilized in the message. The message will now look like this (assuming &amp;lt;tt&amp;gt;player_from&amp;lt;/tt&amp;gt; is on the RED team):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#AA0&amp;quot;&amp;gt;&amp;amp;lt;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#F00&amp;quot;&amp;gt;player_from team color&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#AA0&amp;quot;&amp;gt;&amp;amp;gt; My message&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There's another catch, however: this is only known to work in CS:S and TF2. For other mods, your mileage may vary.&lt;br /&gt;
&lt;br /&gt;
Additionally, CS:S, TF2, HL2:DM, and DoD:S all support RGB(A) hex values in chat messages with &amp;lt;tt style=&amp;quot;color: blue;&amp;quot;&amp;gt;0x07&amp;lt;/tt&amp;gt; and &amp;lt;tt style=&amp;quot;color: blue;&amp;quot;&amp;gt;0x08&amp;lt;/tt&amp;gt;, followed by a 6- or 8- char hex value (e.g., &amp;lt;tt&amp;gt;\x07ABCDEF&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;\x0801234567&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==Color Libraries==&lt;br /&gt;
There are a few libraries that can handle colors for you, so you don't have to muck with UserMessages:&lt;br /&gt;
&lt;br /&gt;
===exvel's Colors===&lt;br /&gt;
This is a simple include file, allowing easy control over chat coloring. You can grab it [http://forums.alliedmods.net/showthread.php?t=96831 on the forums].  Instead of hex codes, colors are denoted with tags, such as &amp;lt;span style=&amp;quot;color: #AA0;&amp;quot;&amp;gt;&amp;lt;tt&amp;gt;{default}&amp;lt;/tt&amp;gt;&amp;lt;/span&amp;gt;, &amp;lt;span style=&amp;quot;color: #0F0;&amp;quot;&amp;gt;&amp;lt;tt&amp;gt;{green}&amp;lt;/tt&amp;gt;&amp;lt;/span&amp;gt;, or &amp;lt;span style=&amp;quot;color: #00F;&amp;quot;&amp;gt;&amp;lt;tt&amp;gt;{blue}&amp;lt;/tt&amp;gt;&amp;lt;/span&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Here's some example usage. Note that this code assumes client 1 is in game and on the &amp;lt;span style=&amp;quot;color: #00F;&amp;quot;&amp;gt;BLU&amp;lt;/span&amp;gt; team:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;colors&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
    CPrintToChatAll(&amp;quot;{green}Hello {red}World! {default}Test 1 concluded.&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    int client_on_blu_team = 1;&lt;br /&gt;
    CPrintToChatAllEx(client_on_blu_team, &amp;quot;{teamcolor}BLU team {default}says {green}hi!&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: #0F0;&amp;quot;&amp;gt;Hello &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #F00;&amp;quot;&amp;gt;World! &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #AA0;&amp;quot;&amp;gt;Test 1 concluded.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: #00F;&amp;quot;&amp;gt;BLU team &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #AA0;&amp;quot;&amp;gt;says &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #0F0;&amp;quot;&amp;gt;hi!&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that to use a team color, there needs to be at least one player on that team. Otherwise, it will default to &amp;lt;span style=&amp;quot;color: #0F0;&amp;quot;&amp;gt;&amp;lt;tt&amp;gt;{green}&amp;lt;/tt&amp;gt;&amp;lt;/span&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===SMLib===&lt;br /&gt;
[http://forums.alliedmods.net/showthread.php?p=1398699 SMLib] is a huge collection of stock functions to keep plug-in developers from reinventing the wheel. It includes a [http://forums.alliedmods.net/showthread.php?p=1398702#post1398702 colors API] very similar to [[#exvel's Colors|exvel's]]. The benefits of SMLib are it supports shorthand color names, such as &amp;lt;span style=&amp;quot;color: #AA0;&amp;quot;&amp;gt;&amp;lt;tt&amp;gt;{N}&amp;lt;/tt&amp;gt;&amp;lt;/span&amp;gt; and &amp;lt;span style=&amp;quot;color: #0F0;&amp;quot;&amp;gt;&amp;lt;tt&amp;gt;{G}&amp;lt;/tt&amp;gt;&amp;lt;/span&amp;gt;, and all colors are supported in its &amp;lt;tt&amp;gt;Client_PrintToChat()&amp;lt;/tt&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
Here's how to print the same thing as the above example with SMLib. Note that this code also assumes client 1 is in game and on the &amp;lt;span style=&amp;quot;color: #00F;&amp;quot;&amp;gt;BLU&amp;lt;/span&amp;gt; team:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;smlib&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
    Client_PrintToChatAll(&amp;quot;{G}Hello {R}World! {N}Test 1 concluded.&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    int client_on_blu_team = 1;&lt;br /&gt;
    Client_PrintToChatAll(client_on_blu_team, &amp;quot;{T}BLU team {N}says {G}hi!&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: #0F0;&amp;quot;&amp;gt;Hello &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #F00;&amp;quot;&amp;gt;World! &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #AA0;&amp;quot;&amp;gt;Test 1 concluded.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: #00F;&amp;quot;&amp;gt;BLU team &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #AA0;&amp;quot;&amp;gt;says &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #0F0;&amp;quot;&amp;gt;hi!&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Why do I get an &amp;quot;unknown symbol&amp;quot; error when using an SDKTools native?=&lt;br /&gt;
None of SourceMod's or SDKTools's functions are built into SourcePawn. Therefore, every time you use one of their functions, SourcePawn needs to know how to call the function. Normally, this is done using includes. Just like you would #include &amp;lt;sourcemod&amp;gt; to use SourceMod's functions, you need to:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;sdktools&amp;gt;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
to use an SDKTools native.&lt;br /&gt;
&lt;br /&gt;
=Why is Source telling me my command is an &amp;quot;Unknown command&amp;quot;?=&lt;br /&gt;
This is because you're not returning &amp;lt;tt&amp;gt;Plugin_Handled&amp;lt;/tt&amp;gt; in your callback. If you don't, SourceMod believes you didn't want the Source Engine to know the command was registered, and it handles it so.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public Action MyCommand(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
    // Do something...&lt;br /&gt;
    &lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Pawn_Tutorial&amp;diff=10290</id>
		<title>Pawn Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Pawn_Tutorial&amp;diff=10290"/>
		<updated>2017-06-03T18:30:22Z</updated>

		<summary type="html">&lt;p&gt;Fyren: /* Switch Statements */ ranges are not supported for switch cases&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{qnotice|This guide is rather hardcoded to [[AMX Mod X]].  It needs to be mode generic.}}&lt;br /&gt;
&lt;br /&gt;
This guide is designed to give you a more in-depth overview of the basics of programming in [[Pawn]].&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
Pawn is an embeddable, (almost) typeless, easy to use scripting language that is compiled for a virtual machine. [[AMX Mod X]] uses Pawn to route scripting functions to the Half-Life engine, using the Pawn [[Virtual Machine]] and [[Metamod]] ([[Pawn]] is written in C, Metamod is written in C++). While you write Pawn scripts in a text editor, the scripts must be compiled with a &amp;quot;Compiler&amp;quot;, which produces a binary for AMX Mod X. The AMX Mod X team distributes a specially modified Pawn compiler.&lt;br /&gt;
&lt;br /&gt;
Programming scripts in Pawn is relatively easy, and does not have concepts in other languages that are unnecessary for general use, such as pointers, vectors, structs, classes, allocation, et cetera. &lt;br /&gt;
&lt;br /&gt;
==Language Paradigms==&lt;br /&gt;
Pawn was originally named &amp;quot;[[Small]]&amp;quot; to emphasize the size of the language specification.  The language sacrifices many features found in modern languages to achieve simplicity and speed, which are required for embedded uses.&lt;br /&gt;
*No typing&lt;br /&gt;
**Pawn only has one data type -- the &amp;quot;[[Cell_(Pawn)|cell]]&amp;quot;.  It is the size of the processor's integral pointer (4 bytes for 32bit processor, 8 bytes for 64bit processors).  This has two major implications - Pawn bytecode is processor specific, and pointers can fit inside a cell.&lt;br /&gt;
**[[Tagging_(Pawn)|Tagging]] - Pawn lets you create weakly statically typed &amp;quot;tags&amp;quot;, which can be associated with variables for primitive operator overloading.  For example, Pawn has no concept of floating point numbers (only integers).  Instead, operators are overloaded with the Float: tag to redirect computation to new functions.  Tag-checking is only enforced as a warning.  If you're using SourcePawn (for SourceMod), there is actually a second type: String.  In a String, letters are stored as separate bytes... essentially having 4 characters stored in every cell.&lt;br /&gt;
**Since Pawn only has one datatype, it does not support structs, records, objects, or anything else.&lt;br /&gt;
**Pawn &amp;lt;i&amp;gt;does&amp;lt;/i&amp;gt; support arrays of cells, which leads to C-style arrays for strings.&lt;br /&gt;
*No garbage collection&lt;br /&gt;
**Pawn has no &amp;quot;heap&amp;quot; allocation built-in.  All variables are stored on the stack or in the data section.  Therefore, no garbage collection is necessary and memory leaks are not possible from the language specification alone.&lt;br /&gt;
*Procedural&lt;br /&gt;
**Pawn is entirely comprised of single, non-nested subroutines.  There are no lambda functions, member functions, constructors, et cetera.  Functions can either be internal (within the script) or public (exposed to the VM by name, like C's &amp;quot;extern&amp;quot;).&lt;br /&gt;
*No thread-safety&lt;br /&gt;
**Pawn is targetted toward single-thread instances.&lt;br /&gt;
&lt;br /&gt;
==Implementation Features==&lt;br /&gt;
*Cross-platform compatible compiler, which outputs bytecode and debug browsing information.&lt;br /&gt;
*Cross-platform compatible Virtual Machine (VM), with support for debug browsing, halting/stopping execution, and interacting with scripts from C/C++ libraries.&lt;br /&gt;
*IA32 JIT Compiler for vastly increasing script execution time.&lt;br /&gt;
&lt;br /&gt;
Because the footprints of the VM and JIT are so small, Pawn is ideal inside games which need a simple and highly fast event system, embedded devices or applications, and realtime systems.&lt;br /&gt;
&lt;br /&gt;
==License==&lt;br /&gt;
Pawn is licensed under the [[ZLib/libpng_License]] license.&lt;br /&gt;
&lt;br /&gt;
=Variables=&lt;br /&gt;
Variables are simple structures for holding data throughout a period of time in your script.&lt;br /&gt;
&lt;br /&gt;
==Types==&lt;br /&gt;
Small has just three data types for declaring variables. The default variable type is a regular whole number, or integer. A variable name, for backwards compatibility, should be 19 characters or less, and MUST start with a letter. It can contain the symbols A-Z, a-z, 0-9, and the underscore (&amp;quot;_&amp;quot;). It is important to note that variable names are case sensitive - &amp;quot;myvar&amp;quot;, &amp;quot;MyVaR&amp;quot;, and &amp;quot;MYVAR&amp;quot; are three separate symbols. &lt;br /&gt;
&lt;br /&gt;
===Integers===&lt;br /&gt;
The simplest data type in Pawn is an &amp;quot;integer&amp;quot;.  Integers are whole numbers.  To declare a new integer variable, use the &amp;quot;new&amp;quot; operator like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new a            //Declare empty variable &amp;quot;a&amp;quot;&lt;br /&gt;
new b=5          //Declare variable &amp;quot;b&amp;quot; and set it to 5.&lt;br /&gt;
new c=5.0        //This is invalid, technically not a whole number!&lt;br /&gt;
new d=&amp;quot;hello&amp;quot;    //&amp;quot;hello&amp;quot; is not a number either, this is invalid.&lt;br /&gt;
&lt;br /&gt;
//You can also declare multiple variables on one line:&lt;br /&gt;
new e,f,g,h&lt;br /&gt;
new x=7, y=3&lt;br /&gt;
new z = 1_000_000 // Pawn supports numbers like this. So big values are easier to read.&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Floats===&lt;br /&gt;
You can also declare a variable as a &amp;quot;Float&amp;quot;, which means it can store numbers with decimal places. These are called &amp;quot;floating point&amp;quot; numbers:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new Float:a            //Declare empty floating point variable &amp;quot;a&amp;quot;&lt;br /&gt;
new Float:b=5.3        //This will declare a new variable &amp;quot;b&amp;quot; and assign 5.3 to it.&lt;br /&gt;
new Float:c=5          //This is valid, but the compiler will give you a warning.&lt;br /&gt;
new Float:d=&amp;quot;hello&amp;quot;    //This is invalid, &amp;quot;hello&amp;quot; is not a decimal number.&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also do the following:&lt;br /&gt;
&amp;lt;pawn&amp;gt;//float(n) is a function that takes a number n and makes it a&lt;br /&gt;
// floating point number.&lt;br /&gt;
new Float:var = float(5)&lt;br /&gt;
new Float:var2 = 5.0     &lt;br /&gt;
new Float:var3 = 1.0*5&lt;br /&gt;
new var4 = floatround(5.0)     &lt;br /&gt;
//Note: floatround(n) is a function that takes a number n and rounds it to a whole number.&lt;br /&gt;
//  this makes the assignment to a regular integer variable valid.&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note - Spacing does generally not matter, as long as the compiler can tell symbols apart from each other. If your spacing is REALLY bad, you will get errors or maybe even warnings. For example, &amp;quot;new var = 5&amp;quot; and &amp;quot;new var=5&amp;quot; are the same, but &amp;quot;newvar=5&amp;quot; is totally wrong.&lt;br /&gt;
&lt;br /&gt;
===Booleans===&lt;br /&gt;
The last variable type is &amp;quot;boolean&amp;quot;. It is very simple - it is either &amp;quot;true&amp;quot;, or &amp;quot;false&amp;quot;. Both &amp;quot;true&amp;quot; and &amp;quot;false&amp;quot; are predefined data structures.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new bool:IsItOn        //Declares a new variable &amp;quot;IsItOn&amp;quot; which is automatically false&lt;br /&gt;
new bool:xyz=true      //Declares a new variable &amp;quot;xyz&amp;quot; set to true&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Arrays=&lt;br /&gt;
&lt;br /&gt;
Pawn features basic &amp;quot;arrays&amp;quot;. An array is a simple type of aggregate data. This means you can store multiple values in one variable! An array follows the same rules as a regular variable, and it has the same types. It simply can contain multiple values. You define an array with brackets, and how many values it can hold. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//This will declare a variable called &amp;quot;Players&amp;quot; which holds 32 numbers. &lt;br /&gt;
new Players[32]&lt;br /&gt;
&lt;br /&gt;
//You can now store values in any of the 32 &amp;quot;slots&amp;quot; this array has.  &lt;br /&gt;
// The slots are numbered from 0 to n-1, or in this case, 0 to 31.&lt;br /&gt;
//Every slot starts off as 0.&lt;br /&gt;
&lt;br /&gt;
//Set slot 0 to 5&lt;br /&gt;
Players[0] = 5&lt;br /&gt;
&lt;br /&gt;
//Set slot 1 to whatever is in slot 0, in this case, the number 5&lt;br /&gt;
Players[1] = Players[0]&lt;br /&gt;
&lt;br /&gt;
//This is invalid! &lt;br /&gt;
//Although there are 32 slots, they are numbered from 0 to 31.&lt;br /&gt;
//Doing this results in AMX Native Error 4 - AMX_ERR_BOUNDS&lt;br /&gt;
// or, it simply won't compile!&lt;br /&gt;
Players[32] = 15&lt;br /&gt;
&lt;br /&gt;
//This is also totally invalid           &lt;br /&gt;
Players[-1] = 6&lt;br /&gt;
&lt;br /&gt;
new a = 3&lt;br /&gt;
//This is also totally invalid.  &lt;br /&gt;
//a must be a constant number.&lt;br /&gt;
new BadArray[a]&lt;br /&gt;
&lt;br /&gt;
//So this is valid:&lt;br /&gt;
const b = 3&lt;br /&gt;
new GoodArray[b]&lt;br /&gt;
&lt;br /&gt;
//You can also use Compiler Directives (See last section)&lt;br /&gt;
&lt;br /&gt;
#define ARRAY_SIZE 3&lt;br /&gt;
new Array[ARRAY_SIZE]&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Arrays can also be declared with groups of data default, such as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new Numbers[4] = {0,1,2,3}&lt;br /&gt;
//Note: it is important that you make sure the amount of numbers&lt;br /&gt;
// you pass and the size of the array match&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can also use any data type with arrays:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//Array of floating points:&lt;br /&gt;
new Float:Numbers[4] = {0.0, 1.2, 2.4, 3.8}&lt;br /&gt;
//Array of booleans.  Note this sets every slot to true.&lt;br /&gt;
new bool:playerHasGun[33] = {true, ...}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Strings=&lt;br /&gt;
&lt;br /&gt;
You have probably noticed that an important data type is missing - characters (letters and symbols). These are called &amp;quot;strings&amp;quot;, and in Pawn, they are technically numbers! A string   is an array of numbers that translate to ASCII (character) symbols. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//This will declare a number array &amp;quot;myString&amp;quot; that contains the data &amp;quot;Hello&amp;quot;.  &lt;br /&gt;
//It will have 6 slots, because there are 5 characters.  &lt;br /&gt;
//The last slot is reserved for the number 0, which tells the Pawn engine that it is a string.&lt;br /&gt;
new myString[] = &amp;quot;Hello&amp;quot;&lt;br /&gt;
// If you're using SourcePawn, do this instead:&lt;br /&gt;
new String:myString[] = &amp;quot;Hello&amp;quot;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: anything in between /* and */ is also a comment.  You cannot use /* */ inside a /* */.  The following set of commands achieves the same purpose, however, it is longer and not recommended.  This works because each character of the string &amp;quot;Hello&amp;quot; is stored in a slot in the array.&lt;br /&gt;
&amp;lt;pawn&amp;gt;new myString[6]&lt;br /&gt;
myString[0] = 'H'&lt;br /&gt;
myString[1] = 'e'&lt;br /&gt;
myString[2] = 'l'&lt;br /&gt;
myString[3] = 'l'&lt;br /&gt;
myString[4] = 'o'&lt;br /&gt;
myString[5] = 0&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{qnotice|Arrays that are meant to be strings must end in a 0, or the null character.  This is so you know where the string ends.}}&lt;br /&gt;
&lt;br /&gt;
You CANNOT do this! While it may compile, it is highly dangerous as it might cause overflow errors:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new myString[6]&lt;br /&gt;
myString = &amp;quot;Hello&amp;quot;     //INVALID!&lt;br /&gt;
myString[0] = &amp;quot;Hello&amp;quot;  //INVALID!&lt;br /&gt;
//To add data to a string, you can do this:&lt;br /&gt;
new goodString[7]&lt;br /&gt;
copy(goodString, 6, &amp;quot;Hello&amp;quot;)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{qnotice|In SourcePawn, copy was renamed to strcopy and avoids the issue with copy noted below.}}&lt;br /&gt;
&lt;br /&gt;
Note that we copied 6 cells of the array into an array that can hold 7.  If we were to copy 7 bytes into this array, copy() could potentially copy an extra byte for the Null character, overflowing the array.  This is called a [[buffer overflow]] and must be carefully avoided.&lt;br /&gt;
&lt;br /&gt;
More examples:&lt;br /&gt;
&amp;lt;pawn&amp;gt;//Copy is a function that takes three parameters:&lt;br /&gt;
copy(destination[], length, source[])&lt;br /&gt;
//It copies the string inside the source array and places &lt;br /&gt;
// it into the destination array, but only copies up to length characters.&lt;br /&gt;
&lt;br /&gt;
//Lastly, to prove that a string is really an array of numbers, this is completely valid:&lt;br /&gt;
new weird[6]&lt;br /&gt;
weird[0] = 68&lt;br /&gt;
weird[1] = 65&lt;br /&gt;
weird[2] = 73&lt;br /&gt;
weird[3] = 86&lt;br /&gt;
weird[4] = 68&lt;br /&gt;
weird[5] = 0&lt;br /&gt;
//This will set the variable &amp;quot;weird&amp;quot; to the string &amp;quot;DAVID&amp;quot;.&lt;br /&gt;
//To see how letters and symbols translate into numbers, visit www.asciitable.com &amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Functions=&lt;br /&gt;
&lt;br /&gt;
Pawn allows you to define your own functions. This comes in handy for removing code that is used in multiple places. Note that all functions should return a value. To do this, you use the &amp;quot;return&amp;quot; command, which immediately halts the function and returns the value of the expression passed to it. No code is executed in a function once the return is found. Here are some examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//This is a function that takes no parameters and returns 1.&lt;br /&gt;
//When activated, it uses the (non-existant) print function.&lt;br /&gt;
show()&lt;br /&gt;
{&lt;br /&gt;
   print(&amp;quot;Hello!&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
   return 1   //End, return 1&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Activate like this:&lt;br /&gt;
show()&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also declare functions to take parameters.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//This declares a function called &amp;quot;add_two_numbers&amp;quot;, which takes two numbers and returns the sum.&lt;br /&gt;
add_two_numbers(first, second)&lt;br /&gt;
{&lt;br /&gt;
   new sum = first + second&lt;br /&gt;
&lt;br /&gt;
   return sum  //Return the sum&lt;br /&gt;
}&lt;br /&gt;
//Then you can use your new function like this:&lt;br /&gt;
&lt;br /&gt;
new a,b&lt;br /&gt;
a = 5&lt;br /&gt;
b = 12&lt;br /&gt;
new c = add_two_numbers(a,b)&lt;br /&gt;
//c will now be equal to 17.&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You are not limited by what types of data parameters can accept. When you give parameters to a function, it is called &amp;quot;passing&amp;quot;. You can pass either data or a variable to a function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//This defines a new function called &amp;quot;add_two_floats&amp;quot;&lt;br /&gt;
// which takes two floating points and returns the sum&lt;br /&gt;
Float:add_two_floats(Float:first, Float:second)&lt;br /&gt;
{&lt;br /&gt;
   new Float:sum = first + second&lt;br /&gt;
&lt;br /&gt;
   return sum&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
new Float:a&lt;br /&gt;
new Float:b&lt;br /&gt;
a = 5.0&lt;br /&gt;
b = 6.3&lt;br /&gt;
new Float:c&lt;br /&gt;
c = add_two_floats( a+b )&lt;br /&gt;
//c is now equal to 11.3&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can even pass arrays!  You do not have to specify the size of the array.  If you do, you must make sure you are calling the function with an array of equal size and type.&lt;br /&gt;
&amp;lt;pawn&amp;gt;add_two_from_array(array[], a, b)&lt;br /&gt;
{&lt;br /&gt;
   new first = array[a]&lt;br /&gt;
   new second = array[b]&lt;br /&gt;
   new sum = add_two_numbers(first, second)   //use our function from earlier&lt;br /&gt;
  &lt;br /&gt;
   return sum&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that when you pass arrays through a function they are passed through what is called &amp;quot;by reference&amp;quot;. When a normal variable is passed to a function, it is copied in memory, and the copy is sent and then deleted afterwards. This is not the case with an array. Because arrays can be very large, the array is &amp;quot;referenced&amp;quot; instead of copied. This means if you change the array, afterwards it will stay changed. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//This function will switch slots a and b inside any array passed to this function.&lt;br /&gt;
swap_slots(array[], a, b)&lt;br /&gt;
{&lt;br /&gt;
   //Note, you need to temporarily hold one of the slots before swapping them&lt;br /&gt;
   //Otherwise, you can't swap both values! This is a classic problem.&lt;br /&gt;
   //If you have a and b, setting b equal to a eliminates the original value in b.&lt;br /&gt;
   new temp&lt;br /&gt;
             &lt;br /&gt;
   temp = array[b]&lt;br /&gt;
   array[b] = array[a]&lt;br /&gt;
   array[a] = temp&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
new myArray[2]&lt;br /&gt;
myArray[0] = 5&lt;br /&gt;
myArray[1] = 6&lt;br /&gt;
swap_slots(myArray, 0, 1)&lt;br /&gt;
//myArray[0] is 6, myArray[1] is 5&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can prevent arrays from being modified by declaring them &amp;quot;constant&amp;quot;, like so:&lt;br /&gt;
&amp;lt;pawn&amp;gt;add_two_from_array(const array[], a, b)&lt;br /&gt;
{&lt;br /&gt;
   new first = array[a]&lt;br /&gt;
   new second = array[b]&lt;br /&gt;
   new sum = add_two_from_array(first, second)&lt;br /&gt;
   return sum&lt;br /&gt;
}&lt;br /&gt;
//Note, now when you use the function, you are guaranteed that the array will not be modified.&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function modifies an array passed as a constant.  It will not work.&lt;br /&gt;
&amp;lt;pawn&amp;gt;bad_function(const array[])&lt;br /&gt;
{&lt;br /&gt;
   array[0] = 0&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Expressions=&lt;br /&gt;
&lt;br /&gt;
Expressions are just what they sound like from mathematics. They are groupings of symbols that return one piece of data. Expressions are normally comprised of parenthetical expressions, and are evaluated in a certain order (from innermost to outermost, parenthesis first, then multiplication, division, addition, subtraction, et cetera). You can put expressions anywhere. You can set variables equal to them or pass them to functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//This is the simplest expression.  It returns the number zero.&lt;br /&gt;
0&lt;br /&gt;
//However, to make it easier to read, this is also valid:&lt;br /&gt;
(0)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If an expression is not zero or it is not false, it not only returns a value, it also returns &amp;quot;true&amp;quot;. Otherwise, it will return 0, which is also &amp;quot;false&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//Here are more mathematical expressions.  The mathematical operators are&lt;br /&gt;
// + for addition&lt;br /&gt;
// - for subtraction&lt;br /&gt;
// * for multiplication&lt;br /&gt;
// / for division&lt;br /&gt;
// % for modulus (finding the remainder of one number divided by another (5%2 is 1)&lt;br /&gt;
(5+6)                       //returns 11&lt;br /&gt;
((5*6)+3)                   //returns 33&lt;br /&gt;
((((5+3)/2)*4)-9)           //returns 7&lt;br /&gt;
((5*6) % 7)                 //returns 2&lt;br /&gt;
//Here are other expressions:&lt;br /&gt;
(true)                      //returns true&lt;br /&gt;
(5.0 + 2.3)                 //returns 7.3 as a floating point&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also extensions of these operators for direct use on variables.&lt;br /&gt;
&amp;lt;pawn&amp;gt;new a = 5&lt;br /&gt;
new b = 6&lt;br /&gt;
//The first are the post/pre increment and decrement operators.&lt;br /&gt;
a++          //returns a+1, or 6.  This is a post increment.&lt;br /&gt;
++a          //also returns a+1, or 6.  This is a pre increment.&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The difference between the two is subtle but important. a++ is evaluated LAST in an expression, while ++a is evaluated FIRST. This differences comes in handy with code that uses loops in certain ways. It is also important to know that the increment/decrement operators will not only return a+1, but set the variable a to a+1.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;a--          //returns 4, post decrement&lt;br /&gt;
--a          //returns 4, pre decrement&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that a++ essentially trims down this code:&lt;br /&gt;
&amp;lt;pawn&amp;gt;a = a + 1&amp;lt;/pawn&amp;gt;&lt;br /&gt;
However, there is another way to write lines of code of this form:&lt;br /&gt;
&amp;lt;pawn&amp;gt;a = a OP y&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Where OP is a math operator.  It can be shortened to:&lt;br /&gt;
&amp;lt;pawn&amp;gt;a OP= x&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Observe:&lt;br /&gt;
&amp;lt;pawn&amp;gt;a += 1       //This sets a to a + 1&lt;br /&gt;
a -= b       //This sets a to a - b&lt;br /&gt;
a *= 0       //This multiplies a by 0&lt;br /&gt;
a /= 2       //This divides a by 2.&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, mathematical operators are not the only operators you are given. There are boolean operators to help you with logical circuits or logical decisions.&lt;br /&gt;
&lt;br /&gt;
The and operator takes in the left expression and right expression.  If both are &amp;quot;true&amp;quot;, then it returns true.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//This is false, because 1 returns true and 0 returns false.  &lt;br /&gt;
//Since both are not true, &amp;amp;&amp;amp; returns false.&lt;br /&gt;
(1 &amp;amp;&amp;amp; 0)&lt;br /&gt;
(1 &amp;amp;&amp;amp; 2)                    //Both numbers are &amp;quot;true&amp;quot;, therefore the expression is true.&lt;br /&gt;
(true &amp;amp;&amp;amp; false)             //false&lt;br /&gt;
(false &amp;amp;&amp;amp; false)            //false&lt;br /&gt;
(true &amp;amp;&amp;amp; true)              //true&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The other important operator is &amp;quot;or&amp;quot;.  It returns true if one of two expressions are true.&lt;br /&gt;
&amp;lt;pawn&amp;gt;(1 || 0)                    //true, since one of the values is true.&lt;br /&gt;
(1 || 2)                    //true&lt;br /&gt;
(true || false)             //true&lt;br /&gt;
(false || false)            //false&lt;br /&gt;
(true || true)              //true&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are other operators as well, that you may not use as often. The &amp;quot;bitwise and&amp;quot; operator returns whether a binary bit sequence is contained in another sequence. In the technical terms, it does an &amp;quot;and (&amp;amp;&amp;amp;)&amp;quot; operation on each of the bits in both numbers. For example, say you have the number &amp;quot;9&amp;quot;, which is &amp;quot;1001&amp;quot; in binary. If you want to know if that sequence contains the number &amp;quot;8&amp;quot; (1000), you can do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//This will return 8, which means 8 is indeed a bit in 9.&lt;br /&gt;
(9 &amp;amp; 8)&lt;br /&gt;
//4 (00100) is not a bit inside 16 (10000) and this will return 0.&lt;br /&gt;
(16 &amp;amp; 4)&lt;br /&gt;
//The next operator is &amp;quot;bitwise or&amp;quot; &lt;br /&gt;
//which does an &amp;quot;or (||)' operation on each of the bits in both numbers.&lt;br /&gt;
//This will take 9 (1001) and match it with 3 (0011), resulting in 1011, or 11.&lt;br /&gt;
(9 | 3)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These two operators are also important, but not used often. They are the bitwise shift operators, &amp;lt;&amp;lt; is a left shift and &amp;gt;&amp;gt; is a right shift. They shift the bits in a number to one direction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//This takes the number 3 (00011) and shifts it three places to binary (11000), or 24.&lt;br /&gt;
(3 &amp;lt;&amp;lt; 3)&lt;br /&gt;
//This takes the number 24 (11000) and shifts it three places to binary (00011), or 3.&lt;br /&gt;
(24 &amp;gt;&amp;gt; 3)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The last operator is &amp;quot;bitwise not&amp;quot;. It returns the exact opposite of whatever is given to it. When used on a number, it will return each of the bits flipped (1 to 0, 0 to 1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//This returns false&lt;br /&gt;
(!true)&lt;br /&gt;
//This returns true&lt;br /&gt;
(!false)&lt;br /&gt;
//This takes 9 (binary 1001) and makes it 6 (binary 0110).&lt;br /&gt;
//This is the &amp;quot;bitwise complement&amp;quot; operator, which performs a !(not) on each bit.&lt;br /&gt;
(~(9))&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Conditionals=&lt;br /&gt;
&lt;br /&gt;
Conditionals allow you to test if an expression meets a standard, and to execute code based on that decision. &lt;br /&gt;
&lt;br /&gt;
==If Statements==&lt;br /&gt;
&lt;br /&gt;
The most important conditional is called &amp;quot;if ... then&amp;quot;. If evaluates whether a given expression is true or false. It if is true, it executes a block of code. If not, it executes a different block of code. For example:&lt;br /&gt;
&lt;br /&gt;
This is an example of the most basic if ... then statement. The first line checks to see if the expression is true. In this case, if the variable a is equal to 5, then the if statement will execute the block of code underneath it, which sets a to 6.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (a == 5)&lt;br /&gt;
{&lt;br /&gt;
   a = 6&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, what happens if a does not equal 5? Then the code will not be executed. However, you can tell it to execute code if the conditions are not met. Now, if a is equal to 5, a will be set to 6. Otherwise, it will be set to 7.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (a == 5)&lt;br /&gt;
{&lt;br /&gt;
   a = 6&lt;br /&gt;
} else {&lt;br /&gt;
   a = 7&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are many different operators you can use inside the if () statement. In fact, you can use any [[#Expressions|expression]] that evaluates to true (not zero) or false (zero).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//This will return true if a does not equal 5&lt;br /&gt;
if (a != 5) {}&lt;br /&gt;
//Returns true if a is greater than 5&lt;br /&gt;
if (a &amp;gt; 5) {}&lt;br /&gt;
//Returns true if a is less than 5&lt;br /&gt;
if (a &amp;lt; 5) {}&lt;br /&gt;
//Returns true if a is greater than or equal to 5&lt;br /&gt;
if (a &amp;gt;= 5) {}&lt;br /&gt;
//Returns true if a is less than or equal to 5&lt;br /&gt;
if (a &amp;lt;= 5) {}&lt;br /&gt;
//Returns true because 11 is true&lt;br /&gt;
if (5+6) {}&lt;br /&gt;
//Returns true of both a and b are true&lt;br /&gt;
if (a &amp;amp;&amp;amp; b) {}&lt;br /&gt;
//Returns true if 7.5 is greater than c&lt;br /&gt;
if ( ((5*3)/2) &amp;gt; c) {}&lt;br /&gt;
//Always returns true no matter what&lt;br /&gt;
if (true) {}&lt;br /&gt;
//Never returns true&lt;br /&gt;
if (false) {}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Note that array comparisons have restrictions. This is invalid:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;my arrayOne[3]&lt;br /&gt;
my arrayTwo[3]&lt;br /&gt;
if (arrayOne == arrayTwo) {&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You must do:&lt;br /&gt;
&amp;lt;pawn&amp;gt;if ((arrayOne[0] == arrayTwo[0]) &amp;amp;&amp;amp; &lt;br /&gt;
    (arrayOne[1] == arrayTwo[1]) &amp;amp;&amp;amp; &lt;br /&gt;
    (arrayOne[2] == arrayTwo[2])) {&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Obviously, this would get very tedious with large arrays. You will see later on how to easily compare strings and arrays.&lt;br /&gt;
&lt;br /&gt;
The if...then model of conditional switching can be brought up to another level. Pawn provides a way for you to provide multiple levels of true and false expressions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//Example of &amp;quot;if...else if&amp;quot;&lt;br /&gt;
if (a == 5) {&lt;br /&gt;
   //This code will be run if a is 5.&lt;br /&gt;
} else if (a &amp;lt; 6) {&lt;br /&gt;
   //This code will be run if a is less than 6&lt;br /&gt;
} else if (a == 7) {&lt;br /&gt;
   //This code will be run if a is 7.&lt;br /&gt;
} else {&lt;br /&gt;
   //If none of the above conditions are met, this code will be run.&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It is important to note that in the above example, each code block is not &amp;quot;fall through&amp;quot;. That means each of the conditions will be checked in order, and if one is true, the code will be executed and the if statement is done. It will not execute multiple true conditions.&lt;br /&gt;
&lt;br /&gt;
==Switch Statements==&lt;br /&gt;
&lt;br /&gt;
Lastly, there is one last type of conditional statement. It is called a &amp;quot;switch&amp;quot; statement, and it allows you to make a nicely ordered list of conditions similar to, but not as powerful as, &amp;quot;if...else if&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//Example of a switch statement&lt;br /&gt;
switch (a)&lt;br /&gt;
{&lt;br /&gt;
    case 5:&lt;br /&gt;
    {&lt;br /&gt;
       //This code will run if a is equal to 5&lt;br /&gt;
    }&lt;br /&gt;
   &lt;br /&gt;
    case 6:&lt;br /&gt;
    {&lt;br /&gt;
       //This code will run if a is equal to 6&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    case 7:&lt;br /&gt;
    {&lt;br /&gt;
       //This code will run if a is equal to 7&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    default:&lt;br /&gt;
    {&lt;br /&gt;
       //This code will run if all other cases fail&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Multiple conditions are also possible in pawn:&lt;br /&gt;
&amp;lt;pawn&amp;gt;//Example of an multiple switch statement&lt;br /&gt;
switch (a)&lt;br /&gt;
{&lt;br /&gt;
    case 1, 2, 3:&lt;br /&gt;
    {&lt;br /&gt;
       //This code will run if a is equal to 1 or 2 or 3&lt;br /&gt;
    }&lt;br /&gt;
   &lt;br /&gt;
    case 4, 5, 6:&lt;br /&gt;
    {&lt;br /&gt;
       //This code will run if a is equal to 4 or 5 or6&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    case 7, 8, 9:&lt;br /&gt;
    {&lt;br /&gt;
       //This code will run if a is equal to 7 or 8 or 9&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    default:&lt;br /&gt;
    {&lt;br /&gt;
       //This code will run if all other cases fail&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that switch cases do not &amp;quot;fall-through.&amp;quot; If a case is true, no other cases are evaluated.&lt;br /&gt;
&lt;br /&gt;
=Looping=&lt;br /&gt;
&lt;br /&gt;
Looping is essential for any language. It allows you to perform the same block of code over and over, by constructing conditions on which code should be repeated.&lt;br /&gt;
&lt;br /&gt;
==For Loops==&lt;br /&gt;
&lt;br /&gt;
The first and most widely used loop is called a &amp;quot;for loop&amp;quot;. It takes an initial value, a condition upon which it should stop, and an incremental step. Then it executes code until it the conditions are no longer true. This lets you repeat the same block of code any number of times. Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;/*A for loop has three parameters:&lt;br /&gt;
  for (initial; condition; increment)&lt;br /&gt;
  {&lt;br /&gt;
    //your code here&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  Before the first loop executes, it runs your initial condition.&lt;br /&gt;
  Then it begins looping your code with these steps:&lt;br /&gt;
  1.  Check if the condition is true.  If so, continue.  If not, stop.&lt;br /&gt;
  2.  Run the code.&lt;br /&gt;
  3.  Run the &amp;quot;increment&amp;quot; parameter.&lt;br /&gt;
  4.  Go to step 1.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
//Example of a for loop&lt;br /&gt;
new i&lt;br /&gt;
new sum&lt;br /&gt;
for (i=1; i&amp;lt;=10; i++)&lt;br /&gt;
{&lt;br /&gt;
   sum += i&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanation:&lt;br /&gt;
&lt;br /&gt;
#The first parameter, i=1, sets the i variable to one. This happens before the looping starts.&lt;br /&gt;
#Next, the &amp;quot;increment&amp;quot; parameter is checked. This parameter is a post-increment operator, so 1 will be added to i after the entire code block is evaluated.&lt;br /&gt;
#Then the condition is checked. Is i&amp;lt;=10? It is currently 1, so it is indeed less than or equal to 10.&lt;br /&gt;
#Since the condition is true, sum+=i is executed. This means i is added into sum.&lt;br /&gt;
#The code block has finished, and i++ increments i to 2.&lt;br /&gt;
#Now it repeats.&lt;br /&gt;
#Is i&amp;lt;=10? Yes, it is 2. Now sum+=i runs again, and now sum is equal to 3.&lt;br /&gt;
#The code block has finished, and i now increments to 3.&lt;br /&gt;
#This happens until...&lt;br /&gt;
#The increment parameter sets i to 11. The condition is no longer true, and the for loop is finished.&lt;br /&gt;
#The sum variable now holds the number 55, which is the sum of 1 through 10.&lt;br /&gt;
&lt;br /&gt;
This provides a nice way of managing arrays!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//Note: this provides a nice way to loop through arrays!  Observe this function below.&lt;br /&gt;
sum_of_array(myArray[], size)&lt;br /&gt;
{&lt;br /&gt;
   //Note: Make sure the user passes the size of the array, so we don't overflow it.&lt;br /&gt;
   new i, sum&lt;br /&gt;
  &lt;br /&gt;
   //This loop will start at 0 and stop right before size is reached.&lt;br /&gt;
   //If the user passes the correct size of the array, &lt;br /&gt;
   // the loop will be going from 0 to size-1&lt;br /&gt;
   // This correctly matches the numbers of slots in the array.&lt;br /&gt;
   for  (i=0; i&amp;lt;size; i++)&lt;br /&gt;
   {&lt;br /&gt;
      //For every time this loop executes, &lt;br /&gt;
      // i will be a number from 0 to size-1&lt;br /&gt;
      //Add the value of the slot (i) in the array to sum.&lt;br /&gt;
      //Once this is finished, sum will contain &lt;br /&gt;
      // the sum of all slots in the array.&lt;br /&gt;
      sum += myArray[i]&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   return sum&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
new NumberArray[4]&lt;br /&gt;
NumberArray[0] = 3&lt;br /&gt;
NumberArray[1] = 1&lt;br /&gt;
NumberArray[2] = 4&lt;br /&gt;
NumberArray[3] = 1&lt;br /&gt;
&lt;br /&gt;
new answer = sum_of_array(NumberArray, 4)&lt;br /&gt;
//answer will be 3+1+4+1, or 9&lt;br /&gt;
&lt;br /&gt;
//Here is a function to compare if one array is equal to another (i.e. a string)&lt;br /&gt;
bool:compare_arrays(array1[], array2[], size)&lt;br /&gt;
{&lt;br /&gt;
   new i&lt;br /&gt;
   for (i=0; i&amp;lt;size; i++)&lt;br /&gt;
   {&lt;br /&gt;
      //If a slot does not match, halt the function and return false.&lt;br /&gt;
      if (array1[i] != array2[i])&lt;br /&gt;
      {&lt;br /&gt;
         return false&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   //If the function got to this point without returning false, return true.&lt;br /&gt;
   return true&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==While Loops==&lt;br /&gt;
&lt;br /&gt;
The next kind of loop is also very important, and is simpler than a for loop. Called a &amp;quot;while&amp;quot; loop, it only takes one parameter: a condition. As long as the condition is true, it keeps executing code. See the above examples rewritten with while loops.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//Basic loop&lt;br /&gt;
new i=0&lt;br /&gt;
new sum&lt;br /&gt;
&lt;br /&gt;
while (++i &amp;lt;= 10)&lt;br /&gt;
{&lt;br /&gt;
   sum+=i&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sum_of_array(array[], size)&lt;br /&gt;
{&lt;br /&gt;
   new i=0, sum&lt;br /&gt;
&lt;br /&gt;
   //Do this loop while i is less than the size.&lt;br /&gt;
   //i is incremented at the end of every loop.&lt;br /&gt;
   while (i++ &amp;lt; size)&lt;br /&gt;
   {&lt;br /&gt;
      sum += array[i]&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   return sum&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
bool:compare_arrays(array1[], array2[], size)&lt;br /&gt;
{&lt;br /&gt;
   new i&lt;br /&gt;
   while (i++ &amp;lt; size)&lt;br /&gt;
   {&lt;br /&gt;
      if (array1[i] != array2[i])&lt;br /&gt;
      {&lt;br /&gt;
         return false&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   return true&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Two Dimensional Arrays==&lt;br /&gt;
&lt;br /&gt;
In Pawn it is possible to have arrays where each slot is another array. This is very useful for storing a table of data, where the first section of slots is a row and the second section of slots is a column. Two dimensional arrays are declared like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//This declares an array with 50 rows and 50 columns.&lt;br /&gt;
new BigArray[50][50]&lt;br /&gt;
//this declares a floating point array with 25 rows and 10 columns.&lt;br /&gt;
new Float:BigArray[25][10]&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each slot in the first subset of the array becomes its own array.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new BigArray[3][3]&lt;br /&gt;
BigArray[0][0] = 10&lt;br /&gt;
BigArray[0][1] = 20&lt;br /&gt;
BigArray[0][2] = 30&lt;br /&gt;
BigArray[1][0] = 40&lt;br /&gt;
BigArray[1][1] = 50&lt;br /&gt;
BigArray[1][2] = 60&lt;br /&gt;
BigArray[2][0] = 70&lt;br /&gt;
BigArray[2][1] = 80&lt;br /&gt;
BigArray[2][2] = 90&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Will result in BigArray looking like this:&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| BigArray&lt;br /&gt;
| 0&lt;br /&gt;
| 1&lt;br /&gt;
| 2&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| 10&lt;br /&gt;
| 20&lt;br /&gt;
| 30&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 40&lt;br /&gt;
| 50&lt;br /&gt;
| 60&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| 70&lt;br /&gt;
| 80&lt;br /&gt;
| 90&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note that our old sum_of_array() function can still work! We can do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new sum = sum_of_array(BigArray[2], 3)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Because BigArray[2] contains a second, single dimensional array, containing {7,8,9}. However, let's write a 2D sum of array function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//This function will tally up a two dimensional array.&lt;br /&gt;
sum_of_table(array[][], rows, cols)&lt;br /&gt;
{&lt;br /&gt;
   new i, j, sum&lt;br /&gt;
&lt;br /&gt;
   //Note, there is a loop inside the loop.  &lt;br /&gt;
   //This lets you go through each array inside the   &lt;br /&gt;
   // bigger array. &lt;br /&gt;
   for (i=0; i&amp;lt;rows; i++)&lt;br /&gt;
   {&lt;br /&gt;
      for (j=0; j&amp;lt;cols; j++)&lt;br /&gt;
      {&lt;br /&gt;
         sum += array[i][j]&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   return sum&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, it is also possible to store an array of strings using two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;new StringList[3][] = {&amp;quot;Hello&amp;quot;, &amp;quot;my&amp;quot;, &amp;quot;friend&amp;quot;}&lt;br /&gt;
/*&lt;br /&gt;
  StringList[0][0] through [0][5] contains &amp;quot;Hello&amp;quot;&lt;br /&gt;
  StringList[1][0] through [1][2] contains &amp;quot;my&amp;quot;&lt;br /&gt;
  StringList[2][0] through [2][6] contains &amp;quot;friend&amp;quot;&lt;br /&gt;
*/&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The table for StringList will look like:&lt;br /&gt;
StringList 	0 	1 	2 	3 	4 	5 	6&lt;br /&gt;
0 	H 	e 	l 	l 	o 	\0 	&lt;br /&gt;
1 	m 	y 	\0 				&lt;br /&gt;
2 	f 	r 	i 	e 	n 	d 	\0&lt;br /&gt;
&lt;br /&gt;
Comparing strings in multidimensional arrays is also similar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;if (StringList[0] == &amp;quot;Hello&amp;quot;)       //INVALID&lt;br /&gt;
if (StringList[0][0] == &amp;quot;Hello&amp;quot;)    //INVALID&lt;br /&gt;
if (equali(StringList[0], &amp;quot;Hello&amp;quot;)) //Valid&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Compiler Pre-processor Directives=&lt;br /&gt;
&lt;br /&gt;
Compiler directives allow you to change how your code is read. This is rather advanced and will only be run over briefly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//To bind a symbol to a value, you can do this:&lt;br /&gt;
#define SYMBOL VALUE&lt;br /&gt;
//for example:&lt;br /&gt;
&lt;br /&gt;
#define MAX_STRING 250&lt;br /&gt;
new String[MAX_STRING]&lt;br /&gt;
&lt;br /&gt;
#define HELLO &amp;quot;Hello.  This is a generic greeting.&amp;quot;&lt;br /&gt;
new Hello[MAX_STRING] = HELLO&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use #defines to change the flow of code the compiler makes.&lt;br /&gt;
&amp;lt;pawn&amp;gt;#if defined LINUX&lt;br /&gt;
   //This portion will be compiled if #define LINUX exists&lt;br /&gt;
   execute_command(&amp;quot;ls -l&amp;quot;)&lt;br /&gt;
#else&lt;br /&gt;
   //This portion will be compiled if #define LINUX does not exist&lt;br /&gt;
   execute_command(&amp;quot;dir&amp;quot;)&lt;br /&gt;
#endif&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also change how much memory your script uses.&lt;br /&gt;
&amp;lt;pawn&amp;gt;#pragma dynamic 4096&lt;br /&gt;
//This creates a 16K stack of memory (default).&lt;br /&gt;
//It is measured in blocks of 4 byte cells.&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also specify whether semicolon usage is required to terminate a line of code (by default it is not required). &lt;br /&gt;
&amp;lt;pawn&amp;gt;#pragma semicolon 1&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also change the control character( amxx std: '^' )&lt;br /&gt;
&amp;lt;pawn&amp;gt;#pragma ctrlchar '\'&lt;br /&gt;
//this sets the control character to backslash( c/c++/c#/java/... std )&lt;br /&gt;
// now you have to use the \ instead of ^&lt;br /&gt;
// e.g. &amp;quot;this is ^&amp;quot;:D^&amp;quot; &amp;quot; must be now &amp;quot; this is \&amp;quot;:D\&amp;quot; &amp;quot;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
&lt;br /&gt;
This guide should have given you a VERY brief introduction to basic Pawn programming. It is by no means comprehensive and it should not constitute the entirety of one's knowledge of Pawn. To read the official Pawn documentation and language guide, go this website: http://www.compuphase.com/pawn/Pawn_Language_Guide.pdf (Note, this guide is very long and should be used as a reference. You may want to try the Small forums or the AMX Mod X forums). Continue to the next Section to see how to apply Small programming to the Half-Life and AMX Mod X engine!&lt;br /&gt;
&lt;br /&gt;
=External Links=&lt;br /&gt;
*[http://www.compuphase.com/pawn/Pawn_Language_Guide.pdf Pawn Language Reference]&lt;br /&gt;
*[http://www.compuphase.com/pawn/pawn.htm Pawn Homepage]&lt;br /&gt;
*[http://www.compuphase.com/ ITB CompuPhase]&lt;br /&gt;
&lt;br /&gt;
[[Category:Scripting (AMX Mod X)]]&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Handle_API_(SourceMod)&amp;diff=10237</id>
		<title>Handle API (SourceMod)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Handle_API_(SourceMod)&amp;diff=10237"/>
		<updated>2017-01-09T01:04:27Z</updated>

		<summary type="html">&lt;p&gt;Fyren: /* Handle Security */ I guess.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The SourceMod [[Handles (SourceMod Scripting)|Handle System]] marshals pointers into typed, unique, 32-bit integers.  This makes coding in SourceMod more cross-platform compatible, type safe, and mistake safe than its predecessor, [[AMX Mod X]].  It also allows for safe object sharing and reference count based object destruction.&lt;br /&gt;
&lt;br /&gt;
The fundamental aspect of Handles is that they encapsulate a single pointer.  This pointer is private data, and can only be read by the Handle's creator.  When the Handle is freed, the pointer is automatically freed (via a special interface), thus ensuring that memory is not leaked.&lt;br /&gt;
&lt;br /&gt;
Handles also provide a simple &amp;quot;security&amp;quot; system for restricting which areas of SourceMod are allowed to directly call certain functions on Handles under a given type.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Basic Types=&lt;br /&gt;
==Handle_t==&lt;br /&gt;
The &amp;lt;tt&amp;gt;Handle_t&amp;lt;/tt&amp;gt; type is a 32bit integer.  Currently, it is composed of two 16-bit integers, a serial number and a handle index.  The serial number is private and used for integrity checking.  The index is the internal ID of the Handle, which is tied to the encapsulated pointer and security information.&lt;br /&gt;
&lt;br /&gt;
Each &amp;lt;tt&amp;gt;Handle_t&amp;lt;/tt&amp;gt; is a unique Handle, however, there are ''cloned'' Handles which are copies of another Handle.  They have their own unique signatures, but they refer to another Handle internally.  Each Handle is also associated with a ''type'', explained below.&lt;br /&gt;
&lt;br /&gt;
==HandleType_t==&lt;br /&gt;
The &amp;lt;tt&amp;gt;HandleType_t&amp;lt;/tt&amp;gt; describes a type under which Handles can be created.  Types can have up to 15 sub-types; sub-types can also have their own sub-types, called child types.  When Handles are being read, they are &amp;quot;type checked,&amp;quot; to make sure they are being read under a given type.  When a type is destroyed, all Handles under the type are destroyed.  If the type has child types, each child type is also destroyed. &lt;br /&gt;
&lt;br /&gt;
Handle types also allow overloading of various Handle operations.  Currently, the only overloaded action is for overloading when a Handle is destroyed.  This allows the encapsulated pointer to be safely destroyed by the type interface.  The interface which overloads type operations is called &amp;lt;tt&amp;gt;IHandleTypeDispatch&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Lastly, types provide a &amp;quot;default security&amp;quot; system which lets programmers restrict which functions can be accessed by other areas in SourceMod.  This is explained later.&lt;br /&gt;
&lt;br /&gt;
=Security=&lt;br /&gt;
'''Note:''' Type defaults can be set via &amp;lt;tt&amp;gt;IHandleSys::InitAccessDefaults()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Type Security==&lt;br /&gt;
Often, extensions may want to share HandleType_t values with each other, so they can create Handles of external types.  However, the owner of the handle type may not want other extensions to perform certain actions.  Thus, types can be ''secured'' by an &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt; when created.  Unless the same &amp;lt;tt&amp;gt;IdentityToken&amp;lt;/tt&amp;gt; is provided, a function may fail if restricted.&lt;br /&gt;
&lt;br /&gt;
Type permissions are declared in a &amp;lt;tt&amp;gt;TypeAccess&amp;lt;/tt&amp;gt; struct, which has the following user-set members:&lt;br /&gt;
*&amp;lt;tt&amp;gt;ident&amp;lt;/tt&amp;gt;: The &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt; owner of this type.&lt;br /&gt;
*&amp;lt;tt&amp;gt;access&amp;lt;/tt&amp;gt;: An array where each index is a &amp;lt;tt&amp;gt;HTypeAccessRight&amp;lt;/tt&amp;gt; enumeration member.  If an index is set to false, functions requiring that right will fail unless the correct &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt; is passed in.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;HTypeAccessRight&amp;lt;/tt&amp;gt; enumeration has the following values:&lt;br /&gt;
*&amp;lt;tt&amp;gt;HTypeAccess_Create&amp;lt;/tt&amp;gt;: Handle creation using this type; default is false.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HTypeAccess_Inherit&amp;lt;/tt&amp;gt;: Inheriting this type for child types; default is false.&lt;br /&gt;
&lt;br /&gt;
Below is a list of each Handle System function that requires type permissions, and which permissions may be required:&lt;br /&gt;
*&amp;lt;tt&amp;gt;CreateType&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;&amp;lt;tt&amp;gt;HTypeAccess_Inherit&amp;lt;/tt&amp;gt; if a parent is specified&amp;lt;/i&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;RemoveType&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;(none, always secured)&amp;lt;/i&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;CreateHandle&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;&amp;lt;tt&amp;gt;HTypeAccess_Create&amp;lt;/tt&amp;gt;&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Handle Security==&lt;br /&gt;
Handle security permissions inherit from their parent type unless given an alternate set of permissions.  Handles are &amp;quot;secured&amp;quot; by two properties, unlike handle types, which just have one.  When verifying your identity with a secured Handle function, you must use the &amp;lt;tt&amp;gt;HandleSecurity&amp;lt;/tt&amp;gt; struct, which has two properties:&lt;br /&gt;
*&amp;lt;tt&amp;gt;pOwner&amp;lt;/tt&amp;gt;: The owner of the Handle, which is usually a plugin &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;pIdentity&amp;lt;/tt&amp;gt;: The owner of the Handle's type, or the &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt; securing its type.&lt;br /&gt;
&lt;br /&gt;
Handle permissions are specified via the &amp;lt;tt&amp;gt;HandleAccess&amp;lt;/tt&amp;gt; struct.  It is passed either through &amp;lt;tt&amp;gt;CreateType&amp;lt;/tt&amp;gt; for default settings in a given type, or through &amp;lt;tt&amp;gt;CreateHandleEx&amp;lt;/tt&amp;gt; for explicit per-Handle permissions.  This struct has the following members:&lt;br /&gt;
*&amp;lt;tt&amp;gt;access&amp;lt;/tt&amp;gt;: An array where each index is a &amp;lt;tt&amp;gt;HandleAccessRight&amp;lt;/tt&amp;gt; enumeration member.  If set to 0, an access right is allowed without a &amp;lt;tt&amp;gt;HandleSecurity&amp;lt;/tt&amp;gt; instance.  Otherwise, the following bitwise flags are checked:&lt;br /&gt;
**&amp;lt;tt&amp;gt;HANDLE_RESTRICT_IDENTITY&amp;lt;/tt&amp;gt;: If flagged, this access right is only granted if the &amp;lt;tt&amp;gt;pIdentity&amp;lt;/tt&amp;gt; member of the &amp;lt;tt&amp;gt;HandleSecurity&amp;lt;/tt&amp;gt; struct matches the Handle's '''type's''' owner.&lt;br /&gt;
**&amp;lt;tt&amp;gt;HANDLE_RESTRICT_OWNER&amp;lt;/tt&amp;gt;: If flagged, this access right is onyl granted if the &amp;lt;tt&amp;gt;pOwner&amp;lt;/tt&amp;gt; member of the &amp;lt;tt&amp;gt;Handlesecurity&amp;lt;/tt&amp;gt; struct matches the Handle's owner.&lt;br /&gt;
&lt;br /&gt;
The following access rights exist for Handles:&lt;br /&gt;
*&amp;lt;tt&amp;gt;HandleAccess_Read&amp;lt;/tt&amp;gt;: This Handle's encapsulated pointer can be retrieved.  Defaults to &amp;lt;tt&amp;gt;HANDLE_RESTRICT_IDENTITY&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HandleAccess_Delete&amp;lt;/tt&amp;gt;: This Handle can be removed or freed.  Defaults to &amp;lt;tt&amp;gt;HANDLE_RESTRICT_OWNER&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;HandleAccess_Clone&amp;lt;/tt&amp;gt;: This Handle can be cloned.  Defaults to 0.&lt;br /&gt;
&lt;br /&gt;
Below is a list of each Handle system function that requires permissions, and which permissions may be required:&lt;br /&gt;
*&amp;lt;tt&amp;gt;FreeHandle&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;&amp;lt;tt&amp;gt;HandleAccess_Delete&amp;lt;/tt&amp;gt;&amp;lt;/i&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;CloneHandle/CloneHandleEx&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;&amp;lt;tt&amp;gt;HandleAccess_Clone&amp;lt;/tt&amp;gt;&amp;lt;/i&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;ReadHandle&amp;lt;/tt&amp;gt;: &amp;lt;i&amp;gt;&amp;lt;tt&amp;gt;HandleAccess_Read&amp;lt;/tt&amp;gt;&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
SourceMod's generic native wrappers assume follow these rules, however, they assume certain access rights, and will return &amp;lt;tt&amp;gt;INVALID_HANDLE&amp;lt;/tt&amp;gt; or 0 if these rights are denied.  Thus, you should make sure your permissions are compatible, unless you explicitly want to deny usage of these functions.&lt;br /&gt;
*&amp;lt;tt&amp;gt;CloneHandle()&amp;lt;/tt&amp;gt;: Passes &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;HandleSecurity&amp;lt;/tt&amp;gt;, meaning &amp;lt;tt&amp;gt;HandleAccess_Clone&amp;lt;/tt&amp;gt; must be 0.&lt;br /&gt;
*&amp;lt;tt&amp;gt;CloseHandle()&amp;lt;/tt&amp;gt;: Passes &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;HandleSecurity::pIdentity&amp;lt;/tt&amp;gt;, and the plugin's &amp;lt;tt&amp;gt;IdentityToken_t&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;HandleSecurity::pOwner&amp;lt;/tt/&amp;gt;.  This means that at most, the only restriction can be &amp;lt;tt&amp;gt;HANDLE_RESTRICT_OWNER&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;HandleAccess_Delete&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Usage Examples=&lt;br /&gt;
Here are some examples of Handle usages.&lt;br /&gt;
&lt;br /&gt;
==Basic Handles==&lt;br /&gt;
The most basic use of Handles is to encapsulate a data structure and allow &amp;lt;tt&amp;gt;CloseHandle&amp;lt;/tt&amp;gt; to universally destroy it.  Let's say we want to implement two natives - &amp;lt;tt&amp;gt;CreateFile&amp;lt;/tt&amp;gt; for creating an empty file, and &amp;lt;tt&amp;gt;WriteLine&amp;lt;/tt&amp;gt; for writing a line to this file.  How could we implement this using the Handle system?&lt;br /&gt;
&lt;br /&gt;
After reading this, it is tempting to think, &amp;quot;Why can't we just return the &amp;lt;tt&amp;gt;FILE&amp;lt;/tt&amp;gt; pointer as a &amp;lt;tt&amp;gt;cell_t&amp;lt;/tt&amp;gt;?&amp;quot;  The reason is that a &amp;lt;tt&amp;gt;cell_t&amp;lt;/tt&amp;gt; is guaranteed to be a 32bit integer.  There is no guarantee that a pointer will always be this size, however, and thus casting on future platforms could break.  This problem happened in [[AMX Mod X]] and greatly restricted flexibility.  &lt;br /&gt;
&lt;br /&gt;
===Creating the type===&lt;br /&gt;
First, we have to create the type and its Dispatch interface.&lt;br /&gt;
&amp;lt;cpp&amp;gt;HandleType_t g_FileType = 0;	/* Holds the HandleType ID */&lt;br /&gt;
&lt;br /&gt;
class FileTypeHandler : public IHandleTypeDispatch&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
	void OnHandleDestroy(HandleType_t type, void *object)&lt;br /&gt;
	{&lt;br /&gt;
		/* :TODO: implement this */&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* Create an instance of the handler */&lt;br /&gt;
FileTypeHandler g_FileTypeHandler;&lt;br /&gt;
&lt;br /&gt;
Initialize()&lt;br /&gt;
{&lt;br /&gt;
	/* Register the type with default security permissions */&lt;br /&gt;
	g_FileType = g_pHandleSys-&amp;gt;CreateType(&amp;quot;File&amp;quot;, &lt;br /&gt;
		&amp;amp;g_FileTypeHandler, &lt;br /&gt;
		0, &lt;br /&gt;
		NULL, &lt;br /&gt;
		NULL, &lt;br /&gt;
		myself-&amp;gt;GetIdentity(), &lt;br /&gt;
		NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Shutdown()&lt;br /&gt;
{&lt;br /&gt;
	/* Remove the type on shutdown */&lt;br /&gt;
	g_pHandleSys-&amp;gt;RemoveType(g_FileType, myself-&amp;gt;GetIdentity());&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creating Handles===&lt;br /&gt;
Creating the Handles is fairly easy once we have a valid pointer to stuff in it.&lt;br /&gt;
&amp;lt;cpp&amp;gt;/* native CreateFile(const String:file[]) */&lt;br /&gt;
static cell_t sm_CreateFile(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	char path[PLATFORM_MAX_PATH];&lt;br /&gt;
	char *filename;&lt;br /&gt;
&lt;br /&gt;
	/* Get the filename */&lt;br /&gt;
	pContext-&amp;gt;LocalToString(params[1], &amp;amp;filename);&lt;br /&gt;
	/* Build a full path */&lt;br /&gt;
	g_pSM-&amp;gt;BuildPath(Path_SM, path, sizeof(path), &amp;quot;%s&amp;quot;, filename);&lt;br /&gt;
	&lt;br /&gt;
	/* Open for writing */&lt;br /&gt;
	FILE *fp = fopen(path, &amp;quot;wt&amp;quot;);&lt;br /&gt;
	if (!fp)&lt;br /&gt;
	{&lt;br /&gt;
		return BAD_HANDLE;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Create the Handle with our type, the FILE pointer, the plugin's identity, and our identity */&lt;br /&gt;
	return g_pHandleSys-&amp;gt;CreateHandle(g_FileType, &lt;br /&gt;
		fp, &lt;br /&gt;
		pContext-&amp;gt;GetIdentity(), &lt;br /&gt;
		myself-&amp;gt;GetIdentity(), &lt;br /&gt;
		NULL);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Reading/Checking Handles===&lt;br /&gt;
Handles aren't very useful unless you have natives to use them.  Let's say we want to write lines of text to our File type.&lt;br /&gt;
&amp;lt;cpp&amp;gt;/* native WriteLine(Handle:hndl, const String:line[]); */&lt;br /&gt;
static cell_t sm_WriteLine(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	Handle_t hndl = static_cast&amp;lt;Handle_t&amp;gt;(params[1]);&lt;br /&gt;
	HandleError err;&lt;br /&gt;
	HandleSecurity sec;&lt;br /&gt;
&lt;br /&gt;
	/* Build our security descriptor */&lt;br /&gt;
	sec.pOwner = NULL;	/* Not needed, owner access is not checked */&lt;br /&gt;
	sec.pIdentity = myself-&amp;gt;GetIdentity();	/* But only this extension can read */&lt;br /&gt;
&lt;br /&gt;
	/* Attempt to read the given handle as our type, using our security info.&lt;br /&gt;
	 * Note that we read the pointer directly in with a little cast.&lt;br /&gt;
	 * This type of cast is safe since sizeof(void **) == sizeof(void *) == sizeof(T *) in almost all cases.&lt;br /&gt;
	 */&lt;br /&gt;
	FILE *fp;&lt;br /&gt;
	if ((err = g_pHandleSys-&amp;gt;ReadHandle(hndl, g_FileType, &amp;amp;sec, (void **)&amp;amp;fp))&lt;br /&gt;
	     != HandleError_None)&lt;br /&gt;
	{&lt;br /&gt;
		return pContext-&amp;gt;ThrowNativeError(&amp;quot;Invalid file handle %x (error %d)&amp;quot;, hndl, err);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Get the text */&lt;br /&gt;
	char *text;&lt;br /&gt;
	pContext-&amp;gt;LocalToString(params[2], &amp;amp;text);&lt;br /&gt;
&lt;br /&gt;
	/* Write it */&lt;br /&gt;
	fputs(text, fp);&lt;br /&gt;
&lt;br /&gt;
	return 1;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===CloseHandle Support===&lt;br /&gt;
Lastly, we need to make it so &amp;lt;tt&amp;gt;CloseHandle()&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FreeHandle()&amp;lt;/tt&amp;gt; will close our file pointer when removing the Handle, which we skipped before.&lt;br /&gt;
&amp;lt;cpp&amp;gt;class FileTypeHandler : public IHandleTypeDispatch&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
	void OnHandleDestroy(HandleType_t type, void *object)&lt;br /&gt;
	{&lt;br /&gt;
		fclose( (FILE *)object );&lt;br /&gt;
	}&lt;br /&gt;
};&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Restricting CloseHandle==&lt;br /&gt;
Let's say that, for various reasons, you don't want users to be able to call CloseHandle().  An example of this might be a data type that is non-temporary, or is being called from a forward, and thus should not be touched.  Or, you might have a special deconstructor that takes extra parameters, and thus you need a separate destroy function.&lt;br /&gt;
&lt;br /&gt;
For example, let's create a separate function called &amp;lt;tt&amp;gt;CloseFile&amp;lt;/tt&amp;gt;.  It doesn't do anything particularly special, but we are going to force its usage over CloseHandle().&lt;br /&gt;
&lt;br /&gt;
===New Security Rules===&lt;br /&gt;
&amp;lt;cpp&amp;gt;Initialize()&lt;br /&gt;
{&lt;br /&gt;
	/* Create default access rights */&lt;br /&gt;
	HandleAccess rules;&lt;br /&gt;
	g_pHandleSys-&amp;gt;InitAccessDefaults(NULL, &amp;amp;rules);&lt;br /&gt;
&lt;br /&gt;
	/* Restrict delete to only our identity */&lt;br /&gt;
	rules.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY;&lt;br /&gt;
&lt;br /&gt;
	/* Register the type with our security permissions */&lt;br /&gt;
	g_FileType = g_pHandleSys-&amp;gt;CreateType(&amp;quot;File&amp;quot;, &lt;br /&gt;
			&amp;amp;g_FileTypeHandler, &lt;br /&gt;
			0, &lt;br /&gt;
			NULL, &lt;br /&gt;
			&amp;amp;rules, &lt;br /&gt;
			myself-&amp;gt;GetIdentity(), &lt;br /&gt;
			NULL);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Implementing the Native===&lt;br /&gt;
&amp;lt;cpp&amp;gt;/* native Closefile(Handle:hndl); */&lt;br /&gt;
static cell_t sm_CloseFile(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	Handle_t hndl = static_cast&amp;lt;Handle_t&amp;gt;(params[1]);&lt;br /&gt;
	HandleError err;&lt;br /&gt;
	HandleSecurity sec;&lt;br /&gt;
&lt;br /&gt;
	/* Build our security descriptor */&lt;br /&gt;
	sec.pOwner = pContext-&amp;gt;GetIdentity();	/* Needed, HANDLE_RESTRICT_OWNER is default */&lt;br /&gt;
	sec.pIdentity = myself-&amp;gt;GetIdentity();	/* But only this extension can read */&lt;br /&gt;
&lt;br /&gt;
	/* Attempt to read the given handle as our type, using our security info.&lt;br /&gt;
	 * Note that we read the pointer directly in with a little cast.&lt;br /&gt;
	 * This type of cast is safe since sizeof(void **) == sizeof(void *) == sizeof(T *) in almost all cases.&lt;br /&gt;
	 */&lt;br /&gt;
	FILE *fp;&lt;br /&gt;
	if ((err = g_pHandleSys-&amp;gt;FreeHandle(hndl, &amp;amp;sec))&lt;br /&gt;
	     != HandleError_None)&lt;br /&gt;
	{&lt;br /&gt;
		return pContext-&amp;gt;ThrowNativeError(&amp;quot;Invalid file handle %x (error %d)&amp;quot;, hndl, err);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 1;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Restricting CloseHandle Per-Handle==&lt;br /&gt;
Taking our above example, it is possible that we might want some Handles to be closed via CloseHandle(), but others not.  Again, this is useful if you wish to pass a Handle as read-only to a plugin, commonly done when using non-temporary structures or Handles used in Forwards.&lt;br /&gt;
&lt;br /&gt;
In this example, we'll create a global instance of our file type, and this instance will be denied access to CloseHandle(), whereas files returned by OpenFile() will not.&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
&amp;lt;cpp&amp;gt;Handle_t g_GlobalFile;&lt;br /&gt;
&lt;br /&gt;
Initialize()&lt;br /&gt;
{&lt;br /&gt;
	/* Register the type with default security permissions */&lt;br /&gt;
	g_FileType = g_pHandleSys-&amp;gt;CreateType(&amp;quot;File&amp;quot;, &lt;br /&gt;
			&amp;amp;g_FileTypeHandler, &lt;br /&gt;
			0, &lt;br /&gt;
			NULL, &lt;br /&gt;
			NULL, &lt;br /&gt;
			myself-&amp;gt;GetIdentity(), &lt;br /&gt;
			NULL);&lt;br /&gt;
&lt;br /&gt;
	/* Create our 'global' file */&lt;br /&gt;
	FILE *fp = tmpfile();&lt;br /&gt;
&lt;br /&gt;
	/* Set up the security descriptor */&lt;br /&gt;
	HandleSecurity sec;&lt;br /&gt;
	sec.pOwner = NULL;		/* No owner for this Handle */&lt;br /&gt;
	sec.pIdentity = myself-&amp;gt;GetIdentity();	/* Only this identity will be allowed */&lt;br /&gt;
&lt;br /&gt;
	/* Set up the access permissions */&lt;br /&gt;
	HandleAccess rules;&lt;br /&gt;
	g_pHandleSys-&amp;gt;InitAccessDefaults(NULL, &amp;amp;rules);&lt;br /&gt;
	rules.access[HandleAccess_Delete] |= HANDLE_RESTRICT_IDENTITY;&lt;br /&gt;
&lt;br /&gt;
	/* Finally, create the Handle with our rules */&lt;br /&gt;
	g_GlobalFile = g_pHandleSys-&amp;gt;CreateHandleEx(g_FileType, fp, &amp;amp;sec, &amp;amp;rules, NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Shutdown()&lt;br /&gt;
{&lt;br /&gt;
	/* Remove our global Handle (not needed, but we do it for clarity */&lt;br /&gt;
	HandleSecurity sec;&lt;br /&gt;
	sec.pOwner = NULL;&lt;br /&gt;
	sec.pIdentity = myself-&amp;gt;GetIdentity();&lt;br /&gt;
&lt;br /&gt;
	g_pHandleSys-&amp;gt;FreeHandle(g_GlobalFile, &amp;amp;sec);&lt;br /&gt;
&lt;br /&gt;
	/* Remove the type on shutdown */&lt;br /&gt;
	g_pHandleSys-&amp;gt;RemoveType(g_FileType, myself-&amp;gt;GetIdentity());&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Development]]&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Counter-Strike:_Global_Offensive_Events&amp;diff=10099</id>
		<title>Counter-Strike: Global Offensive Events</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Counter-Strike:_Global_Offensive_Events&amp;diff=10099"/>
		<updated>2016-01-13T19:52:21Z</updated>

		<summary type="html">&lt;p&gt;Fyren: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;:''Refer back to [[Game Events (Source)]] for more events.''&lt;br /&gt;
&lt;br /&gt;
=== player_death ===&lt;br /&gt;
{{qnotice|When a client dies}}&lt;br /&gt;
{{begin-hl2msg|player_death|string}}&lt;br /&gt;
{{hl2msg|short|userid|user ID who died}}&lt;br /&gt;
{{hl2msg|short|attacker|user ID who killed}}&lt;br /&gt;
{{hl2msg|short|assister|user ID who assisted in the kill}}&lt;br /&gt;
{{hl2msg|string|weapon|weapon name killer used }}&lt;br /&gt;
{{hl2msg|string|weapon_itemid|inventory item id of weapon killer used}}&lt;br /&gt;
{{hl2msg|string|weapon_fauxitemid|faux item id of weapon killer used}}&lt;br /&gt;
{{hl2msg|string|weapon_originalowner_xuid|}}&lt;br /&gt;
{{hl2msg|bool|headshot|singals a headshot}}&lt;br /&gt;
{{hl2msg|short|dominated|did killer dominate victim with this kill}}&lt;br /&gt;
{{hl2msg|short|revenge|did killer get revenge on victim with this kill}}&lt;br /&gt;
{{hl2msg|short|penetrated|number of objects shot penetrated before killing target}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== player_hurt ===&lt;br /&gt;
{{qnotice|When a client is damaged}}&lt;br /&gt;
{{begin-hl2msg|player_hurt|string}}&lt;br /&gt;
{{hl2msg|short|userid|user ID who was hurt}}&lt;br /&gt;
{{hl2msg|short|attacker|user ID who attacked}}&lt;br /&gt;
{{hl2msg|byte|health|remaining health points}}&lt;br /&gt;
{{hl2msg|byte|armor|remaining armor points}}&lt;br /&gt;
{{hl2msg|string|weapon|weapon name attacker used, if not the world}}&lt;br /&gt;
{{hl2msg|short|dmg_health|damage done to health}}&lt;br /&gt;
{{hl2msg|byte|dmg_armor|damage done to armor}}&lt;br /&gt;
{{hl2msg|byte|hitgroup|hitgroup that was damaged ; &amp;lt;nowiki&amp;gt;1=hs 2=upper torso 3=lower torso 4=left arm 5=right arm 6=left leg 7=right leg&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== item_purchase ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|item_purchase|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|short|team|}}&lt;br /&gt;
{{hl2msg|string|weapon|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== bomb_beginplant ===&lt;br /&gt;
{{qnotice|When the bomb is starting to get planted}}&lt;br /&gt;
{{begin-hl2msg|bomb_beginplant|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who is planting the bomb}}&lt;br /&gt;
{{hl2msg|short|site|bombsite index}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== bomb_abortplant ===&lt;br /&gt;
{{qnotice|When the bomb planter stops planting the bomb}}&lt;br /&gt;
{{begin-hl2msg|bomb_abortplant|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who is planting the bomb}}&lt;br /&gt;
{{hl2msg|short|site|bombsite index}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== bomb_planted ===&lt;br /&gt;
{{qnotice|When the bomb has been planted}}&lt;br /&gt;
{{begin-hl2msg|bomb_planted|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who planted the bomb}}&lt;br /&gt;
{{hl2msg|short|site|bombsite index}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== bomb_defused ===&lt;br /&gt;
{{qnotice|When the bomb has been defused}}&lt;br /&gt;
{{begin-hl2msg|bomb_defused|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who defused the bomb}}&lt;br /&gt;
{{hl2msg|short|site|bombsite index}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== bomb_exploded ===&lt;br /&gt;
{{qnotice|When the bomb explodes}}&lt;br /&gt;
{{begin-hl2msg|bomb_exploded|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who planted the bomb}}&lt;br /&gt;
{{hl2msg|short|site|bombsite index}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== bomb_dropped ===&lt;br /&gt;
{{qnotice|When the bomb is dropped by a client}}&lt;br /&gt;
{{begin-hl2msg|bomb_dropped|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who dropped the bomb}}&lt;br /&gt;
{{hl2msg|long|entindex|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== bomb_pickup ===&lt;br /&gt;
{{qnotice|When the bomb is picked up by a client}}&lt;br /&gt;
{{begin-hl2msg|bomb_pickup|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who picked up the bomb}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== defuser_dropped ===&lt;br /&gt;
{{qnotice|When the defuser is dropped by a client}}&lt;br /&gt;
{{begin-hl2msg|defuser_dropped|string}}&lt;br /&gt;
{{hl2msg|long|entityid|defuser's entity ID}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== defuser_pickup ===&lt;br /&gt;
{{qnotice|When the defuser is picked up by a client}}&lt;br /&gt;
{{begin-hl2msg|defuser_pickup|string}}&lt;br /&gt;
{{hl2msg|long|entityid|defuser's entity ID}}&lt;br /&gt;
{{hl2msg|short|userid|player who picked up the defuser}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== announce_phase_end ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|announce_phase_end|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== cs_intermission ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|cs_intermission|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== bomb_begindefuse ===&lt;br /&gt;
{{qnotice|When the bomb is started to be defused}}&lt;br /&gt;
{{begin-hl2msg|bomb_begindefuse|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who is defusing}}&lt;br /&gt;
{{hl2msg|bool|haskit|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== bomb_abortdefuse ===&lt;br /&gt;
{{qnotice|When the bomb defusal is stopped}}&lt;br /&gt;
{{begin-hl2msg|bomb_abortdefuse|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who was defusing}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== hostage_follows ===&lt;br /&gt;
{{qnotice|When the hostage begins following a client}}&lt;br /&gt;
{{begin-hl2msg|hostage_follows|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who touched the hostage}}&lt;br /&gt;
{{hl2msg|short|hostage|hostage entity index}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== hostage_hurt ===&lt;br /&gt;
{{qnotice|When a hostage is damaged}}&lt;br /&gt;
{{begin-hl2msg|hostage_hurt|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who hurt the hostage}}&lt;br /&gt;
{{hl2msg|short|hostage|hostage entity index}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== hostage_killed ===&lt;br /&gt;
{{qnotice|When a hostage is killed}}&lt;br /&gt;
{{begin-hl2msg|hostage_killed|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who killed the hostage}}&lt;br /&gt;
{{hl2msg|short|hostage|hostage entity index}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== hostage_rescued ===&lt;br /&gt;
{{qnotice|When a hostage is rescued}}&lt;br /&gt;
{{begin-hl2msg|hostage_rescued|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who rescued the hostage}}&lt;br /&gt;
{{hl2msg|short|hostage|hostage entity index}}&lt;br /&gt;
{{hl2msg|short|site|rescue site index}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== hostage_stops_following ===&lt;br /&gt;
{{qnotice|When a hostage stops following a client}}&lt;br /&gt;
{{begin-hl2msg|hostage_stops_following|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who rescued the hostage}}&lt;br /&gt;
{{hl2msg|short|hostage|hostage entity index}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== hostage_rescued_all ===&lt;br /&gt;
{{qnotice|When all the hostages are rescued}}&lt;br /&gt;
{{begin-hl2msg|hostage_rescued_all|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== hostage_call_for_help ===&lt;br /&gt;
{{qnotice|When the hostage calls for help}}&lt;br /&gt;
{{begin-hl2msg|hostage_call_for_help|string}}&lt;br /&gt;
{{hl2msg|short|hostage|hostage entity index}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== vip_escaped ===&lt;br /&gt;
{{qnotice|When the VIP escapes}}&lt;br /&gt;
{{begin-hl2msg|vip_escaped|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who was the VIP}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== vip_killed ===&lt;br /&gt;
{{qnotice|When the VIP is killed}}&lt;br /&gt;
{{begin-hl2msg|vip_killed|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who was the VIP}}&lt;br /&gt;
{{hl2msg|short|attacker|user ID who killed the VIP}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== player_radio ===&lt;br /&gt;
{{qnotice|When the player uses radio commands}}&lt;br /&gt;
{{begin-hl2msg|player_radio|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|short|slot|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== bomb_beep ===&lt;br /&gt;
{{qnotice|Every time the bomb beep sound happens}}&lt;br /&gt;
{{begin-hl2msg|bomb_beep|string}}&lt;br /&gt;
{{hl2msg|long|entindex|c4 entity}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== weapon_fire ===&lt;br /&gt;
{{qnotice|Every time a client fires their weapon}}&lt;br /&gt;
{{begin-hl2msg|weapon_fire|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|string|weapon|weapon name used}}&lt;br /&gt;
{{hl2msg|bool|silenced|is weapon silenced}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== weapon_fire_on_empty ===&lt;br /&gt;
{{qnotice|Every time a client fires their weapon and it's empty}}&lt;br /&gt;
{{begin-hl2msg|weapon_fire_on_empty|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|string|weapon|weapon name used}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== weapon_outofammo ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|weapon_outofammo|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== weapon_reload ===&lt;br /&gt;
{{qnotice|Every time a client reloads their weapon}}&lt;br /&gt;
{{begin-hl2msg|weapon_reload|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== weapon_zoom ===&lt;br /&gt;
{{qnotice|Every time a client zooms a scoped weapon}}&lt;br /&gt;
{{begin-hl2msg|weapon_zoom|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== silencer_detach ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|silencer_detach|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== inspect_weapon ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|inspect_weapon|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== weapon_zoom_rifle ===&lt;br /&gt;
{{qnotice|exists for the game instructor to let it know when the player zoomed in with a regular rifle. Different from the above weapon_zoom because we don't use this event to notify bots}}&lt;br /&gt;
{{begin-hl2msg|weapon_zoom_rifle|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== player_spawned ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|player_spawned|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|bool|inrestart|true if restart is pending}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== item_pickup ===&lt;br /&gt;
{{qnotice|Every time an item is picked up (generally weapons)}}&lt;br /&gt;
{{begin-hl2msg|item_pickup|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|string|item|either a weapon such as 'tmp' or 'hegrenade', or an item such as 'nvgs'}}&lt;br /&gt;
{{hl2msg|bool|silent|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== ammo_pickup ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|ammo_pickup|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|string|item|either a weapon such as 'tmp' or 'hegrenade', or an item such as 'nvgs'}}&lt;br /&gt;
{{hl2msg|long|index|the weapon entindex}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== item_equip ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|item_equip|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|string|item|either a weapon such as 'tmp' or 'hegrenade', or an item such as 'nvgs'}}&lt;br /&gt;
{{hl2msg|bool|canzoom|}}&lt;br /&gt;
{{hl2msg|bool|hassilencer|}}&lt;br /&gt;
{{hl2msg|bool|issilenced|}}&lt;br /&gt;
{{hl2msg|bool|hastracers|}}&lt;br /&gt;
{{hl2msg|short|weptype|see below}}&lt;br /&gt;
{{hl2msg|''none''|''none''|WEAPONTYPE_UNKNOWN		&amp;amp;#61;	-1}}&lt;br /&gt;
{{hl2msg|''none''|''none''|WEAPONTYPE_KNIFE			&amp;amp;#61;	0}}&lt;br /&gt;
{{hl2msg|''none''|''none''|WEAPONTYPE_PISTOL		&amp;amp;#61;	1}}&lt;br /&gt;
{{hl2msg|''none''|''none''|WEAPONTYPE_SUBMACHINEGUN	&amp;amp;#61;	2}}&lt;br /&gt;
{{hl2msg|''none''|''none''|WEAPONTYPE_RIFLE			&amp;amp;#61;	3}}&lt;br /&gt;
{{hl2msg|''none''|''none''|WEAPONTYPE_SHOTGUN		&amp;amp;#61;	4}}&lt;br /&gt;
{{hl2msg|''none''|''none''|WEAPONTYPE_SNIPER_RIFLE	&amp;amp;#61;	5}}&lt;br /&gt;
{{hl2msg|''none''|''none''|WEAPONTYPE_MACHINEGUN	&amp;amp;#61;	6}}&lt;br /&gt;
{{hl2msg|''none''|''none''|WEAPONTYPE_C4			&amp;amp;#61;	7}}&lt;br /&gt;
{{hl2msg|''none''|''none''|WEAPONTYPE_GRENADE		&amp;amp;#61;	8}}&lt;br /&gt;
{{hl2msg|bool|ispainted|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== enter_buyzone ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|enter_buyzone|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|bool|canbuy|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== exit_buyzone ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|exit_buyzone|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|bool|canbuy|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== buytime_ended ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|buytime_ended|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== enter_bombzone ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|enter_bombzone|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|bool|hasbomb|}}&lt;br /&gt;
{{hl2msg|bool|isplanted|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== exit_bombzone ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|exit_bombzone|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|bool|hasbomb|}}&lt;br /&gt;
{{hl2msg|bool|isplanted|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== enter_rescue_zone ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|enter_rescue_zone|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== exit_rescue_zone ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|exit_rescue_zone|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== silencer_off ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|silencer_off|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== silencer_on ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|silencer_on|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== buymenu_open ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|buymenu_open|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== buymenu_close ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|buymenu_close|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== round_prestart ===&lt;br /&gt;
{{qnotice|sent before all other round restart actions}}&lt;br /&gt;
{{begin-hl2msg|round_prestart|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== round_poststart ===&lt;br /&gt;
{{qnotice|sent after all other round restart actions}}&lt;br /&gt;
{{begin-hl2msg|round_poststart|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== round_start ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|round_start|string}}&lt;br /&gt;
{{hl2msg|long|timelimit|round time limit in seconds}}&lt;br /&gt;
{{hl2msg|long|fraglimit|frag limit in seconds}}&lt;br /&gt;
{{hl2msg|string|objective|round objective}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== round_end ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|round_end|string}}&lt;br /&gt;
{{hl2msg|byte|winner|winner team/user id}}&lt;br /&gt;
{{hl2msg|byte|reason|reson why team won}}&lt;br /&gt;
{{hl2msg|string|message|round end round message }}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== grenade_bounce ===&lt;br /&gt;
{{qnotice|Every time a grenade bounces}}&lt;br /&gt;
{{begin-hl2msg|grenade_bounce|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== hegrenade_detonate ===&lt;br /&gt;
{{qnotice|Every time a hegrenade explodes}}&lt;br /&gt;
{{begin-hl2msg|hegrenade_detonate|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|short|entityid|}}&lt;br /&gt;
{{hl2msg|float|x|}}&lt;br /&gt;
{{hl2msg|float|y|}}&lt;br /&gt;
{{hl2msg|float|z|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== flashbang_detonate ===&lt;br /&gt;
{{qnotice|Every time a flashbang detonates}}&lt;br /&gt;
{{begin-hl2msg|flashbang_detonate|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|short|entityid|}}&lt;br /&gt;
{{hl2msg|float|x|}}&lt;br /&gt;
{{hl2msg|float|y|}}&lt;br /&gt;
{{hl2msg|float|z|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== smokegrenade_detonate ===&lt;br /&gt;
{{qnotice|Every time a smokegrenade detonates}}&lt;br /&gt;
{{begin-hl2msg|smokegrenade_detonate|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|short|entityid|}}&lt;br /&gt;
{{hl2msg|float|x|}}&lt;br /&gt;
{{hl2msg|float|y|}}&lt;br /&gt;
{{hl2msg|float|z|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== smokegrenade_expired ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|smokegrenade_expired|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|short|entityid|}}&lt;br /&gt;
{{hl2msg|float|x|}}&lt;br /&gt;
{{hl2msg|float|y|}}&lt;br /&gt;
{{hl2msg|float|z|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== molotov_detonate ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|molotov_detonate|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|float|x|}}&lt;br /&gt;
{{hl2msg|float|y|}}&lt;br /&gt;
{{hl2msg|float|z|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== decoy_detonate ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|decoy_detonate|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|short|entityid|}}&lt;br /&gt;
{{hl2msg|float|x|}}&lt;br /&gt;
{{hl2msg|float|y|}}&lt;br /&gt;
{{hl2msg|float|z|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== decoy_started ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|decoy_started|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|short|entityid|}}&lt;br /&gt;
{{hl2msg|float|x|}}&lt;br /&gt;
{{hl2msg|float|y|}}&lt;br /&gt;
{{hl2msg|float|z|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== inferno_startburn ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|inferno_startburn|string}}&lt;br /&gt;
{{hl2msg|short|entityid|}}&lt;br /&gt;
{{hl2msg|float|x|}}&lt;br /&gt;
{{hl2msg|float|y|}}&lt;br /&gt;
{{hl2msg|float|z|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== inferno_expire ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|inferno_expire|string}}&lt;br /&gt;
{{hl2msg|short|entityid|}}&lt;br /&gt;
{{hl2msg|float|x|}}&lt;br /&gt;
{{hl2msg|float|y|}}&lt;br /&gt;
{{hl2msg|float|z|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== inferno_extinguish ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|inferno_extinguish|string}}&lt;br /&gt;
{{hl2msg|short|entityid|}}&lt;br /&gt;
{{hl2msg|float|x|}}&lt;br /&gt;
{{hl2msg|float|y|}}&lt;br /&gt;
{{hl2msg|float|z|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== decoy_firing ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|decoy_firing|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|short|entityid|}}&lt;br /&gt;
{{hl2msg|float|x|}}&lt;br /&gt;
{{hl2msg|float|y|}}&lt;br /&gt;
{{hl2msg|float|z|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== bullet_impact ===&lt;br /&gt;
{{qnotice|Every time a bullet hits something}}&lt;br /&gt;
{{begin-hl2msg|bullet_impact}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|float|x|}}&lt;br /&gt;
{{hl2msg|float|y|}}&lt;br /&gt;
{{hl2msg|float|z|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== player_footstep ===&lt;br /&gt;
{{qnotice|Every time a player takes a step}}&lt;br /&gt;
{{begin-hl2msg|player_footstep|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== player_jump ===&lt;br /&gt;
{{qnotice|Every time a player jumps}}&lt;br /&gt;
{{begin-hl2msg|player_jump|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== player_blind ===&lt;br /&gt;
{{qnotice|Every time a player is blinded by a flashbang}}&lt;br /&gt;
{{begin-hl2msg|player_blind|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== player_falldamage ===&lt;br /&gt;
{{qnotice|Every time a player takes damage due to a fall}}&lt;br /&gt;
{{begin-hl2msg|player_falldamage|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|float|damage|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== door_moving ===&lt;br /&gt;
{{qnotice|Every time a door is put in motion (opened)}}&lt;br /&gt;
{{begin-hl2msg|door_moving|string}}&lt;br /&gt;
{{hl2msg|long|entindex|}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== round_freeze_end ===&lt;br /&gt;
{{qnotice|When the round's mp_freezetime is up}}&lt;br /&gt;
{{begin-hl2msg|round_freeze_end|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== mb_input_lock_success ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|mb_input_lock_success|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== mb_input_lock_cancel ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|mb_input_lock_cancel|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== nav_blocked ===&lt;br /&gt;
{{qnotice|''Guess: Called when an area is blocked by the nav of a map''}}&lt;br /&gt;
{{begin-hl2msg|nav_blocked|string}}&lt;br /&gt;
{{hl2msg|long|area|}}&lt;br /&gt;
{{hl2msg|bool|blocked|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== nav_generate ===&lt;br /&gt;
{{qnotice|Called when a nav file does not exist for a map and bots are added}}&lt;br /&gt;
{{begin-hl2msg|nav_generate|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== player_stats_updated ===&lt;br /&gt;
{{qnotice|''Guess: Called when the player stats (achievments) are sent to valve''}}&lt;br /&gt;
{{begin-hl2msg|player_stats_updated|string}}&lt;br /&gt;
{{hl2msg|bool|forceupload|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== achievement_info_loaded ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|achievement_info_loaded|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== spec_target_updated ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|spec_target_updated|string}}&lt;br /&gt;
{{hl2msg|byte|userid|entindex of the player}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== spec_mode_updated ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|spec_target_updated|string}}&lt;br /&gt;
{{hl2msg|byte|userid|entindex of the player}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== hltv_changed_mode ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|hltv_changed_mode|string}}&lt;br /&gt;
{{hl2msg|long|oldmode|}}&lt;br /&gt;
{{hl2msg|long|newmode|}}&lt;br /&gt;
{{hl2msg|long|obs_target|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== cs_game_disconnected ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|cs_game_disconnected|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== cs_win_panel_round ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|cs_win_panel_round|string}}&lt;br /&gt;
{{hl2msg|bool|show_timer_defend|}}&lt;br /&gt;
{{hl2msg|bool|show_timer_attack|}}&lt;br /&gt;
{{hl2msg|short|timer_time|}}&lt;br /&gt;
{{hl2msg|byte|final_event|defined in cs_gamerules.h}}&lt;br /&gt;
{{hl2msg|string|funfact_token|}}&lt;br /&gt;
{{hl2msg|short|funfact_player|}}&lt;br /&gt;
{{hl2msg|long|funfact_data1|}}&lt;br /&gt;
{{hl2msg|long|funfact_data2|}}&lt;br /&gt;
{{hl2msg|long|funfact_data3|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== cs_win_panel_match ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|cs_win_panel_match|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|Well nothing defined in CS:GO but maybe it's the same as in CS:S}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== cs_match_end_restart ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|cs_match_end_restart|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== cs_pre_restart ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|cs_pre_restart|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== show_freezepanel ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|show_freezepanel|string}}&lt;br /&gt;
{{hl2msg|short|victim|endindex of the one who was killed}}&lt;br /&gt;
{{hl2msg|short|killer|entindex of the killer entity}}&lt;br /&gt;
{{hl2msg|short|hits_taken|}}&lt;br /&gt;
{{hl2msg|short|damage_taken|}}&lt;br /&gt;
{{hl2msg|short|hits_given|}}&lt;br /&gt;
{{hl2msg|short|damage_given|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== hide_freezepanel ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|hide_freezepanel|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== freezecam_started ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|freezecam_started|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== player_avenged_teammate ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|player_avenged_teammate|string}}&lt;br /&gt;
{{hl2msg|short|avenger_id|}}&lt;br /&gt;
{{hl2msg|short|avenged_player_id|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== achievement_earned ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|achievement_earned|string}}&lt;br /&gt;
{{hl2msg|byte|player|entindex of the player}}&lt;br /&gt;
{{hl2msg|short|achievement|achievement ID}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== achievement_earned_local ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|achievement_earned_local|string}}&lt;br /&gt;
{{hl2msg|short|achievement|achievement ID}}&lt;br /&gt;
{{hl2msg|short|splitscreenplayer|splitscreen ID}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== item_found ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|item_found|string}}&lt;br /&gt;
{{hl2msg|byte|player|entindex of the player}}&lt;br /&gt;
{{hl2msg|byte|quality|quality of the item}}&lt;br /&gt;
{{hl2msg|byte|method|method by which we acquired the item}}&lt;br /&gt;
{{hl2msg|long|itemdef|the item definition index}}&lt;br /&gt;
{{hl2msg|long|itemid|the item id in the players inventory}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== item_gifted ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|item_gifted|string}}&lt;br /&gt;
{{hl2msg|byte|player|entindex of the player who sent the gift}}&lt;br /&gt;
{{hl2msg|long|itemdef|the item definition index of the gift that was opened}}&lt;br /&gt;
{{hl2msg|byte|numgifts|how many recipients got the gifts in this gift batch}}&lt;br /&gt;
{{hl2msg|byte|giftidx|index of recipient in this gift batch (0 for the first recipient, 1 for second, and so on...)}}&lt;br /&gt;
{{hl2msg|long|accountid|gift recipient's account ID}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== repost_xbox_achievements ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|repost_xbox_achievements|string}}&lt;br /&gt;
{{hl2msg|short|splitscreenplayer|splitscreen ID}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== match_end_conditions ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|match_end_conditions|string}}&lt;br /&gt;
{{hl2msg|long|frags|}}&lt;br /&gt;
{{hl2msg|long|max_rounds|}}&lt;br /&gt;
{{hl2msg|long|win_rounds|}}&lt;br /&gt;
{{hl2msg|long|time|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== round_mvp ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|round_mvp|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|short|reason|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== player_decal ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|player_decal|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== teamplay_round_start ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|teamplay_round_start|string}}&lt;br /&gt;
{{hl2msg|bool|full_reset|is this a full reset of the map}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== client_disconnect===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|client_disconnect|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== gg_player_levelup ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|gg_player_levelup|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who leveled up}}&lt;br /&gt;
{{hl2msg|short|weaponrank|}}&lt;br /&gt;
{{hl2msg|string|weaponname|name of weapon being awarded}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== ggtr_player_levelup ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|ggtr_player_levelup|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who leveled up}}&lt;br /&gt;
{{hl2msg|short|weaponrank|}}&lt;br /&gt;
{{hl2msg|string|weaponname|name of weapon being awarded}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== ggprogressive_player_levelup ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|ggprogressive_player_levelup|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who leveled up}}&lt;br /&gt;
{{hl2msg|short|weaponrank|}}&lt;br /&gt;
{{hl2msg|string|weaponname|name of weapon being awarded}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== gg_killed_enemy ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|gg_killed_enemy|string}}&lt;br /&gt;
{{hl2msg|short|victimid|user ID who died}}&lt;br /&gt;
{{hl2msg|short|attackerid|user ID who killed}}&lt;br /&gt;
{{hl2msg|short|dominated|did killer dominate victim with this kill}}&lt;br /&gt;
{{hl2msg|short|revenge|did killer get revenge on victim with this kill}}&lt;br /&gt;
{{hl2msg|bool|bonus|did killer kill with a bonus weapon?}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== gg_final_weapon_achieved ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|gg_final_weapon_achieved|string}}&lt;br /&gt;
{{hl2msg|short|playerid|user ID who achieved the final gun game weapon}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== gg_bonus_grenade_achieved ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|gg_bonus_grenade_achieved|string}}&lt;br /&gt;
{{hl2msg|short|userid|user ID who achieved the bonus grenade}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== switch_team ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|switch_team|string}}&lt;br /&gt;
{{hl2msg|short|numPlayers|number of active players on both T and CT}}&lt;br /&gt;
{{hl2msg|short|numSpectators|number of spectators}}&lt;br /&gt;
{{hl2msg|short|avg_rank|average rank of human players}}&lt;br /&gt;
{{hl2msg|short|numTSlotsFree|}}&lt;br /&gt;
{{hl2msg|short|numCTSlotsFree|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== gg_leader ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|gg_leader|string}}&lt;br /&gt;
{{hl2msg|short|playerid|user ID that is currently in the lead}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== gg_player_impending_upgrade ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|gg_player_impending_upgrade|string}}&lt;br /&gt;
{{hl2msg|short|userid|player who will be leveling up}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== write_profile_data ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|write_profile_data|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== trial_time_expired ===&lt;br /&gt;
{{qnotice|fired when a player runs out of time in trial mode}}&lt;br /&gt;
{{begin-hl2msg|trial_time_expired|string}}&lt;br /&gt;
{{hl2msg|short|slot|player whose time has expired}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== update_matchmaking_stats ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|update_matchmaking_stats|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== player_reset_vote ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|player_reset_vote|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|short|vote|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== enable_restart_voting ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|enable_restart_voting|string}}&lt;br /&gt;
{{hl2msg|bool|enable|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== sfuievent ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|sfuievent|string}}&lt;br /&gt;
{{hl2msg|string|action|}}&lt;br /&gt;
{{hl2msg|string|data|}}&lt;br /&gt;
{{hl2msg|byte|slot|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== start_vote ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|start_vote|string}}&lt;br /&gt;
{{hl2msg|short|userid|user ID on server}}&lt;br /&gt;
{{hl2msg|byte|type|}}&lt;br /&gt;
{{hl2msg|short|vote_parameter|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== player_given_c4 ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|player_given_c4|string}}&lt;br /&gt;
{{hl2msg|short|userid|user ID who received the c4}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== gg_reset_round_start_sounds ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|gg_reset_round_start_sounds|string}}&lt;br /&gt;
{{hl2msg|short|userid|user ID who should have round start sounds reset}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== tr_player_flashbanged ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|tr_player_flashbanged|string}}&lt;br /&gt;
{{hl2msg|short|userid|user ID of the player banged}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== tr_highlight_ammo ===&lt;br /&gt;
{{qnotice|not used yet because this relied on vgui panels, scaleform isn't supported yet}}&lt;br /&gt;
{{begin-hl2msg|tr_highlight_ammo|string}}&lt;br /&gt;
{{hl2msg|short|userid|user ID of the player}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== tr_mark_complete ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|tr_mark_complete|string}}&lt;br /&gt;
{{hl2msg|short|complete|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== tr_mark_best_time ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|tr_mark_best_time|string}}&lt;br /&gt;
{{hl2msg|long|time|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== tr_exit_hint_trigger ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|tr_exit_hint_trigger|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== bot_takeover ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|bot_takeover|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|short|botid|}}&lt;br /&gt;
{{hl2msg|short|index|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== tr_show_finish_msgbox ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|tr_show_finish_msgbox|string}}&lt;br /&gt;
{{hl2msg|short|userid|user ID of the player}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== tr_show_exit_msgbox ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|tr_show_exit_msgbox|string}}&lt;br /&gt;
{{hl2msg|short|userid|user ID of the player}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== reset_player_controls ===&lt;br /&gt;
{{qnotice|used for demos}}&lt;br /&gt;
{{begin-hl2msg|reset_player_controls|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== jointeam_failed ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|jointeam_failed|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|byte|reason|3 = 0 = team_full}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== teamchange_pending ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|teamchange_pending|string}}&lt;br /&gt;
{{hl2msg|short|userid|}}&lt;br /&gt;
{{hl2msg|byte|toteam|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== material_default_complete ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|material_default_complete|string}}&lt;br /&gt;
{{hl2msg|''none''|''none''|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== cs_prev_next_spectator ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|cs_prev_next_spectator|string}}&lt;br /&gt;
{{hl2msg|bool|next|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== cs_handle_ime_event ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|cs_handle_ime_event|string}}&lt;br /&gt;
{{hl2msg|1|local|}}&lt;br /&gt;
{{hl2msg|string|eventtype|}}&lt;br /&gt;
{{hl2msg|wstring|eventdata|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== nextlevel_changed ===&lt;br /&gt;
{{qnotice|a game event, name may be 32 characters long}}&lt;br /&gt;
{{begin-hl2msg|nextlevel_changed|string}}&lt;br /&gt;
{{hl2msg|string|nextlevel|weapon name killer used}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== seasoncoin_levelup ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|seasoncoin_levelup|string}}&lt;br /&gt;
{{hl2msg|short|player|}}&lt;br /&gt;
{{hl2msg|short|category|}}&lt;br /&gt;
{{hl2msg|short|rank|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== tournament_reward ===&lt;br /&gt;
{{qnotice|-}}&lt;br /&gt;
{{begin-hl2msg|tournament_reward|string}}&lt;br /&gt;
{{hl2msg|long|defindex|}}&lt;br /&gt;
{{hl2msg|long|totalrewards|}}&lt;br /&gt;
{{hl2msg|long|accountid|}}&lt;br /&gt;
{{end-hl2msg}}&lt;br /&gt;
&lt;br /&gt;
=== start_halftime ===&lt;br /&gt;
{{qnotice|}}&lt;br /&gt;
{{begin-hl2msg|start_halftime|string}}&lt;br /&gt;
{{end-hl2msg}}&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Introduction_to_SourceMod_Plugins&amp;diff=10091</id>
		<title>Introduction to SourceMod Plugins</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Introduction_to_SourceMod_Plugins&amp;diff=10091"/>
		<updated>2015-12-22T20:07:07Z</updated>

		<summary type="html">&lt;p&gt;Fyren: Undo revision 10051 by MrTimcakes (talk) - no, &amp;quot;we&amp;quot; don't recommend it&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide will give you a basic introduction to writing a [[SourceMod]] plugin.  If you are not familiar with the SourcePawn language, it is recommended that you at least briefly read the [[Introduction to SourcePawn]] article.&lt;br /&gt;
&lt;br /&gt;
For information on compiling plugins, see [[Compiling SourceMod Plugins]]. You can use [http://www.crimsoneditor.com/ Crimson Editor], [http://www.pspad.com/ PSPad], [http://www.ultraedit.com/ UltraEdit], [http://notepad-plus.sourceforge.net/uk/site.htm Notepad++], [http://www.textpad.com/ TextPad], [http://sourceforge.net/projects/pawnstudio/ Pawn Studio] or any other text editor you're comfortable with to write plugins.&lt;br /&gt;
&lt;br /&gt;
=Starting from scratch=&lt;br /&gt;
Open your favorite text editor and create a new empty file. When you have an empty file you can just start writing code using the core language, however, you will not be able to use any of SourceMod features because the compiler does not now about them. This is done deliberately so it is possible to use SourcePawn outside of SourceMod. But since we are writing a SourceMod plugin, it is a good idea to enable access to SourceMod features first. This it done using &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive. It tells compiler to &amp;quot;paste&amp;quot; the code from another file into yours.&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
How does this work? First of all, note that we enclosed file name into angle brackets. Angle brackets tell the compiler to look in the default include directory. By default, it is '''scripting/include'''. You can open it right now and see a lot of inc files there. Those are SourceMod include files that describe various functions, tags and other features available for SourceMod plugins. The files are plain-text and you are encouraged to read them. You will notice however, that there's not much code in there, certainly not enough to implement all the great features of SourceMod, so where are they? They are implemented inside a SourceMod core which is written in C++ and is compiled into binary files which end up in '''bin''' directory. So how does your SourcePawn code and SM core link together if compiler doesn't know about existence of the latter? SourceMod include files are written specially, so they say that the implementation of functions is ''somewhere else''. Compiler understands that and generate a special code that says that this function call is going outside. When SourceMod loads your plugin, it inspects these bits of code and substitutes it's own internal functions instead. This is called [http://en.wikipedia.org/wiki/Dynamic_linking dynamic linking].&lt;br /&gt;
&lt;br /&gt;
=Setting up plugin info=&lt;br /&gt;
Now that we got access to SourceMod features, it is time to setup the information that will be displayed via &amp;lt;tt&amp;gt;sm plugins list&amp;lt;/tt&amp;gt; command. No one likes unnamed plugins. To do that we are going to look inside '''sourcemod.inc''' file and see the format that information should be declared. It's always helpful to look inside SM include files to find out information you don't know. There is also an [http://docs.sourcemod.net/api/ API documentation] but it can be outdated and it only has SM core files so if your plugin are going to use any third party extension or another plugin, you will have to study inc files. So, open '''sourcemod.inc''' and scroll down a bit until you see this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Plugin public information.&lt;br /&gt;
 */&lt;br /&gt;
struct Plugin&lt;br /&gt;
{&lt;br /&gt;
   public const char[] name;		/**&amp;lt; Plugin Name */&lt;br /&gt;
   public const char[] description;	/**&amp;lt; Plugin Description */&lt;br /&gt;
   public const char[] author;		/**&amp;lt; Plugin Author */&lt;br /&gt;
   public const char[] version;		/**&amp;lt; Plugin Version */&lt;br /&gt;
   public const char[] url;			/**&amp;lt; Plugin URL */&lt;br /&gt;
};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
and this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Declare this as a struct in your plugin to expose its information.&lt;br /&gt;
 * Example:&lt;br /&gt;
 *&lt;br /&gt;
 * public Plugin myinfo =&lt;br /&gt;
 * {&lt;br /&gt;
 *    name = &amp;quot;My Plugin&amp;quot;,&lt;br /&gt;
 *    //etc&lt;br /&gt;
 * };&lt;br /&gt;
 */&lt;br /&gt;
public Plugin myinfo;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It tells us that we need to create a global public variable &amp;lt;tt&amp;gt;myinfo&amp;lt;/tt&amp;gt; which must be of type &amp;lt;tt&amp;gt;Plugin&amp;lt;/tt&amp;gt; which is a struct with 5 fields which themselves are strings. It may sound complicated for a beginner but it's easy. Let's go ahead and create one:&lt;br /&gt;
&amp;lt;pawn&amp;gt;public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;public&amp;lt;/tt&amp;gt; keyword means that SourceMod will be able to directly access our variable. &amp;lt;tt&amp;gt;Plugin:&amp;lt;/tt&amp;gt; defines a type of our variable. &amp;lt;tt&amp;gt;myinfo&amp;lt;/tt&amp;gt; is, obviously, a name of our variable as required by SourceMod. You see that we initialize it right away. This is preferred way to do when filling out plugin info.&lt;br /&gt;
&lt;br /&gt;
After that the full code of your plugin should look like this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Getting code to run=&lt;br /&gt;
We already include SourceMod features and filled up or plugin info. We now have a perfectly well formed plugin which can be compiled and loaded by SourceMod. However, there is one problem - it does nothing. You might be tempted to just start writing a code after &amp;lt;tt&amp;gt;myinfo&amp;lt;/tt&amp;gt; declaration just to see that it will not compile. SourcePawn, unlike other scripting languages like Lua, does not allow a code to be outside of functions. After reading that, you may probably want to just define some function, name it &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt; probably, compile and load a plugin and see that your code never gets called. So how do we make SourceMod call our code? For this exact reason we have forwards. Forwards are function prototypes declared by one party that can be implemented by another party as a [http://en.wikipedia.org/wiki/Callback_%28computer_programming%29 callback]. When a first party starts a forward call, all parties that have matching callbacks receive the call. SourceMod declares a plenty of interesting forwards that we can implement. As you can see, forwards are the only way to get our code executed, keep that in mind. So let's implement &amp;lt;tt&amp;gt;OnPluginStart&amp;lt;/tt&amp;gt; forward. As you may have guessed, it is called when our plugin starts. To do that, we'll have to look up the declaration of &amp;lt;tt&amp;gt;OnPluginStart&amp;lt;/tt&amp;gt;. It is declared inside '''sourcemod.inc''', a file we are already familiar with, let's find it:&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Called when the plugin is fully initialized and all known external references &lt;br /&gt;
 * are resolved. This is only called once in the lifetime of the plugin, and is &lt;br /&gt;
 * paired with OnPluginEnd().&lt;br /&gt;
 *&lt;br /&gt;
 * If any run-time error is thrown during this callback, the plugin will be marked &lt;br /&gt;
 * as failed.&lt;br /&gt;
 *&lt;br /&gt;
 * It is not necessary to close any handles or remove hooks in this function.  &lt;br /&gt;
 * SourceMod guarantees that plugin shutdown automatically and correctly releases &lt;br /&gt;
 * all resources.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
forward void OnPluginStart();&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Empty parentheses tells us that no arguments are passed inside this forward, &amp;lt;tt&amp;gt;@noreturn&amp;lt;/tt&amp;gt; inside documentation tells us that we don't have to return anything, pretty simple forward. So how to write a correct callback for it? Firstly, our callback must have the same name, so it's &amp;lt;tt&amp;gt;OnPluginStart&amp;lt;/tt&amp;gt;, secondly, our callback should have the same number of arguments, none in this case, and lastly, SourceMod needs to be able to call our callback so it needs to be &amp;lt;tt&amp;gt;public&amp;lt;/tt&amp;gt;. So the implementation looks like this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we can write code inside curly braces and it will be executed when our plugin starts. Let's output &amp;lt;tt&amp;gt;&amp;quot;Hello world!&amp;quot;&amp;lt;/tt&amp;gt; to server console. To do that we are going to use &amp;lt;tt&amp;gt;PrintToServer&amp;lt;/tt&amp;gt; function. It is declared inside '''console.inc''', however, we don't need to manually include '''console.inc''' because it is included automatically as part of '''sourcemod.inc'''.&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Sends a message to the server console.&lt;br /&gt;
 *&lt;br /&gt;
 * @param format		Formatting rules.&lt;br /&gt;
 * @param ...			Variable number of format parameters.&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native int PrintToServer(const char[] format, any ...);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
As you can see, this is a native function. It is implemented inside SM core. Judging by it's arguments, we can see that it is a [[Format_Class_Functions_%28SourceMod_Scripting%29|format class function]]. However, we don't need any formatting right now, so let's just pass &amp;lt;tt&amp;gt;&amp;quot;Hello world!&amp;quot;&amp;lt;/tt&amp;gt; string as an only argument:&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	PrintToServer(&amp;quot;Hello world!&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
That's it! The full code of your plugin should look like this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	PrintToServer(&amp;quot;Hello world!&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Compile and load your plugin on your server and see for yourself that the message is displayed in server console.&lt;br /&gt;
&lt;br /&gt;
=Includes=&lt;br /&gt;
Pawn requires '''include files''', much like C requires header files.  Include files list all of the structures, functions, callbacks, and tags that are available.  There are three types of include files:&lt;br /&gt;
*'''Core''' - &amp;lt;tt&amp;gt;sourcemod.inc&amp;lt;/tt&amp;gt; and anything it includes.  These are all provided by SourceMod's Core.&lt;br /&gt;
*'''Extension''' - adds a dependency against a certain extension.&lt;br /&gt;
*'''Plugin''' - adds a dependency against a certain plugin.&lt;br /&gt;
&lt;br /&gt;
Include files are loaded using the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; compiler directive.&lt;br /&gt;
&lt;br /&gt;
=Commands=&lt;br /&gt;
Our first example will be writing a simple admin command to slap a player.  We'll continue to extend this example with more features until we have a final, complete result.&lt;br /&gt;
&lt;br /&gt;
==Declaration==&lt;br /&gt;
First, let's look at what an admin command requires.  Admin commands are registered using the [https://sm.alliedmods.net/new-api/console/RegAdminCmd RegAdminCmd] function.  They require a '''name''', a '''callback function''', and '''default admin flags'''.  &lt;br /&gt;
&lt;br /&gt;
The callback function is what's invoked every time the command is used.  [https://sm.alliedmods.net/new-api/console/ConCmd Click here] to see its prototype.  Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we've successfully implemented a command -- though it doesn't do anything yet.  In fact, it will say &amp;quot;Unknown command&amp;quot; if you use it! This is because you're not returning Plugin_Handled in your callback. Since you haven't,  SourceMod believes you didn't want the Source Engine to know the command was registered, and it handles it so. The reason SourceMod expects your function to return Plugin_Handled is because of the Action tag you put in your function's prototype. The Action tag specifies that Command_MySlap must return one of four things. See the [https://sm.alliedmods.net/new-api/core/Action Action] enumeration in the sourcemod API to learn more about these return types and when to use them.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now the command will report no error, but it still won't do anything. This is because returning &amp;quot;Plugin_Handled&amp;quot; in a command callback will prevent the engine from processing the command. The engine will never even see that the command was run. This is what you will want to do if you are registering a completely new command through SourceMod.&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
Let's decide what the command will look like.  Let's have it act like the default &amp;lt;tt&amp;gt;sm_slap&amp;lt;/tt&amp;gt; command:&lt;br /&gt;
&amp;lt;pre&amp;gt;sm_myslap &amp;lt;name|#userid&amp;gt; [damage]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To implement this, we'll need a few steps:&lt;br /&gt;
*Get the input from the console.  For this we use [https://sm.alliedmods.net/new-api/console/GetCmdArg GetCmdArg()].&lt;br /&gt;
*Find a matching player.  For this we use [https://sm.alliedmods.net/new-api/helpers/FindTarget FindTarget()].&lt;br /&gt;
*Slap them.  For this we use [https://sm.alliedmods.net/new-api/sdktools_functions/SlapPlayer SlapPlayer()], which requires including &amp;lt;tt&amp;gt;sdktools&amp;lt;/tt&amp;gt;, an extension bundled with SourceMod.&lt;br /&gt;
*Respond to the admin.  For this we use [https://sm.alliedmods.net/new-api/console/ReplyToCommand ReplyToCommand()].&lt;br /&gt;
&lt;br /&gt;
Full example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
#include &amp;lt;sdktools&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0.0.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg1[32], arg2[32];&lt;br /&gt;
	int damage;&lt;br /&gt;
&lt;br /&gt;
	/* Get the first argument */&lt;br /&gt;
	GetCmdArg(1, arg1, sizeof(arg1));&lt;br /&gt;
&lt;br /&gt;
	/* If there are 2 or more arguments, and the second argument fetch &lt;br /&gt;
	 * is successful, convert it to an integer.&lt;br /&gt;
	 */&lt;br /&gt;
	if (args &amp;gt;= 2 &amp;amp;&amp;amp; GetCmdArg(2, arg2, sizeof(arg2)))&lt;br /&gt;
	{&lt;br /&gt;
		damage = StringToInt(arg2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Try and find a matching player */&lt;br /&gt;
	int target = FindTarget(client, arg1);&lt;br /&gt;
	if (target == -1)&lt;br /&gt;
	{&lt;br /&gt;
		/* FindTarget() automatically replies with the &lt;br /&gt;
		 * failure reason.&lt;br /&gt;
		 */&lt;br /&gt;
		return Plugin_Handled;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	SlapPlayer(target, damage);&lt;br /&gt;
&lt;br /&gt;
	char name[MAX_NAME_LENGTH];&lt;br /&gt;
	&lt;br /&gt;
	GetClientName(target, name, sizeof(name));&lt;br /&gt;
	ReplyToCommand(client, &amp;quot;[SM] You slapped %s for %d damage!&amp;quot;, name, damage);&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information on what %s and %d are, see [[Format Class Functions (SourceMod Scripting)|Format Class Functions]].  Note that you never need to unregister or remove your admin command.  When a plugin is unloaded, SourceMod cleans it up for you.&lt;br /&gt;
&lt;br /&gt;
=ConVars=&lt;br /&gt;
ConVars, also known as cvars, are global console variables in the Source engine.  They can have integer, float, or string values.  ConVar accessing is done through [[Handles (SourceMod Scripting)|Handles]].  Since ConVars are global, you do not need to close ConVar Handles (in fact, you cannot).&lt;br /&gt;
&lt;br /&gt;
The handy feature of ConVars is that they are easy for users to configure.  They can be placed in any .cfg file, such as &amp;lt;tt&amp;gt;server.cfg&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;sourcemod.cfg&amp;lt;/tt&amp;gt;.  To make this easier, SourceMod has an [https://sm.alliedmods.net/new-api/sourcemod/AutoExecConfig AutoExecConfig()] function.  This function will automatically build a default .cfg file containing all of your cvars, annotated with comments, for users.  It is highly recommend that you call this if you have customizable ConVars.&lt;br /&gt;
&lt;br /&gt;
Let's extend your example from earlier with a new ConVar.  Our ConVar will be &amp;lt;tt&amp;gt;sm_myslap_damage&amp;lt;/tt&amp;gt; and will specify the default damage someone is slapped for if no damage is specified.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;ConVar sm_myslap_damage = null;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
&lt;br /&gt;
	sm_myslap_damage = CreateConVar(&amp;quot;sm_myslap_damage&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;Default slap damage&amp;quot;);&lt;br /&gt;
	AutoExecConfig(true, &amp;quot;plugin_myslap&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg1[32], arg2[32];&lt;br /&gt;
	int damage = GetConVarInt(sm_myslap_damage);&lt;br /&gt;
&lt;br /&gt;
	/* The rest remains unchanged! */&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Showing Activity, Logging=&lt;br /&gt;
Almost all admin commands should log their activity, and some admin commands should show their activity to in-game clients.  This can be done via the [https://sm.alliedmods.net/new-api/logging/LogAction LogAction()] and [https://sm.alliedmods.net/new-api/console/ShowActivity2 ShowActivity2()] functions.  The exact functionality of ShowActivity2() is determined by the &amp;lt;tt&amp;gt;sm_show_activity&amp;lt;/tt&amp;gt; cvar.&lt;br /&gt;
&lt;br /&gt;
For example, let's rewrite the last few lines of our slap command:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
	SlapPlayer(target, damage);&lt;br /&gt;
&lt;br /&gt;
	char name[MAX_NAME_LENGTH];&lt;br /&gt;
	&lt;br /&gt;
	GetClientName(target, name, sizeof(name));&lt;br /&gt;
&lt;br /&gt;
	ShowActivity2(client, &amp;quot;[SM] &amp;quot;, &amp;quot;Slapped %s for %d damage!&amp;quot;, name, damage);&lt;br /&gt;
	LogAction(client, target, &amp;quot;\&amp;quot;%L\&amp;quot; slapped \&amp;quot;%L\&amp;quot; (damage %d)&amp;quot;, client, target, damage);&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Multiple Targets=&lt;br /&gt;
To fully complete our slap demonstration, let's make it support multiple targets.  SourceMod's [[Admin_Commands_%28SourceMod%29#How_to_Target|targeting system]] is quite advanced, so using it may seem complicated at first.  &lt;br /&gt;
&lt;br /&gt;
The function we use is [https://sm.alliedmods.net/new-api/commandfilters/ProcessTargetString ProcessTargetString()].  It takes in input from the console, and returns a list of matching clients.  It also returns a noun that will identify either a single client or describe a list of clients.  The idea is that each client is then processed, but the activity shown to all players is only processed once.  This reduces screen spam.&lt;br /&gt;
&lt;br /&gt;
This method of target processing is used for almost every admin command in SourceMod, and in fact FindTarget() is just a simplified version.&lt;br /&gt;
&lt;br /&gt;
Full, final example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
#include &amp;lt;sdktools&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ConVar sm_myslap_damage = null;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0.0.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	LoadTranslations(&amp;quot;common.phrases&amp;quot;);&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
&lt;br /&gt;
	sm_myslap_damage = CreateConVar(&amp;quot;sm_myslap_damage&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;Default slap damage&amp;quot;);&lt;br /&gt;
	AutoExecConfig(true, &amp;quot;plugin_myslap&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg1[32], arg2[32];&lt;br /&gt;
	int damage = GetConVarInt(sm_myslap_damage);&lt;br /&gt;
&lt;br /&gt;
	/* Get the first argument */&lt;br /&gt;
	GetCmdArg(1, arg1, sizeof(arg1));&lt;br /&gt;
&lt;br /&gt;
	/* If there are 2 or more arguments, and the second argument fetch &lt;br /&gt;
	 * is successful, convert it to an integer.&lt;br /&gt;
	 */&lt;br /&gt;
	if (args &amp;gt;= 2 &amp;amp;&amp;amp; GetCmdArg(2, arg2, sizeof(arg2)))&lt;br /&gt;
	{&lt;br /&gt;
		damage = StringToInt(arg2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * target_name - stores the noun identifying the target(s)&lt;br /&gt;
	 * target_list - array to store clients&lt;br /&gt;
	 * target_count - variable to store number of clients&lt;br /&gt;
	 * tn_is_ml - stores whether the noun must be translated&lt;br /&gt;
	 */&lt;br /&gt;
	char target_name[MAX_TARGET_LENGTH];&lt;br /&gt;
	int target_list[MAXPLAYERS], target_count;&lt;br /&gt;
	bool tn_is_ml;&lt;br /&gt;
&lt;br /&gt;
	if ((target_count = ProcessTargetString(&lt;br /&gt;
			arg1,&lt;br /&gt;
			client,&lt;br /&gt;
			target_list,&lt;br /&gt;
			MAXPLAYERS,&lt;br /&gt;
			COMMAND_FILTER_ALIVE, /* Only allow alive players */&lt;br /&gt;
			target_name,&lt;br /&gt;
			sizeof(target_name),&lt;br /&gt;
			tn_is_ml)) &amp;lt;= 0)&lt;br /&gt;
	{&lt;br /&gt;
		/* This function replies to the admin with a failure message */&lt;br /&gt;
		ReplyToTargetError(client, target_count);&lt;br /&gt;
		return Plugin_Handled;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	for (int i = 0; i &amp;lt; target_count; i++)&lt;br /&gt;
	{&lt;br /&gt;
		SlapPlayer(target_list[i], damage);&lt;br /&gt;
		LogAction(client, target_list[i], &amp;quot;\&amp;quot;%L\&amp;quot; slapped \&amp;quot;%L\&amp;quot; (damage %d)&amp;quot;, client, target_list[i], damage);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (tn_is_ml)&lt;br /&gt;
	{&lt;br /&gt;
		ShowActivity2(client, &amp;quot;[SM] &amp;quot;, &amp;quot;Slapped %t for %d damage!&amp;quot;, target_name, damage);&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		ShowActivity2(client, &amp;quot;[SM] &amp;quot;, &amp;quot;Slapped %s for %d damage!&amp;quot;, target_name, damage);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Client and Entity Indexes=&lt;br /&gt;
One major point of confusion with Half-Life 2 is the difference between the following things:&lt;br /&gt;
*Client index&lt;br /&gt;
*Entity index&lt;br /&gt;
*Userid&lt;br /&gt;
&lt;br /&gt;
The first answer is that clients are entities.  Thus, a client index and an entity index are the same thing.  When a SourceMod function asks for an entity index, a client index can be specified.  When a SourceMod function asks for a client index, usually it means only a client index can be specified.&lt;br /&gt;
&lt;br /&gt;
A fast way to check if an entity index is a client is checking whether it's between 1 and [https://sm.alliedmods.net/new-api/clients/GetMaxClients GetMaxClients()] (inclusive).  If a server has N client slots maximum, then entities 1 through N are always reserved for clients.  Note that 0 is a valid entity index; it is the world entity (worldspawn).&lt;br /&gt;
&lt;br /&gt;
A userid, on the other hand, is completely different.  The server maintains a global &amp;quot;connection count&amp;quot; number, and it starts at 1.  Each time a client connects, the connection count is incremented, and the client receives that new number as their userid.&lt;br /&gt;
&lt;br /&gt;
For example, the first client to connect has a userid of 2.  If he exits and rejoins, his userid will be 3 (unless another client joins in-between).  Although SourceMod fires the OnClientConnected and OnClientDisconnected callbacks every map change, the server tracks players across map changes and does not change their userids or client indexes.  To see if a client really connected or disconnected, hook the  [[Generic Source Server Events#player_connect|player_connect]] and [[Generic Source Server Events#player_disconnect|player_disconnect]] events instead.&lt;br /&gt;
&lt;br /&gt;
SourceMod provides two functions for userids: [https://sm.alliedmods.net/new-api/clients/GetClientOfUserId GetClientOfUserId()] and [https://sm.alliedmods.net/new-api/clients/GetClientUserId GetClientUserId()].&lt;br /&gt;
&lt;br /&gt;
=Events=&lt;br /&gt;
Events are informational notification messages passed between objects in the server.  Many are also passed from the server to the client.  They are defined in .res files under the &amp;lt;tt&amp;gt;hl2/resource&amp;lt;/tt&amp;gt; folder and &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; folders of specific mods.  For a basic listing, see [[Game Events (Source)|Source Game Events]].&lt;br /&gt;
&lt;br /&gt;
It is important to note a few concepts about events:&lt;br /&gt;
*They are almost always informational.  That is, blocking &amp;lt;tt&amp;gt;player_death&amp;lt;/tt&amp;gt; will not stop a player from dying.  It may block a HUD or console message or something else minor.&lt;br /&gt;
*They almost always use userids instead of client indexes.&lt;br /&gt;
*Just because it is in a resource file does not mean it is ever called, or works the way you expect it to.  Mods are notorious at not properly documenting their event functionality.&lt;br /&gt;
&lt;br /&gt;
An example of finding when a player dies:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
   HookEvent(&amp;quot;player_death&amp;quot;, Event_PlayerDeath);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast)&lt;br /&gt;
{&lt;br /&gt;
   int victim_id = event.GetInt(&amp;quot;userid&amp;quot;);&lt;br /&gt;
   int attacker_id = event.GetInt(&amp;quot;attacker&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
   int victim = GetClientOfUserId(victim_id);&lt;br /&gt;
   int attacker = GetClientOfUserId(attacker_id);&lt;br /&gt;
&lt;br /&gt;
   /* CODE */&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Callback Orders and Pairing=&lt;br /&gt;
SourceMod has a number of builtin callbacks about the state of the server and plugin.  Some of these are paired in special ways which is confusing to users.&lt;br /&gt;
&lt;br /&gt;
==Pairing==&lt;br /&gt;
'''Pairing''' is SourceMod terminology.  Examples of it are:&lt;br /&gt;
*OnMapEnd() cannot be called without an OnMapStart(), and if OnMapStart() is called, it cannot be called again without an OnMapEnd().&lt;br /&gt;
*OnClientConnected(N) for a given client N will only be called once, until an OnClientDisconnected(N) for the same client N is called (which is guaranteed to happen).&lt;br /&gt;
&lt;br /&gt;
There is a formal definition of SourceMod's pairing.  For two functions X and Y, both with input A, the following conditions hold:&lt;br /&gt;
*If X is invoked with input A, it cannot be invoked again with the same input unless Y is called with input A.&lt;br /&gt;
*If X is invoked with input A, it is guaranteed that Y will, at some point, be called with input A.&lt;br /&gt;
*Y cannot be invoked with any input A unless X was called first with input A.&lt;br /&gt;
*The relationship is described as, &amp;quot;X is paired with Y,&amp;quot; and &amp;quot;Y is paired to X.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==General Callbacks==&lt;br /&gt;
These callbacks are listed in the order they are called, in the lifetime of a plugin and the server.&lt;br /&gt;
&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/sourcemod/AskPluginLoad2 AskPluginLoad2()] - Called once, immediately after the plugin is loaded from the disk.  This function can be used to stop a plugin from loading and return a custom error message; return APLRes_Failure and use strcopy on to replace the error string.  All CreateNative and RegPluginLibrary calls should be done here.  &lt;br /&gt;
*[https://sm.alliedmods.net/new-api/sourcemod/OnPluginStart OnPluginStart()] - Called once, after the plugin has been fully initialized and can proceed to load.  Any run-time errors in this function will cause the plugin to fail to load.  '''This is paired with OnPluginEnd()'''.&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/sourcemod/OnAllPluginsLoaded OnAllPluginsLoaded()] - Called once, after all non-late loaded plugins have called OnPluginStart.  &lt;br /&gt;
*[https://sm.alliedmods.net/new-api/sourcemod/OnMapStart OnMapStart()] - Called every time the map loads.  If the plugin is loaded late, and the map has already started, this function is called anyway after load, in order to preserve pairing.  '''This function is paired with OnMapEnd().'''&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/sourcemod/OnConfigsExecuted OnConfigsExecuted()] - Called once per map-change after  &amp;lt;tt&amp;gt;servercfgfile&amp;lt;/tt&amp;gt; (usually &amp;lt;tt&amp;gt;server.cfg&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;sourcemod.cfg&amp;lt;/tt&amp;gt;, and all plugin config files have finished executing.  If a plugin is loaded after this has happened, the callback is called anyway, in order to preserve pairing.  '''This function is paired with OnMapEnd().'''&lt;br /&gt;
*At this point, most game callbacks can occur, such as events and callbacks involving clients (or other things, like OnGameFrame).&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/sourcemod/OnMapEnd OnMapEnd()] - Called when the map is about to end.  At this point, all clients are disconnected, but &amp;lt;tt&amp;gt;TIMER_NO_MAPCHANGE&amp;lt;/tt&amp;gt; timers are not yet destroyed.  '''This function is paired to OnMapStart().'''&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/sourcemod/OnPluginEnd OnPluginEnd()] - Called once, immediately before the plugin is unloaded.  '''This function is paired to OnPluginStart().'''&lt;br /&gt;
&lt;br /&gt;
==Client Callbacks==&lt;br /&gt;
These callbacks are listed in no specific order, however, their documentation holds for both fake and real clients.&lt;br /&gt;
&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/clients/OnClientConnect OnClientConnect()] - Called when a player initiates a connection.  You can block a player from connecting by returning Plugin_Stop and setting rejectmsg to an error message.&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/clients/OnClientConnected OnClientConnected()] - Called after a player connects. Signifies that the player is in-game and IsClientConnected() will return true. '''This is paired with OnClientDisconnect() for successful connections only.'''&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/clients/OnClientAuthorized OnClientAuthorized()] - Called when a player gets a Steam ID.  It is important to note that this may never be called.  It may occur any time in between OnClientConnected and OnClientPreAdminCheck/OnClientDisconnect.  Do not rely on it unless you are writing something that needs Steam IDs, and even then you should use OnClientPostAdminCheck().&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/clients/OnClientPutInServer OnClientPutInServer()] - Signifies that the player is in-game and IsClientInGame() will return true.&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/clients/OnClientPostAdminCheck OnClientPostAdminCheck()] - Called after the player is '''both authorized and in-game'''.  This is the best callback for checking administrative access after connect.&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/clients/OnClientDisconnect OnClientDisconnect()] - Called when a player's disconnection starts.  '''This is paired to OnClientConnected().'''&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/clients/OnClientDisconnect_Post OnClientDisconnect_Post()] - Called when a player's disconnection ends.  '''This is paired to OnClientConnected().'''&lt;br /&gt;
&lt;br /&gt;
=Frequently Asked Questions=&lt;br /&gt;
==Are plugins reloaded every mapchange?==&lt;br /&gt;
Plugins, by default, are not reloaded on mapchange unless their timestamp changes.  This is a feature so plugin authors have more flexibility with the state of their plugins.  &lt;br /&gt;
&lt;br /&gt;
==Do I need to call CloseHandle in OnPluginEnd?==&lt;br /&gt;
No.  SourceMod automatically closes your Handles when your plugin is unloaded, in order to prevent memory errors.&lt;br /&gt;
&lt;br /&gt;
==Do I need to #include every individual .inc?==&lt;br /&gt;
No.  &amp;lt;tt&amp;gt;#include &amp;lt;sourcemod&amp;gt;&amp;lt;/tt&amp;gt; will give you 95% of the .incs.  Similarly, &amp;lt;tt&amp;gt;#include &amp;lt;sdktools&amp;gt;&amp;lt;/tt&amp;gt; includes everything starting with &amp;lt;sdktools&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Why don't some events fire?==&lt;br /&gt;
There is no guarantee that events will fire.  The event listing is not a specification, it is a list of the events that a game is capable of firing.  Whether the game actually fires them is up to Valve or the developer.&lt;br /&gt;
&lt;br /&gt;
==Do I need to CloseHandle timers?==&lt;br /&gt;
No.  In fact, doing so may cause errors.  Timers naturally die on their own unless they are infinite timers, in which case you can use KillTimer() or die gracefully by returning &amp;lt;tt&amp;gt;Plugin_Stop&amp;lt;/tt&amp;gt; in the callback.&lt;br /&gt;
&lt;br /&gt;
==Are clients disconnected on mapchange?==&lt;br /&gt;
All clients are fully disconnected before the map changes.  They are all reconnected after the next map starts.&lt;br /&gt;
&lt;br /&gt;
If you only want to detect when a client initially connects or leaves your server, hook the [[Generic Source Server Events#player_connect|player_connect]] or [[Generic Source Server Events#player_disconnect|player_disconnect]] events respectively.&lt;br /&gt;
&lt;br /&gt;
=Further Reading=&lt;br /&gt;
For further reading, see the &amp;quot;Scripting&amp;quot; section at the [http://docs.sourcemod.net/ SourceMod Documentation].&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Scripting]]&lt;br /&gt;
&lt;br /&gt;
{{LanguageSwitch}}&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Introduction_to_SourceMod_Plugins&amp;diff=9939</id>
		<title>Introduction to SourceMod Plugins</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Introduction_to_SourceMod_Plugins&amp;diff=9939"/>
		<updated>2015-07-13T01:19:13Z</updated>

		<summary type="html">&lt;p&gt;Fyren: syntax fixes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide will give you a basic introduction to writing a [[SourceMod]] plugin.  If you are not familiar with the SourcePawn language, it is recommended that you at least briefly read the [[Introduction to SourcePawn]] article.&lt;br /&gt;
&lt;br /&gt;
For information on compiling plugins, see [[Compiling SourceMod Plugins]]. You can use [http://www.crimsoneditor.com/ Crimson Editor], [http://www.pspad.com/ PSPad], [http://www.ultraedit.com/ UltraEdit], [http://notepad-plus.sourceforge.net/uk/site.htm Notepad++], [http://www.textpad.com/ TextPad], [http://sourceforge.net/projects/pawnstudio/ Pawn Studio] or any other text editor you're comfortable with to write plugins.&lt;br /&gt;
&lt;br /&gt;
=Starting from scratch=&lt;br /&gt;
Open your favorite text editor and create a new empty file. When you have an empty file you can just start writing code using the core language, however, you will not be able to use any of SourceMod features because the compiler does not now about them. This is done deliberately so it is possible to use SourcePawn outside of SourceMod. But since we are writing a SourceMod plugin, it is a good idea to enable access to SourceMod features first. This it done using &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive. It tells compiler to &amp;quot;paste&amp;quot; the code from another file into yours.&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
How does this work? First of all, note that we enclosed file name into angle brackets. Angle brackets tell the compiler to look in the default include directory. By default, it is '''scripting/include'''. You can open it right now and see a lot of inc files there. Those are SourceMod include files that describe various functions, tags and other features available for SourceMod plugins. The files are plain-text and you are encouraged to read them. You will notice however, that there's not much code in there, certainly not enough to implement all the great features of SourceMod, so where are they? They are implemented inside a SourceMod core which is written in C++ and is compiled into binary files which end up in '''bin''' directory. So how does your SourcePawn code and SM core link together if compiler doesn't know about existence of the latter? SourceMod include files are written specially, so they say that the implementation of functions is ''somewhere else''. Compiler understands that and generate a special code that says that this function call is going outside. When SourceMod loads your plugin, it inspects these bits of code and substitutes it's own internal functions instead. This is called [http://en.wikipedia.org/wiki/Dynamic_linking dynamic linking].&lt;br /&gt;
&lt;br /&gt;
=Setting up plugin info=&lt;br /&gt;
Now that we got access to SourceMod features, it is time to setup the information that will be displayed via &amp;lt;tt&amp;gt;sm plugins list&amp;lt;/tt&amp;gt; command. No one likes unnamed plugins. To do that we are going to look inside '''sourcemod.inc''' file and see the format that information should be declared. It's always helpful to look inside SM include files to find out information you don't know. There is also an [http://docs.sourcemod.net/api/ API documentation] but it can be outdated and it only has SM core files so if your plugin are going to use any third party extension or another plugin, you will have to study inc files. So, open '''sourcemod.inc''' and scroll down a bit until you see this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Plugin public information.&lt;br /&gt;
 */&lt;br /&gt;
struct Plugin&lt;br /&gt;
{&lt;br /&gt;
   public const char[] name;		/**&amp;lt; Plugin Name */&lt;br /&gt;
   public const char[] description;	/**&amp;lt; Plugin Description */&lt;br /&gt;
   public const char[] author;		/**&amp;lt; Plugin Author */&lt;br /&gt;
   public const char[] version;		/**&amp;lt; Plugin Version */&lt;br /&gt;
   public const char[] url;			/**&amp;lt; Plugin URL */&lt;br /&gt;
};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
and this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Declare this as a struct in your plugin to expose its information.&lt;br /&gt;
 * Example:&lt;br /&gt;
 *&lt;br /&gt;
 * public Plugin myinfo =&lt;br /&gt;
 * {&lt;br /&gt;
 *    name = &amp;quot;My Plugin&amp;quot;,&lt;br /&gt;
 *    //etc&lt;br /&gt;
 * };&lt;br /&gt;
 */&lt;br /&gt;
public Plugin myinfo;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It tells us that we need to create a global public variable &amp;lt;tt&amp;gt;myinfo&amp;lt;/tt&amp;gt; which must be of type &amp;lt;tt&amp;gt;Plugin&amp;lt;/tt&amp;gt; which is a struct with 5 fields which themselves are strings. It may sound complicated for a beginner but it's easy. Let's go ahead and create one:&lt;br /&gt;
&amp;lt;pawn&amp;gt;public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;public&amp;lt;/tt&amp;gt; keyword means that SourceMod will be able to directly access our variable. &amp;lt;tt&amp;gt;Plugin:&amp;lt;/tt&amp;gt; defines a type of our variable. &amp;lt;tt&amp;gt;myinfo&amp;lt;/tt&amp;gt; is, obviously, a name of our variable as required by SourceMod. You see that we initialize it right away. This is preferred way to do when filling out plugin info.&lt;br /&gt;
&lt;br /&gt;
After that the full code of your plugin should look like this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Getting code to run=&lt;br /&gt;
We already include SourceMod features and filled up or plugin info. We now have a perfectly well formed plugin which can be compiled and loaded by SourceMod. However, there is one problem - it does nothing. You might be tempted to just start writing a code after &amp;lt;tt&amp;gt;myinfo&amp;lt;/tt&amp;gt; declaration just to see that it will not compile. SourcePawn, unlike other scripting languages like Lua, does not allow a code to be outside of functions. After reading that, you may probably want to just define some function, name it &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt; probably, compile and load a plugin and see that your code never gets called. So how do we make SourceMod call our code? For this exact reason we have forwards. Forwards are function prototypes declared by one party that can be implemented by another party as a [http://en.wikipedia.org/wiki/Callback_%28computer_programming%29 callback]. When a first party starts a forward call, all parties that have matching callbacks receive the call. SourceMod declares a plenty of interesting forwards that we can implement. As you can see, forwards are the only way to get our code executed, keep that in mind. So let's implement &amp;lt;tt&amp;gt;OnPluginStart&amp;lt;/tt&amp;gt; forward. As you may have guessed, it is called when our plugin starts. To do that, we'll have to look up the declaration of &amp;lt;tt&amp;gt;OnPluginStart&amp;lt;/tt&amp;gt;. It is declared inside '''sourcemod.inc''', a file we are already familiar with, let's find it:&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Called when the plugin is fully initialized and all known external references &lt;br /&gt;
 * are resolved. This is only called once in the lifetime of the plugin, and is &lt;br /&gt;
 * paired with OnPluginEnd().&lt;br /&gt;
 *&lt;br /&gt;
 * If any run-time error is thrown during this callback, the plugin will be marked &lt;br /&gt;
 * as failed.&lt;br /&gt;
 *&lt;br /&gt;
 * It is not necessary to close any handles or remove hooks in this function.  &lt;br /&gt;
 * SourceMod guarantees that plugin shutdown automatically and correctly releases &lt;br /&gt;
 * all resources.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
forward void OnPluginStart();&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Empty parentheses tells us that no arguments are passed inside this forward, &amp;lt;tt&amp;gt;@noreturn&amp;lt;/tt&amp;gt; inside documentation tells us that we don't have to return anything, pretty simple forward. So how to write a correct callback for it? Firstly, our callback must have the same name, so it's &amp;lt;tt&amp;gt;OnPluginStart&amp;lt;/tt&amp;gt;, secondly, our callback should have the same number of arguments, none in this case, and lastly, SourceMod needs to be able to call our callback so it needs to be &amp;lt;tt&amp;gt;public&amp;lt;/tt&amp;gt;. So the implementation looks like this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we can write code inside curly braces and it will be executed when our plugin starts. Let's output &amp;lt;tt&amp;gt;&amp;quot;Hello world!&amp;quot;&amp;lt;/tt&amp;gt; to server console. To do that we are going to use &amp;lt;tt&amp;gt;PrintToServer&amp;lt;/tt&amp;gt; function. It is declared inside '''console.inc''', however, we don't need to manually include '''console.inc''' because it is included automatically as part of '''sourcemod.inc'''.&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Sends a message to the server console.&lt;br /&gt;
 *&lt;br /&gt;
 * @param format		Formatting rules.&lt;br /&gt;
 * @param ...			Variable number of format parameters.&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native int PrintToServer(const char[] format, any ...);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
As you can see, this is a native function. It is implemented inside SM core. Judging by it's arguments, we can see that it is a [[Format_Class_Functions_%28SourceMod_Scripting%29|format class function]]. However, we don't need any formatting right now, so let's just pass &amp;lt;tt&amp;gt;&amp;quot;Hello world!&amp;quot;&amp;lt;/tt&amp;gt; string as an only argument:&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	PrintToServer(&amp;quot;Hello world!&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
That's it! The full code of your plugin should look like this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	PrintToServer(&amp;quot;Hello world!&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Compile and load your plugin on your server and see for yourself that the message is displayed in server console.&lt;br /&gt;
&lt;br /&gt;
=Includes=&lt;br /&gt;
Pawn requires '''include files''', much like C requires header files.  Include files list all of the structures, functions, callbacks, and tags that are available.  There are three types of include files:&lt;br /&gt;
*'''Core''' - &amp;lt;tt&amp;gt;sourcemod.inc&amp;lt;/tt&amp;gt; and anything it includes.  These are all provided by SourceMod's Core.&lt;br /&gt;
*'''Extension''' - adds a dependency against a certain extension.&lt;br /&gt;
*'''Plugin''' - adds a dependency against a certain plugin.&lt;br /&gt;
&lt;br /&gt;
Include files are loaded using the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; compiler directive.&lt;br /&gt;
&lt;br /&gt;
=Commands=&lt;br /&gt;
Our first example will be writing a simple admin command to slap a player.  We'll continue to extend this example with more features until we have a final, complete result.&lt;br /&gt;
&lt;br /&gt;
==Declaration==&lt;br /&gt;
First, let's look at what an admin command requires.  Admin commands are registered using the [http://docs.sourcemod.net/api/index.php?fastload=show&amp;amp;id=471&amp;amp; RegAdminCmd] function.  They require a '''name''', a '''callback function''', and '''default admin flags'''.  &lt;br /&gt;
&lt;br /&gt;
The callback function is what's invoked every time the command is used.  [http://docs.sourcemod.net/api/index.php?fastload=show&amp;amp;id=771&amp;amp; Click here] to see its prototype.  Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
public OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action:Command_MySlap(client, args)&lt;br /&gt;
{&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we've successfully implemented a command -- though it doesn't do anything yet.  In fact, it will say &amp;quot;Unknown command&amp;quot; if you use it!  The reason is because of the &amp;lt;tt&amp;gt;Action&amp;lt;/tt&amp;gt; tag.  Any command that you type in the console, even if it's registered by SourceMod, will be sent to the engine to be processed. Because we have not had SourceMod block this functionality yet, the engine replies with &amp;quot;Unknown command&amp;quot; because it is not a valid engine command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now the command will report no error, but it still won't do anything. This is because returning &amp;quot;Plugin_Handled&amp;quot; in a command callback will prevent the engine from processing the command. The engine will never even see that the command was run. This is what you will want to do if you are registering a completely new command through SourceMod.&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
Let's decide what the command will look like.  Let's have it act like the default &amp;lt;tt&amp;gt;sm_slap&amp;lt;/tt&amp;gt; command:&lt;br /&gt;
&amp;lt;pre&amp;gt;sm_myslap &amp;lt;name|#userid&amp;gt; [damage]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To implement this, we'll need a few steps:&lt;br /&gt;
*Get the input from the console.  For this we use [http://docs.sourcemod.net/api/index.php?fastload=show&amp;amp;id=473&amp;amp; GetCmdArg()].&lt;br /&gt;
*Find a matching player.  For this we use [http://docs.sourcemod.net/api/index.php?fastload=show&amp;amp;id=144&amp;amp; FindTarget()].&lt;br /&gt;
*Slap them.  For this we use [http://docs.sourcemod.net/api/index.php?fastload=show&amp;amp;id=42&amp;amp; SlapPlayer()], which requires including &amp;lt;tt&amp;gt;sdktools&amp;lt;/tt&amp;gt;, an extension bundled with SourceMod.&lt;br /&gt;
*Respond to the admin.  For this we use [http://docs.sourcemod.net/api/index.php?fastload=show&amp;amp;id=462&amp;amp; ReplyToCommand()].&lt;br /&gt;
&lt;br /&gt;
Full example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
#include &amp;lt;sdktools&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0.0.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg1[32], arg2[32];&lt;br /&gt;
	int damage;&lt;br /&gt;
&lt;br /&gt;
	/* Get the first argument */&lt;br /&gt;
	GetCmdArg(1, arg1, sizeof(arg1));&lt;br /&gt;
&lt;br /&gt;
	/* If there are 2 or more arguments, and the second argument fetch &lt;br /&gt;
	 * is successful, convert it to an integer.&lt;br /&gt;
	 */&lt;br /&gt;
	if (args &amp;gt;= 2 &amp;amp;&amp;amp; GetCmdArg(2, arg2, sizeof(arg2)))&lt;br /&gt;
	{&lt;br /&gt;
		damage = StringToInt(arg2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Try and find a matching player */&lt;br /&gt;
	int target = FindTarget(client, arg1);&lt;br /&gt;
	if (target == -1)&lt;br /&gt;
	{&lt;br /&gt;
		/* FindTarget() automatically replies with the &lt;br /&gt;
		 * failure reason.&lt;br /&gt;
		 */&lt;br /&gt;
		return Plugin_Handled;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	SlapPlayer(target, damage);&lt;br /&gt;
&lt;br /&gt;
	char name[MAX_NAME_LENGTH];&lt;br /&gt;
	&lt;br /&gt;
	GetClientName(target, name, sizeof(name));&lt;br /&gt;
	ReplyToCommand(client, &amp;quot;[SM] You slapped %s for %d damage!&amp;quot;, name, damage);&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information on what %s and %d are, see [[Format Class Functions (SourceMod Scripting)|Format Class Functions]].  Note that you never need to unregister or remove your admin command.  When a plugin is unloaded, SourceMod cleans it up for you.&lt;br /&gt;
&lt;br /&gt;
=ConVars=&lt;br /&gt;
ConVars, also known as cvars, are global console variables in the Source engine.  They can have integer, float, or string values.  ConVar accessing is done through [[Handles (SourceMod Scripting)|Handles]].  Since ConVars are global, you do not need to close ConVar Handles (in fact, you cannot).&lt;br /&gt;
&lt;br /&gt;
The handy feature of ConVars is that they are easy for users to configure.  They can be placed in any .cfg file, such as &amp;lt;tt&amp;gt;server.cfg&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;sourcemod.cfg&amp;lt;/tt&amp;gt;.  To make this easier, SourceMod has an [http://docs.sourcemod.net/api/index.php?fastload=show&amp;amp;id=607&amp;amp; AutoExecConfig()] function.  This function will automatically build a default .cfg file containing all of your cvars, annotated with comments, for users.  It is highly recommend that you call this if you have customizable ConVars.&lt;br /&gt;
&lt;br /&gt;
Let's extend your example from earlier with a new ConVar.  Our ConVar will be &amp;lt;tt&amp;gt;sm_myslap_damage&amp;lt;/tt&amp;gt; and will specify the default damage someone is slapped for if no damage is specified.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;ConVar sm_myslap_damage = null&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
&lt;br /&gt;
	sm_myslap_damage = CreateConVar(&amp;quot;sm_myslap_damage&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;Default slap damage&amp;quot;);&lt;br /&gt;
	AutoExecConfig(true, &amp;quot;plugin_myslap&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg1[32], arg2[32];&lt;br /&gt;
	int damage = GetConVarInt(sm_myslap_damage);&lt;br /&gt;
&lt;br /&gt;
	/* The rest remains unchanged! */&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Showing Activity, Logging=&lt;br /&gt;
Almost all admin commands should log their activity, and some admin commands should show their activity to in-game clients.  This can be done via the [http://docs.sourcemod.net/api/index.php?fastload=show&amp;amp;id=599&amp;amp; LogAction()] and [http://docs.sourcemod.net/api/index.php?fastload=show&amp;amp;id=466&amp;amp; ShowActivity2()] functions.  The exact functionality of ShowActivity2() is determined by the &amp;lt;tt&amp;gt;sm_show_activity&amp;lt;/tt&amp;gt; cvar.&lt;br /&gt;
&lt;br /&gt;
For example, let's rewrite the last few lines of our slap command:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
	SlapPlayer(target, damage);&lt;br /&gt;
&lt;br /&gt;
	char name[MAX_NAME_LENGTH];&lt;br /&gt;
	&lt;br /&gt;
	GetClientName(target, name, sizeof(name));&lt;br /&gt;
&lt;br /&gt;
	ShowActivity2(client, &amp;quot;[SM] &amp;quot;, &amp;quot;Slapped %s for %d damage!&amp;quot;, name, damage);&lt;br /&gt;
	LogAction(client, target, &amp;quot;\&amp;quot;%L\&amp;quot; slapped \&amp;quot;%L\&amp;quot; (damage %d)&amp;quot;, client, target, damage);&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Multiple Targets=&lt;br /&gt;
To fully complete our slap demonstration, let's make it support multiple targets.  SourceMod's [[Admin_Commands_%28SourceMod%29#How_to_Target|targeting system]] is quite advanced, so using it may seem complicated at first.  &lt;br /&gt;
&lt;br /&gt;
The function we use is [http://docs.sourcemod.net/api/index.php?fastload=show&amp;amp;id=703&amp;amp; ProcessTargetString()].  It takes in input from the console, and returns a list of matching clients.  It also returns a noun that will identify either a single client or describe a list of clients.  The idea is that each client is then processed, but the activity shown to all players is only processed once.  This reduces screen spam.&lt;br /&gt;
&lt;br /&gt;
This method of target processing is used for almost every admin command in SourceMod, and in fact FindTarget() is just a simplified version.&lt;br /&gt;
&lt;br /&gt;
Full, final example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
#include &amp;lt;sdktools&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ConVar sm_myslap_damage = INVALID_HANDLE&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0.0.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	LoadTranslations(&amp;quot;common.phrases&amp;quot;);&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
&lt;br /&gt;
	sm_myslap_damage = CreateConVar(&amp;quot;sm_myslap_damage&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;Default slap damage&amp;quot;);&lt;br /&gt;
	AutoExecConfig(true, &amp;quot;plugin_myslap&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg1[32], arg2[32];&lt;br /&gt;
	int damage = GetConVarInt(sm_myslap_damage);&lt;br /&gt;
&lt;br /&gt;
	/* Get the first argument */&lt;br /&gt;
	GetCmdArg(1, arg1, sizeof(arg1));&lt;br /&gt;
&lt;br /&gt;
	/* If there are 2 or more arguments, and the second argument fetch &lt;br /&gt;
	 * is successful, convert it to an integer.&lt;br /&gt;
	 */&lt;br /&gt;
	if (args &amp;gt;= 2 &amp;amp;&amp;amp; GetCmdArg(2, arg2, sizeof(arg2)))&lt;br /&gt;
	{&lt;br /&gt;
		damage = StringToInt(arg2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * target_name - stores the noun identifying the target(s)&lt;br /&gt;
	 * target_list - array to store clients&lt;br /&gt;
	 * target_count - variable to store number of clients&lt;br /&gt;
	 * tn_is_ml - stores whether the noun must be translated&lt;br /&gt;
	 */&lt;br /&gt;
	char target_name[MAX_TARGET_LENGTH];&lt;br /&gt;
	int target_list[MAXPLAYERS], target_count;&lt;br /&gt;
	bool tn_is_ml;&lt;br /&gt;
&lt;br /&gt;
	if ((target_count = ProcessTargetString(&lt;br /&gt;
			arg1,&lt;br /&gt;
			client,&lt;br /&gt;
			target_list,&lt;br /&gt;
			MAXPLAYERS,&lt;br /&gt;
			COMMAND_FILTER_ALIVE, /* Only allow alive players */&lt;br /&gt;
			target_name,&lt;br /&gt;
			sizeof(target_name),&lt;br /&gt;
			tn_is_ml)) &amp;lt;= 0)&lt;br /&gt;
	{&lt;br /&gt;
		/* This function replies to the admin with a failure message */&lt;br /&gt;
		ReplyToTargetError(client, target_count);&lt;br /&gt;
		return Plugin_Handled;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	for (int i = 0; i &amp;lt; target_count; i++)&lt;br /&gt;
	{&lt;br /&gt;
		SlapPlayer(target_list[i], damage);&lt;br /&gt;
		LogAction(client, target_list[i], &amp;quot;\&amp;quot;%L\&amp;quot; slapped \&amp;quot;%L\&amp;quot; (damage %d)&amp;quot;, client, target_list[i], damage);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (tn_is_ml)&lt;br /&gt;
	{&lt;br /&gt;
		ShowActivity2(client, &amp;quot;[SM] &amp;quot;, &amp;quot;Slapped %t for %d damage!&amp;quot;, target_name, damage);&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		ShowActivity2(client, &amp;quot;[SM] &amp;quot;, &amp;quot;Slapped %s for %d damage!&amp;quot;, target_name, damage);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Client and Entity Indexes=&lt;br /&gt;
One major point of confusion with Half-Life 2 is the difference between the following things:&lt;br /&gt;
*Client index&lt;br /&gt;
*Entity index&lt;br /&gt;
*Userid&lt;br /&gt;
&lt;br /&gt;
The first answer is that clients are entities.  Thus, a client index and an entity index are the same thing.  When a SourceMod function asks for an entity index, a client index can be specified.  When a SourceMod function asks for a client index, usually it means only a client index can be specified.&lt;br /&gt;
&lt;br /&gt;
A fast way to check if an entity index is a client is checking whether it's between 1 and [http://docs.sourcemod.net/api/index.php?fastload=show&amp;amp;id=397&amp;amp; GetMaxClients()] (inclusive).  If a server has N client slots maximum, then entities 1 through N are always reserved for clients.  Note that 0 is a valid entity index; it is the world entity (worldspawn).&lt;br /&gt;
&lt;br /&gt;
A userid, on the other hand, is completely different.  The server maintains a global &amp;quot;connection count&amp;quot; number, and it starts at 1.  Each time a client connects, the connection count is incremented, and the client receives that new number as their userid.&lt;br /&gt;
&lt;br /&gt;
For example, the first client to connect has a userid of 2.  If he exits and rejoins, his userid will be 3 (unless another client joins in-between).  Although SourceMod fires the OnClientConnected and OnClientDisconnected callbacks every map change, the server tracks players across map changes and does not change their userids or client indexes.  To see if a client really connected or disconnected, hook the  [[Generic Source Server Events#player_connect|player_connect]] and [[Generic Source Server Events#player_disconnect|player_disconnect]] events instead.&lt;br /&gt;
&lt;br /&gt;
SourceMod provides two functions for userids: [http://docs.sourcemod.net/api/index.php?fastload=show&amp;amp;id=442&amp;amp; GetClientOfUserId()] and [http://docs.sourcemod.net/api/index.php?fastload=show&amp;amp;id=402&amp;amp; GetClientUserId()].&lt;br /&gt;
&lt;br /&gt;
=Events=&lt;br /&gt;
Events are informational notification messages passed between objects in the server.  Many are also passed from the server to the client.  They are defined in .res files under the &amp;lt;tt&amp;gt;hl2/resource&amp;lt;/tt&amp;gt; folder and &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; folders of specific mods.  For a basic listing, see [[Game Events (Source)|Source Game Events]].&lt;br /&gt;
&lt;br /&gt;
It is important to note a few concepts about events:&lt;br /&gt;
*They are almost always informational.  That is, blocking &amp;lt;tt&amp;gt;player_death&amp;lt;/tt&amp;gt; will not stop a player from dying.  It may block a HUD or console message or something else minor.&lt;br /&gt;
*They almost always use userids instead of client indexes.&lt;br /&gt;
*Just because it is in a resource file does not mean it is ever called, or works the way you expect it to.  Mods are notorious at not properly documenting their event functionality.&lt;br /&gt;
&lt;br /&gt;
An example of finding when a player dies:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
   HookEvent(&amp;quot;player_death&amp;quot;, Event_PlayerDeath);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast)&lt;br /&gt;
{&lt;br /&gt;
   int  victim_id = GetEventInt(event, &amp;quot;userid&amp;quot;);&lt;br /&gt;
   int attacker_id = GetEventInt(event, &amp;quot;attacker&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
   int victim = GetClientOfUserId(victim_id);&lt;br /&gt;
   int attacker = GetClientOfUserId(attacker_id);&lt;br /&gt;
&lt;br /&gt;
   /* CODE */&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Callback Orders and Pairing=&lt;br /&gt;
SourceMod has a number of builtin callbacks about the state of the server and plugin.  Some of these are paired in special ways which is confusing to users.&lt;br /&gt;
&lt;br /&gt;
==Pairing==&lt;br /&gt;
'''Pairing''' is SourceMod terminology.  Examples of it are:&lt;br /&gt;
*OnMapEnd() cannot be called without an OnMapStart(), and if OnMapStart() is called, it cannot be called again without an OnMapEnd().&lt;br /&gt;
*OnClientConnected(N) for a given client N will only be called once, until an OnClientDisconnected(N) for the same client N is called (which is guaranteed to happen).&lt;br /&gt;
&lt;br /&gt;
There is a formal definition of SourceMod's pairing.  For two functions X and Y, both with input A, the following conditions hold:&lt;br /&gt;
*If X is invoked with input A, it cannot be invoked again with the same input unless Y is called with input A.&lt;br /&gt;
*If X is invoked with input A, it is guaranteed that Y will, at some point, be called with input A.&lt;br /&gt;
*Y cannot be invoked with any input A unless X was called first with input A.&lt;br /&gt;
*The relationship is described as, &amp;quot;X is paired with Y,&amp;quot; and &amp;quot;Y is paired to X.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==General Callbacks==&lt;br /&gt;
These callbacks are listed in the order they are called, in the lifetime of a plugin and the server.&lt;br /&gt;
&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/sourcemod/AskPluginLoad2 AskPluginLoad2()] - Called once, immediately after the plugin is loaded from the disk.  This function can be used to stop a plugin from loading and return a custom error message; return APLRes_Failure and use strcopy on to replace the error string.  All CreateNative and RegPluginLibrary calls should be done here.  &lt;br /&gt;
*[https://sm.alliedmods.net/new-api/sourcemod/OnPluginStart OnPluginStart()] - Called once, after the plugin has been fully initialized and can proceed to load.  Any run-time errors in this function will cause the plugin to fail to load.  '''This is paired with OnPluginEnd()'''.&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/sourcemod/OnAllPluginsLoaded OnAllPluginsLoaded()] - Called once, after all non-late loaded plugins have called OnPluginStart.  &lt;br /&gt;
*[https://sm.alliedmods.net/new-api/sourcemod/OnMapStart OnMapStart()] - Called every time the map loads.  If the plugin is loaded late, and the map has already started, this function is called anyway after load, in order to preserve pairing.  '''This function is paired with OnMapEnd().'''&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/sourcemod/OnConfigsExecuted OnConfigsExecuted()] - Called once per map-change after  &amp;lt;tt&amp;gt;servercfgfile&amp;lt;/tt&amp;gt; (usually &amp;lt;tt&amp;gt;server.cfg&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;sourcemod.cfg&amp;lt;/tt&amp;gt;, and all plugin config files have finished executing.  If a plugin is loaded after this has happened, the callback is called anyway, in order to preserve pairing.  '''This function is paired with OnMapEnd().'''&lt;br /&gt;
*At this point, most game callbacks can occur, such as events and callbacks involving clients (or other things, like OnGameFrame).&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/sourcemod/OnMapEnd OnMapEnd()] - Called when the map is about to end.  At this point, all clients are disconnected, but &amp;lt;tt&amp;gt;TIMER_NO_MAPCHANGE&amp;lt;/tt&amp;gt; timers are not yet destroyed.  '''This function is paired to OnMapStart().'''&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/sourcemod/OnPluginEnd OnPluginEnd()] - Called once, immediately before the plugin is unloaded.  '''This function is paired to OnPluginStart().'''&lt;br /&gt;
&lt;br /&gt;
==Client Callbacks==&lt;br /&gt;
These callbacks are listed in no specific order, however, their documentation holds for both fake and real clients.&lt;br /&gt;
&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/clients/OnClientConnect OnClientConnect()] - Called when a player initiates a connection.  You can block a player from connecting by returning Plugin_Stop and setting rejectmsg to an error message.&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/clients/OnClientConnected OnClientConnected()] - Called after a player connects. Signifies that the player is in-game and IsClientConnected() will return true. '''This is paired with OnClientDisconnect() for successful connections only.'''&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/clients/OnClientAuthorized OnClientAuthorized()] - Called when a player gets a Steam ID.  It is important to note that this may never be called.  It may occur any time in between OnClientConnected and OnClientPreAdminCheck/OnClientDisconnect.  Do not rely on it unless you are writing something that needs Steam IDs, and even then you should use OnClientPostAdminCheck().&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/clients/OnClientPutInServer OnClientPutInServer()] - Signifies that the player is in-game and IsClientInGame() will return true.&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/clients/OnClientPostAdminCheck OnClientPostAdminCheck()] - Called after the player is '''both authorized and in-game'''.  This is the best callback for checking administrative access after connect.&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/clients/OnClientDisconnect OnClientDisconnect()] - Called when a player's disconnection starts.  '''This is paired to OnClientConnected().'''&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/clients/OnClientDisconnect_Post OnClientDisconnect_Post()] - Called when a player's disconnection ends.  '''This is paired to OnClientConnected().'''&lt;br /&gt;
&lt;br /&gt;
=Frequently Asked Questions=&lt;br /&gt;
==Are plugins reloaded every mapchange?==&lt;br /&gt;
Plugins, by default, are not reloaded on mapchange unless their timestamp changes.  This is a feature so plugin authors have more flexibility with the state of their plugins.  &lt;br /&gt;
&lt;br /&gt;
==Do I need to call CloseHandle in OnPluginEnd?==&lt;br /&gt;
No.  SourceMod automatically closes your Handles when your plugin is unloaded, in order to prevent memory errors.&lt;br /&gt;
&lt;br /&gt;
==Do I need to #include every individual .inc?==&lt;br /&gt;
No.  &amp;lt;tt&amp;gt;#include &amp;lt;sourcemod&amp;gt;&amp;lt;/tt&amp;gt; will give you 95% of the .incs.  Similarly, &amp;lt;tt&amp;gt;#include &amp;lt;sdktools&amp;gt;&amp;lt;/tt&amp;gt; includes everything starting with &amp;lt;sdktools&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Why don't some events fire?==&lt;br /&gt;
There is no guarantee that events will fire.  The event listing is not a specification, it is a list of the events that a game is capable of firing.  Whether the game actually fires them is up to Valve or the developer.&lt;br /&gt;
&lt;br /&gt;
==Do I need to CloseHandle timers?==&lt;br /&gt;
No.  In fact, doing so may cause errors.  Timers naturally die on their own unless they are infinite timers, in which case you can use KillTimer() or die gracefully by returning &amp;lt;tt&amp;gt;Plugin_Stop&amp;lt;/tt&amp;gt; in the callback.&lt;br /&gt;
&lt;br /&gt;
==Are clients disconnected on mapchange?==&lt;br /&gt;
All clients are fully disconnected before the map changes.  They are all reconnected after the next map starts.&lt;br /&gt;
&lt;br /&gt;
If you only want to detect when a client initially connects or leaves your server, hook the [[Generic Source Server Events#player_connect|player_connect]] or [[Generic Source Server Events#player_disconnect|player_disconnect]] events respectively.&lt;br /&gt;
&lt;br /&gt;
=Further Reading=&lt;br /&gt;
For further reading, see the &amp;quot;Scripting&amp;quot; section at the [http://docs.sourcemod.net/ SourceMod Documentation].&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Scripting]]&lt;br /&gt;
&lt;br /&gt;
{{LanguageSwitch}}&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Custom_Admin_Menu_(SourceMod)&amp;diff=9542</id>
		<title>Custom Admin Menu (SourceMod)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Custom_Admin_Menu_(SourceMod)&amp;diff=9542"/>
		<updated>2014-03-23T19:30:50Z</updated>

		<summary type="html">&lt;p&gt;Fyren: /* Example Files */ fix links for CF&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
The custom menu feature allows server admins to add new items to the SourceMod admin menu. It is designed to be used as a complement to plugins adding themselves to the menu. For more information see [[Admin Menu (SourceMod Scripting)]].&lt;br /&gt;
&lt;br /&gt;
Admins configure their menu using the config file (sourcemod/configs/adminmenu_custom.txt) and this is generated into a set of items and categories for the admin menu when the server starts.&lt;br /&gt;
&lt;br /&gt;
==Parameter List==&lt;br /&gt;
&lt;br /&gt;
These are all the parameters that can be specified to configure your menu. Most are optional and have a default value if they are not found. See the [[#Example Command|Example Command]] and/or the attached [[#Example Files|Example Files]] for information on how to lay out your config file.&lt;br /&gt;
&lt;br /&gt;
*cmd - command to be executed (#1,#2 etc for parameters - no limit on these) Use @num to have the parameter sent without being surrounded by &amp;quot;quotes&amp;quot;&lt;br /&gt;
*admin - admin level required to access the command - see [[#Admin Levels|Admin Levels]]&lt;br /&gt;
*execute - 'server' or 'player' - selects whether to execute as a client command or server command - defaults to 'player'&lt;br /&gt;
*1 - Information about parameter 1 (#1) - You need as many of these as you have parameters&lt;br /&gt;
**type - defaults to 'list' if not provided&lt;br /&gt;
***'groupplayer' 	- List of [[#Group Submenus|Groups]] + connected player &lt;br /&gt;
***'group' 			- List of [[#Group Submenus|Groups]]&lt;br /&gt;
***'player' 		- List of players&lt;br /&gt;
***'list'			- Custom Defined list of Options&lt;br /&gt;
***'mapcycle'		- Auto filled with the contents of your mapcycle file&lt;br /&gt;
***'onoff'			- On or Off menu that sends the numbers 1/0 (good for cvars etc)&lt;br /&gt;
**path - Only required for type mapcycle. Path (including file name and extension) to the file containing a list of maps (straight text formatting like mapcycle.txt) - defaults to 'mapcycle.txt'&lt;br /&gt;
**method - 'name', 'steamid', 'userid', 'userid2' (doesn't prepend the '#'), 'clientid', 'ip' - only needed for groupplayer/player menus - defaults to name&lt;br /&gt;
**title - To be shown for the parameter selection menu (optional)&lt;br /&gt;
**1-x	 - List parameters - only needed for 'list' type parameters&lt;br /&gt;
**1.-x. - Text to be shown for parameter - only needed for 'list' type parameters (optional, above will be used as text if ommited)&lt;br /&gt;
**1* - x* - Admin level required to see this option (same as the rest of the admin types)&lt;br /&gt;
&lt;br /&gt;
==Example Command==&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
&amp;quot;Commands&amp;quot;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;Fun Commands&amp;quot;&lt;br /&gt;
	{&lt;br /&gt;
		&amp;quot;Set Player Speed&amp;quot;&lt;br /&gt;
		{&lt;br /&gt;
			&amp;quot;cmd&amp;quot;			&amp;quot;sm_speed #1 @2&amp;quot;&lt;br /&gt;
			&amp;quot;admin&amp;quot;			&amp;quot;sm_kick&amp;quot;&lt;br /&gt;
			&amp;quot;execute&amp;quot;		&amp;quot;player&amp;quot;&lt;br /&gt;
			&amp;quot;1&amp;quot;&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;type&amp;quot; 		&amp;quot;groupplayer&amp;quot;&lt;br /&gt;
				&amp;quot;method&amp;quot;	&amp;quot;name&amp;quot;&lt;br /&gt;
				&amp;quot;title&amp;quot;		&amp;quot;Player/Team to Edit&amp;quot;&lt;br /&gt;
		&lt;br /&gt;
			}&lt;br /&gt;
			&amp;quot;2&amp;quot;&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;type&amp;quot; 		&amp;quot;list&amp;quot;&lt;br /&gt;
				&amp;quot;title&amp;quot;		&amp;quot;Speed Multiplier&amp;quot;&lt;br /&gt;
				&amp;quot;1&amp;quot;		&amp;quot;1.0&amp;quot;&lt;br /&gt;
				&amp;quot;1.&amp;quot;		&amp;quot;Normal&amp;quot;&lt;br /&gt;
				&amp;quot;2&amp;quot;		&amp;quot;0.8&amp;quot;&lt;br /&gt;
				&amp;quot;2.&amp;quot;		&amp;quot;80%&amp;quot;&lt;br /&gt;
				&amp;quot;3&amp;quot;		&amp;quot;0.5&amp;quot;&lt;br /&gt;
				&amp;quot;3.&amp;quot;		&amp;quot;Half&amp;quot;&lt;br /&gt;
				&amp;quot;4&amp;quot;		&amp;quot;1.5&amp;quot;&lt;br /&gt;
				&amp;quot;4.&amp;quot;		&amp;quot;50% Boost&amp;quot;&lt;br /&gt;
				&amp;quot;5&amp;quot;		&amp;quot;2.0&amp;quot;&lt;br /&gt;
				&amp;quot;5.&amp;quot;		&amp;quot;Double&amp;quot;&lt;br /&gt;
				&amp;quot;5*&amp;quot;		&amp;quot;sm_ban&amp;quot; &lt;br /&gt;
				//restrict the double option to admins who have access to the 'sm_ban' override&lt;br /&gt;
			}&lt;br /&gt;
		&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
Using the above as the contents of your adminmenu_custom.txt config file would create a new category option in the admin menu called 'Fun Commands'.&lt;br /&gt;
*This category would contain an option called : &amp;quot;Set Player Speed&amp;quot;.&lt;br /&gt;
*Selecting it would prompt another menu titled: &amp;quot;Player/Team to Edit&amp;quot; containing a list of Groups and Player Names.&lt;br /&gt;
*Selecting one of these would prompt a second menu titled &amp;quot;Speed Multiplier&amp;quot;.&lt;br /&gt;
*List of options like &amp;quot;Normal&amp;quot;, &amp;quot;80%&amp;quot; etc.&lt;br /&gt;
*Example command sent if the user selected &amp;quot;Double&amp;quot; (through the player using FakeClientCommand)  - 'sm_speed &amp;quot;@CT&amp;quot; 2.0'&lt;br /&gt;
&lt;br /&gt;
NB: You can use \ as an escape character. So \&amp;quot; will let you add quotes to your strings.&lt;br /&gt;
&lt;br /&gt;
==Admin Levels==&lt;br /&gt;
&lt;br /&gt;
	All 'admin' types now require a string command name. This command can be already existing (sm_ban) or completely imaginary (onlycrabscanusethis).&lt;br /&gt;
	&lt;br /&gt;
	If the command exists that section (or list option) will require the exact same access level as that command (including any overrides you have specified).&amp;lt;br&amp;gt;&lt;br /&gt;
	E.g. You use sm_ban as the admin level for a submenu, so anyone that can access sm_ban will also be able to access this menu option (By default this is admins with the 'ban' flag). However if you have overridden sm_ban in one of your lower groups (&amp;quot;override&amp;quot; &amp;quot;allow&amp;quot; - in admin_groups.cfg). This group will also have access.&lt;br /&gt;
	&lt;br /&gt;
	If the command doesn't exist you will need to add it to your overrides sections as if it was a normal command. This can be done in admin_overrides.cfg (to assign flag letters to this command),&lt;br /&gt;
	and/or in admin_groups.cfg (to give access to the command to a specified group or remove it from a group even though they have the flag)&lt;br /&gt;
&lt;br /&gt;
If no admin level is specified for a base command it will default to the first argument of the &amp;quot;cmd&amp;quot; string. For example having&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
&amp;quot;cmd&amp;quot;		&amp;quot;sm_ban #1 #2&amp;quot;&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
would have a default admin override string of 'sm_ban'&lt;br /&gt;
	&lt;br /&gt;
For more information, see [[Overriding Command Access (SourceMod)|Overriding Command Access]]&lt;br /&gt;
&lt;br /&gt;
==Group Submenus==&lt;br /&gt;
&lt;br /&gt;
Types 'group' and 'groupplayer' auto-add pre configured options to the menu. These options are configured using sourcemod/configs/adminmenu_grouping.txt&lt;br /&gt;
&lt;br /&gt;
They are generally used to provide common commands like '@all' , '@t' etc to your menus.&lt;br /&gt;
&lt;br /&gt;
==Categories==&lt;br /&gt;
&lt;br /&gt;
If you wish to add items to an existing SourceMod category you will need to specify it’s internal name within the &amp;quot;commands&amp;quot; group. The three categories provided by SourceMod are:&lt;br /&gt;
&lt;br /&gt;
*PlayerCommands&lt;br /&gt;
*ServerCommands&lt;br /&gt;
*VotingCommands&lt;br /&gt;
&lt;br /&gt;
==Sorting==&lt;br /&gt;
Categories and items added using the dynamic menu can be sorted in the same way as normal items. For more information, see [[Admin Menu Configuration (SourceMod)|Admin Menu Configuration]]&lt;br /&gt;
&lt;br /&gt;
You need to specify the name you gave the command in your configuration file. For the provided example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
&amp;quot;item&amp;quot;	&amp;quot;Set Player Speed&amp;quot;&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
==Extra Uses==&lt;br /&gt;
An example of using the dynamic menu to its full potential: Giving admins access to some cvars while not letting them have general 'sm_cvar' access.&lt;br /&gt;
&lt;br /&gt;
Add the cvar you want to make available using the command directly and set the 'execute' parameter to 'server'&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
&amp;quot;cmd&amp;quot;		&amp;quot;mp_friendlyfire #1&amp;quot;&lt;br /&gt;
&amp;quot;execute&amp;quot;	&amp;quot;server&amp;quot;&lt;br /&gt;
&amp;quot;admin&amp;quot;		&amp;quot;sm_kick&amp;quot;&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
This fires the command directly through rcon so it bypasses the normal SourceMod admin requirements and only checks what you set using the 'admin' parameter. This method can be used to create a list of commonly used (and low impact) cvars that your lower admins can change at will, without giving them access to everything. The same method works for rcon commands.&lt;br /&gt;
&lt;br /&gt;
==Example Files==&lt;br /&gt;
&lt;br /&gt;
Example adminmenu_custom.txt setup with Super Commands examples:&amp;lt;br&amp;gt;&lt;br /&gt;
[http://users.alliedmods.net/~pred/supercmdsmenu.ini adminmenu_custom.txt]&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A Full example setup thanks to uE|Tekniqal:&amp;lt;br&amp;gt;&lt;br /&gt;
[http://users.alliedmods.net/~pred/smsuper.ini adminmenu_custom.txt]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://users.alliedmods.net/~pred/admin_overrides.cfg admin_overrides.cfg]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://users.alliedmods.net/~pred/admin_groups.cfg admin_groups.cfg]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Documentation]]&lt;br /&gt;
&lt;br /&gt;
{{LanguageSwitch}}&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Main_Page&amp;diff=9097</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Main_Page&amp;diff=9097"/>
		<updated>2013-10-15T05:30:07Z</updated>

		<summary type="html">&lt;p&gt;Fyren: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
Welcome to the AlliedModders Wiki. This is where you can find documentation about our projects and development.&lt;br /&gt;
&lt;br /&gt;
=Projects=&lt;br /&gt;
{| width=&amp;quot;80%&amp;quot; style=&amp;quot;text-align: left;&amp;quot;&lt;br /&gt;
| style=&amp;quot;width: 110px;&amp;quot; | [[Image:Sm_small.gif|left]]&lt;br /&gt;
| style=&amp;quot;vertical-align: top;&amp;quot; | [[SourceMod]], the optimized and highly extensible scripting and administration environment for [[Half-Life 2]].&lt;br /&gt;
* [[:Category:SourceMod Documentation|Documentation]]&lt;br /&gt;
* [[:Category:SourceMod Scripting|Scripting]]&lt;br /&gt;
* [[:Category:SourceMod Development|Development]]&lt;br /&gt;
| style=&amp;quot;width: 110px; padding-left: 20px;&amp;quot; | [[Image:Mms.jpg|left]]&lt;br /&gt;
| style=&amp;quot;vertical-align: top;&amp;quot; | [[Metamod:Source]], the ultimate plugin API for [[Half-Life 2]], featuring interface hooking and a versatile plugin API.&lt;br /&gt;
* [[:Category:Metamod:Source Documentation|Documentation]]&lt;br /&gt;
* [[:Category:Metamod:Source Development|Development]]&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-bottom: 20px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;padding-bottom: 20px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;padding-bottom: 20px;&amp;quot; |&lt;br /&gt;
| style=&amp;quot;padding-bottom: 20px;&amp;quot; |&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;width: 110px;&amp;quot; | [[Image:Amxxsmall.gif|left]]&lt;br /&gt;
| [[AMX Mod X]], the powerful and flexible scripting environment for [[Half-Life 1]].&lt;br /&gt;
* [[:Category:Documentation (AMX Mod X)|Documentation]]&lt;br /&gt;
* [[:Category:Scripting (AMX Mod X)|Scripting]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Mercurial Tutorial==&lt;br /&gt;
AlliedModders uses Mercurial for source code management. Interested in how it works? Check out the [[Mercurial Tutorial|Mercurial tutorial]]!&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=8340</id>
		<title>Releasing Products</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Releasing_Products&amp;diff=8340"/>
		<updated>2011-10-29T03:22:00Z</updated>

		<summary type="html">&lt;p&gt;Fyren: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is an internal page for doing AlliedModders product releases.&lt;br /&gt;
&lt;br /&gt;
=Making Builds=&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Once you are '''absolutely sure''' the product is ready for a release...&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Jump to a Linux system, check out the source tree.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Update the changelog (&amp;lt;tt&amp;gt;changelog.txt&amp;lt;/tt&amp;gt; for SourceMod, &amp;lt;tt&amp;gt;support/changelog.txt&amp;lt;/tt&amp;gt; for Metamod:Source).&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Edit the build_type file and change the &amp;quot;dev&amp;quot; string to &amp;quot;rel&amp;quot; (&amp;lt;tt&amp;gt;tools/buildbot/build_type&amp;lt;/tt&amp;gt; for SourceMod, &amp;lt;tt&amp;gt;support/buildbot/build_type&amp;lt;/tt&amp;gt; for Metamod:Source).&lt;br /&gt;
 &amp;lt;li&amp;gt;Edit &amp;lt;tt&amp;gt;product.version&amp;lt;/tt&amp;gt; to remove the -dev tag.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;For SourceMod, edit &amp;lt;tt&amp;gt;plugins/include/version.inc&amp;lt;/tt&amp;gt; to remove the -dev tag.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Commit the changes.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Push.  Watch the waterfall page until builds are complete.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Post-Build Work=&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Grab the binaries from the drop site ([http://metamodsource.net/mmsdrop/ MM:S drop site], [http://sourcemod.net/smdrop/ SourceMod drop site]).  It will be the latest package.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Install the packages on both Linux and Windows.  '''MAKE SURE THE VERSIONS ARE CORRECT.  THERE SHOULD BE NO -dev TAG.'''&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Metamod:Source checks:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
meta version&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
SourceMod checks:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sm plugins list&lt;br /&gt;
sm exts list&lt;br /&gt;
sm version&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If the versions are not correct, do not release.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;For SourceMod, you need to add the language translation packs.  &lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
  '''If this is a major release (1.X.0), there is no prior pack.  Make one:'''&lt;br /&gt;
  &amp;lt;ol&amp;gt;&lt;br /&gt;
   &amp;lt;li&amp;gt;Extract both the tar.gz and zip files to separate folders.&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li&amp;gt;Visit the [http://www.sourcemod.net/translator/?go=translate&amp;amp;op=status translator status page].&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li&amp;gt;Click &amp;quot;export languages.cfg&amp;quot; - save the new version to &amp;lt;tt&amp;gt;addons/sourcemod/configs/&amp;lt;/tt&amp;gt;, overwriting the old one.&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li&amp;gt;Click &amp;quot;export&amp;quot; next to each language that is finished.  Extract the folder to &amp;lt;tt&amp;gt;addons/sourcemod/translations/&amp;lt;/tt&amp;gt;.  For example, if you extract Spanish, you should have &amp;lt;tt&amp;gt;addons/sourcemod/translations/es/&amp;lt;/tt&amp;gt; complete with ML files.&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li&amp;gt;Repackage thefolders using the correct compression types (.tar.gz for Linux, .zip for Windows).&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;/ol&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;If this is a minor release (1.X.Y where Y != 0), there is already a prior pack.  Add it in:&amp;lt;/b&amp;gt;&lt;br /&gt;
  &amp;lt;ol&amp;gt;&lt;br /&gt;
   &amp;lt;li&amp;gt;Extract both the tar.gz and zip files to separate folders.&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li&amp;gt;Download the last minor release from the same branch as this release.&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li&amp;gt;Copy the &amp;lt;tt&amp;gt;addons/sourcemod/configs/languages.cfg&amp;lt;/tt&amp;gt; file from the old release over the new one.&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li&amp;gt;Copy the &amp;lt;tt&amp;gt;addons/sourcemod/translations/&amp;lt;/tt&amp;gt; sub-folders from the old release over to the new one.&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li&amp;gt;Repackage thefolders using the correct compression types (.tar.gz for Linux, .zip for Windows).&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;/ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;The build is done!&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Releasing to Mirrors=&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Log into iroh as yourself.  Upload your final builds to your home directory.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/scripts/amjump mirror&lt;br /&gt;
cd /scripts/mirror&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Copy your final builds from your home directory into the mirror folder.  Rename them to release names, for example: &amp;lt;tt&amp;gt;sourcemod-1.1.2-windows.zip&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;mmsource-1.8.0-linux-tar.gz&amp;lt;/tt&amp;gt;.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Mirror distribution is done with the following command:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mirror.pl &amp;lt;projectID&amp;gt; &amp;lt;releaseName&amp;gt; &amp;lt;file&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Metamod:Source's ID is 4, SourceMod's ID is 2.  For example, these commands mirrored the Metamod:Source 1.8.7 release:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mirror.pl 4 1.8.7 mmsource-1.8.7-linux.zip&lt;br /&gt;
./mirror.pl 4 1.8.7 mmsource-1.8.7-windows.tar.gz&lt;br /&gt;
./mirror.pl 4 1.8.7 mmsource-1.8.7-mac.tar.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
These commands mirrored the SourceMod 1.4.0 release:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./mirror.pl 2 1.4.0 sourcemod-1.4.0-linux.tar.gz&lt;br /&gt;
./mirror.pl 2 1.4.0 sourcemod-1.4.0-windows.zip&lt;br /&gt;
./mirror.pl 2 1.4.0 sourcemod-1.4.0-mac.zip&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Type &amp;lt;tt&amp;gt;exit&amp;lt;/tt&amp;gt; to get back to your user account.  You're done!&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Cleaning up the Tree=&lt;br /&gt;
It's time to make sure the tree is set for future development.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Run &amp;lt;tt&amp;gt;hg tag&amp;lt;/tt&amp;gt; on the last revision of the release.  Usually this is the changeset that bumped versions, and usually this is &amp;lt;tt&amp;gt;tip&amp;lt;/tt&amp;gt;.  For example, Metamod:Source:&lt;br /&gt;
&amp;lt;pre&amp;gt;hg tag mmsource-1.7.2&amp;lt;/pre&amp;gt;&lt;br /&gt;
SourceMod:&lt;br /&gt;
&amp;lt;pre&amp;gt;hg tag sourcemod-1.1.2&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Bump the minor version in &amp;lt;tt&amp;gt;product.version&amp;lt;/tt&amp;gt;. Don't forget to add -dev.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Change the &amp;lt;tt&amp;gt;tools/buildbot/build_type&amp;lt;/tt&amp;gt; (SourceMod) or &amp;lt;tt&amp;gt;support/buildbot/build_type&amp;lt;/tt&amp;gt; (Metamod:Source) contents back to &amp;quot;dev&amp;quot;.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;For SourceMod, bump the two minor versions in &amp;lt;tt&amp;gt;plugins/include/version.inc&amp;lt;/tt&amp;gt; and re-add the -dev tag to the version string.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Commit and push.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Updating the SourceMod Site=&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Visit a [http://wiki.alliedmods.net/SourceMod_Release_Notes Release Notes] page.  Copy the contents, make a new one for your specific release.  Update the changelog, relnote anything big and important.  Link back to it from the &amp;quot;main&amp;quot; relnotes page.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Jump to the sourcemod account by logging into iroh as yourself:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/scripts/amjump sourcemod&lt;br /&gt;
cd /groups/sourcemod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Edit the &amp;lt;tt&amp;gt;public_html/downloads.php&amp;lt;/tt&amp;gt; file with your favorite text editor.  Edit all instances of the old version with the new one.  Make sure to get every link, including relnotes.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Update ~/compiler-1.x to the latest minor version, where x is the major version number.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Run &amp;lt;tt&amp;gt;~/scripts/purge_old_builds.pl&amp;lt;/tt&amp;gt;, then edit its entry for 1.x.y, where x = this major release, and y = the new minor version.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Exit out of the sourcemod account.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Post news.  If you deviate from normal style, don't forget links for downloads, upgrading, and relnotes.  It also helps to say &amp;quot;this is backwards compatible&amp;quot; because users will always ask.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Updating the Metamod:Source Site=&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Jump to the alliedmodders account by logging into iroh as yourself:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/scripts/amjump alliedmodders&lt;br /&gt;
cd /groups/alliedmodders/hub/amhub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Edit the &amp;lt;tt&amp;gt;mmsource.py&amp;lt;/tt&amp;gt; file with your favorite text editor. Update the &amp;lt;tt&amp;gt;latest&amp;lt;/tt&amp;gt; version number in the &amp;lt;tt&amp;gt;downloads&amp;lt;/tt&amp;gt; function.  If this is a new major release (1.X.0), update the &amp;lt;tt&amp;gt;stable&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;devel&amp;lt;/tt&amp;gt; version numbers in the &amp;lt;tt&amp;gt;downloads&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;snapshots&amp;lt;/tt&amp;gt; functions.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Edit the &amp;lt;tt&amp;gt;templates/mmsource/downloads.html&amp;lt;/tt&amp;gt; file and update all Mercurial links with the tagged changeset ID for this release.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Edit the &amp;lt;tt&amp;gt;templates/mmsource/navbar.html&amp;lt;/tt&amp;gt; file and replace all instances of the old version with the new one.&lt;br /&gt;
 &amp;lt;li&amp;gt;Run the following command:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
touch ../run/apache.wsgi&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Post news.  Do this by making a post in [https://forums.alliedmods.net/forumdisplay.php?f=124 this forum], which is private.  LOOK AT OLDER POSTS - you need to write valid XHTML!&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Exit out of the alliedmodders account.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Updating Translations=&lt;br /&gt;
This section applies to SourceMod major releases. In order to update the translator tool, shell in as the &amp;quot;sourcemod&amp;quot; user. Find the translation folder. Run the following steps:&lt;br /&gt;
* cd sourcemod-central&lt;br /&gt;
* hg pull -u&lt;br /&gt;
* cd ..&lt;br /&gt;
* ./sync_lang_files.pl sourcemod-central/translations&lt;br /&gt;
&lt;br /&gt;
Any languages with a non-green status will not be exported, so a few weeks before a release it is a good idea to post news asking for translators.&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Timers_(SourceMod_Scripting)&amp;diff=7775</id>
		<title>Timers (SourceMod Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Timers_(SourceMod_Scripting)&amp;diff=7775"/>
		<updated>2010-07-15T01:30:54Z</updated>

		<summary type="html">&lt;p&gt;Fyren: a year later and yet...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Timers in [[SourceMod]] are timed events that occur once or repeatedly at a given interval.&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
Timers allow you to set an interval, a function to use as the event callback, and an optional Handle to pass through the callback.  This is useful for saving data asynchronously.&lt;br /&gt;
&lt;br /&gt;
All timer functions are in &amp;lt;tt&amp;gt;plugins/include/timers.inc&amp;lt;/tt&amp;gt;.  &lt;br /&gt;
&lt;br /&gt;
=Basic Usage=&lt;br /&gt;
==One-Time Timers==&lt;br /&gt;
One-time timers are timers that only execute once.  An example of a one-time timer might look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	CreateTimer(5.0, LoadStuff)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action:LoadStuff(Handle:timer)&lt;br /&gt;
{&lt;br /&gt;
	PrintToServer(&amp;quot;Loading stuff!&amp;quot;)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code will print &amp;quot;Loading stuff!&amp;quot; to the server console five seconds after the map loads.  The return value has no meaning for one-time timers.&lt;br /&gt;
&lt;br /&gt;
==Repeatable Timers==&lt;br /&gt;
Repeatable timers execute infinitely many times, once every interval.  Based on the return value, they either continue or cancel.&lt;br /&gt;
&lt;br /&gt;
For example, say you want to display a message five times, once every three seconds:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
DoMessage()&lt;br /&gt;
{&lt;br /&gt;
	CreateTimer(3.0, PrintMsg, _, TIMER_REPEAT)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action:PrintMsg(Handle:timer)&lt;br /&gt;
{&lt;br /&gt;
	static NumPrinted = 0&lt;br /&gt;
	if (NumPrinted++ &amp;gt;= 5)&lt;br /&gt;
	{&lt;br /&gt;
		PrintToServer(&amp;quot;Warning! This is a message.&amp;quot;)&lt;br /&gt;
		NumPrinted = 0&lt;br /&gt;
&lt;br /&gt;
		return Plugin_Stop&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Continue&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &amp;lt;tt&amp;gt;Plugin_Stop&amp;lt;/tt&amp;gt; stops the timer, and &amp;lt;tt&amp;gt;Plugin_Continue&amp;lt;/tt&amp;gt; allows it to continue repeating.&lt;br /&gt;
&lt;br /&gt;
=Passing Data=&lt;br /&gt;
==Simple Values==&lt;br /&gt;
As mentioned earlier, timers let you pass values on to the callback function.  This value can be any type.  For example, let's say we want to print a message to a player fifteen seconds after they connect.  However, we want to cancel the timer if the player disconnects.  Implementing this is very easy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;#define MAX_PLAYERS 256&lt;br /&gt;
&lt;br /&gt;
new Handle:WelcomeTimers[MAX_PLAYERS+1]&lt;br /&gt;
&lt;br /&gt;
public OnClientPutInServer(client)&lt;br /&gt;
{&lt;br /&gt;
	WelcomeTimers[client] = CreateTimer(15.0, WelcomePlayer, client)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public OnClientDisconnect(client)&lt;br /&gt;
{&lt;br /&gt;
	if (WelcomeTimers[client] != INVALID_HANDLE)&lt;br /&gt;
	{&lt;br /&gt;
		KillTimer(WelcomeTimers[client])&lt;br /&gt;
		WelcomeTimers[client] = INVALID_HANDLE&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action:WelcomePlayer(Handle:timer, any:client)&lt;br /&gt;
{&lt;br /&gt;
	PrintToConsole(client, &amp;quot;Welcome to the server!&amp;quot;)&lt;br /&gt;
	WelcomeTimers[client] = INVALID_HANDLE&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Handles==&lt;br /&gt;
If you want to pass a Handle as a value, you have the option of using &amp;lt;tt&amp;gt;TIMER_HNDL_CLOSE&amp;lt;/tt&amp;gt;, which will automatically call &amp;lt;tt&amp;gt;CloseHandle()&amp;lt;/tt&amp;gt; for you once the timer dies.  &lt;br /&gt;
&lt;br /&gt;
==Data Packs==&lt;br /&gt;
Data packs are packable structures that can be used to hold asynchronous data (data that must be saved and unpacked for later).  They are especially useful for timers, and thus there exists a helper function, called &amp;lt;tt&amp;gt;CreateDataTimer()&amp;lt;/tt&amp;gt;, which creates a timer using a data pack handle.  The handle is created and closed automatically for you.&lt;br /&gt;
&lt;br /&gt;
The above example could be rewritten as:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#define MAX_PLAYERS 256&lt;br /&gt;
&lt;br /&gt;
new Handle:WelcomeTimers[MAX_PLAYERS+1]&lt;br /&gt;
&lt;br /&gt;
public OnClientPutInServer(client)&lt;br /&gt;
{&lt;br /&gt;
	new Handle:pack&lt;br /&gt;
	WelcomeTimers[client] = CreateDataTimer(15.0, WelcomePlayer, pack)&lt;br /&gt;
	WritePackCell(pack, client)&lt;br /&gt;
	WritePackString(pack, &amp;quot;Welcome to the server!&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public OnClientDisconnect(client)&lt;br /&gt;
{&lt;br /&gt;
	if (WelcomeTimers[client] != INVALID_HANDLE)&lt;br /&gt;
	{&lt;br /&gt;
		KillTimer(WelcomeTimers[client])&lt;br /&gt;
		WelcomeTimers[client] = INVALID_HANDLE&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action:WelcomePlayer(Handle:timer, Handle:pack)&lt;br /&gt;
{&lt;br /&gt;
	decl String:str[128]&lt;br /&gt;
	new client&lt;br /&gt;
&lt;br /&gt;
	/* Set to the beginning and unpack it */&lt;br /&gt;
	ResetPack(pack)&lt;br /&gt;
	client = ReadPackCell(pack)&lt;br /&gt;
	ReadPackString(pack, str, sizeof(str))&lt;br /&gt;
&lt;br /&gt;
	PrintToConsole(client, &amp;quot;%s&amp;quot;, str)&lt;br /&gt;
	WelcomeTimers[client] = INVALID_HANDLE&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Notes=&lt;br /&gt;
==Accuracy==&lt;br /&gt;
The smallest possible interval is 0.1 seconds.  Timers have high precision (floating point) but low accuracy, as the current time is based on the in-game tick count, not the system clock.  This has two implications:&lt;br /&gt;
*If the server is paused (not ticking), timers will not run.&lt;br /&gt;
*The server will not always tick at an exact interval.  &lt;br /&gt;
&lt;br /&gt;
For example, a 1.234 second interval timer starting from time &amp;lt;tt&amp;gt;t&amp;lt;/tt&amp;gt; might not tick until &amp;lt;tt&amp;gt;t+1.242&amp;lt;/tt&amp;gt; at a tickrate of 66 ticks per second.&lt;br /&gt;
&lt;br /&gt;
==Timer Death==&lt;br /&gt;
All timers are guaranteed to die either by:&lt;br /&gt;
*&amp;lt;tt&amp;gt;CloseHandle()&amp;lt;/tt&amp;gt; being called (or on plugin unload);&lt;br /&gt;
*&amp;lt;tt&amp;gt;KillTimer()&amp;lt;/tt&amp;gt; being called;&lt;br /&gt;
*&amp;lt;tt&amp;gt;Plugin_Stop&amp;lt;/tt&amp;gt; being returned from a repeatable timer;&lt;br /&gt;
*&amp;lt;tt&amp;gt;TriggerTimer()&amp;lt;/tt&amp;gt; being called on a one-time timer;&lt;br /&gt;
*Execution of a one-time timer finishes.&lt;br /&gt;
&lt;br /&gt;
When a timer dies, if &amp;lt;tt&amp;gt;TIMER_HNDL_CLOSE&amp;lt;/tt&amp;gt; is set, the Handle will always be closed with the permissions that &amp;lt;tt&amp;gt;CloseHandle()&amp;lt;/tt&amp;gt; uses by default.  Since timers cannot be cloned, there should be no ownership issues.&lt;br /&gt;
&lt;br /&gt;
==Changing Intervals==&lt;br /&gt;
The interval of a timer cannot be changed as of this writing.  The timer must be killed and a new one created.&lt;br /&gt;
&lt;br /&gt;
==AMX Mod X==&lt;br /&gt;
Unlike [[AMX Mod X]]'s &amp;lt;tt&amp;gt;set_task&amp;lt;/tt&amp;gt; function, you cannot pass arrays using &amp;lt;tt&amp;gt;CreateTimer&amp;lt;/tt&amp;gt;.  To accomplish this, you should use the data pack functionality explained above.&lt;br /&gt;
&lt;br /&gt;
Similarly, there are no flags for counted repeats (non-infinite loops) or timers based on the map start or end.  These must be done manually.&lt;br /&gt;
&lt;br /&gt;
=External Links=&lt;br /&gt;
*[http://www.sourcemod.net/devlog/?p=130 On Timer Design, Part 3] (SourceMod DevLog)&lt;br /&gt;
*[http://www.sourcemod.net/devlog/?p=119 On Timer Design, Part 2] (SourceMod DevLog)&lt;br /&gt;
*[http://www.sourcemod.net/devlog/?p=118 On Timer Design, Part 1] (SourceMod DevLog)&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Scripting]]&lt;br /&gt;
&lt;br /&gt;
{{LanguageSwitch}}&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Building_SourceMod&amp;diff=7476</id>
		<title>Building SourceMod</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Building_SourceMod&amp;diff=7476"/>
		<updated>2009-12-24T05:46:18Z</updated>

		<summary type="html">&lt;p&gt;Fyren: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Compiling SourceMod is not difficult, but requires a number of prerequisites.  This article details the requirements and steps to being able to build working SourceMod binaries.  These directions may change any time and may be updated as SourceMod's build process improves.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' You cannot use MingW to build working SourceMod Windows binaries.  It is not ABI compatible with Visual C++ which is what Valve uses for the Source engine.  You can only use GCC to build Linux binaries.&lt;br /&gt;
&lt;br /&gt;
=Requirements=&lt;br /&gt;
&lt;br /&gt;
==Windows==&lt;br /&gt;
*Microsoft Visual C++ 2008 (Express or higher) is supported and used for official builds.&lt;br /&gt;
*Microsoft Visual C++ 2005 (Express or higher) is unsupported.&lt;br /&gt;
*Microsoft Visual C++ 2003 7.1 or higher may not build out-of-box, but can build compatible binaries.&lt;br /&gt;
*Microsoft Visual C++ 2003 7.0 or lower '''cannot''' be used.&lt;br /&gt;
&lt;br /&gt;
If you are installing Visual C++ 2005 Express, it may not come with Microsoft's Platform SDK installed.  If this is the case, you must manually install the Platform SDK.  You can find directions on how to do this and test your setup [http://www.microsoft.com/express/2005/platformsdk/default.aspx here].  Visual C++ 2008 &amp;quot;streamlines&amp;quot; the Platform SDK installation according to Microsoft.&lt;br /&gt;
&lt;br /&gt;
==Linux==&lt;br /&gt;
For Linux, SourceMod requires the GNU C/C++ Compiler (from GCC):&lt;br /&gt;
*Version 4.1 is used for official binaries and is guaranteed to build.&lt;br /&gt;
*Versions 3.4 through 4.2 are guaranteed to be binary (ABI) compatible, although SourceMod may not necessarily build out-of-box against them.&lt;br /&gt;
*Any GCC version below 3.4 '''cannot''' be used.&lt;br /&gt;
&lt;br /&gt;
==CPU==&lt;br /&gt;
SourceMod is strictly a 32-bit x86 (IA32) product.  You should not try to force a compiler to build 64-bit binaries of SourceMod.&lt;br /&gt;
&lt;br /&gt;
Your CPU and its compiler must support SSE in order to build SourceMod.  To build without needing or having a dependency against SSE, please see the [[Compiling SourceMod#Removing SSE|Removing SSE]] section near the bottom.&lt;br /&gt;
&lt;br /&gt;
Approximate compiling times for SourceMod's Core are roughly:&lt;br /&gt;
*Windows, Core 2 Quad E6600: 30 seconds (using /MP)&lt;br /&gt;
*Windows, Core 2 Duo E6600: 75 seconds&lt;br /&gt;
*Windows, Centrino 1.8GHz: 5 minutes&lt;br /&gt;
*Linux, Core 2 Duo E6600: &amp;lt;= 1 minute&lt;br /&gt;
*Linux, P3 Dual 500MHz: &amp;gt;= 7 minutes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Setup=&lt;br /&gt;
This section describes how to set up your computer for compiling.&lt;br /&gt;
&lt;br /&gt;
==Getting the Files==&lt;br /&gt;
This section describes which files you must obtain and how to obtain them.  Do not worry about where to place them yet -- that will be discussed on a per-platform basis.  You can download the files anywhere you'd like.&lt;br /&gt;
&lt;br /&gt;
The recommended method of getting the required files is via [http://subversion.tigris.org/ Subversion].  We have our own [[Subversion Tutorial]] if you prefer that method.  Although you do not need both HL2SDK versions (unless you wish to build binaries against both), you do need both Metamod:Source versions.  Extensions don't necessarily require Metamod:Source (or even the Source Engine) but its template library is used extensively in SourceMod.&lt;br /&gt;
&lt;br /&gt;
*SourceMod. For full download options, see the [http://www.sourcemod.net/downloads.php SourceMod Downloads] page.  Obviously, you must download the source code and not a binary package.&lt;br /&gt;
*HL2SDK Original.  As of this writing (Sep 2008) this engine is used for most Source games, except for TF2, GMod10, and DoD:S. Repository: [http://hg.alliedmods.net/hl2sdk hl2sdk]&lt;br /&gt;
*HL2SDK OrangeBox.  As of this writing (Sep 2008) this engine is used TF2, GMod10, and DoD:S. Repository: [http://hg.alliedmods.net/hl2sdk-ob hl2sdk-ob]&lt;br /&gt;
*HL2SDK Left4Dead. This engine is used for L4D. Repository: [http://hg.alliedmods.net/hl2sdk-l4d hl2sdk-l4d]&lt;br /&gt;
*Metamod:Source Source Code. Visit [http://www.metamodsource.net/?go=downloads Metamod:Source downloads]. Right now SourceMod builds against Metamod:Source 1.7.&lt;br /&gt;
&lt;br /&gt;
'''Note''' that when we refer to &amp;quot;Metamod:Source&amp;quot; in this article, we are referring to its source code tree, not a binary package.&lt;br /&gt;
&lt;br /&gt;
If you intend to compile the MySQL extension, you must also download MySQL 5.0.  You can use any version.  For simplicity, here are the versions we use:&lt;br /&gt;
*Linux: We use the 5.0.45 binary from the &amp;quot;[http://dev.mysql.com/downloads/mysql/5.0.html#linux Linux (non RPM packages)]&amp;quot; for &amp;quot;Linux (x86).&amp;quot;  You can also use [http://dev.mysql.com/get/Downloads/MySQL-5.0/mysql-5.0.45-linux-i686-glibc23.tar.gz/from/pick this direct link] (may not be valid in the future).&lt;br /&gt;
*Windows: Due to a MySQL build change we use 5.0.24a which is an older download.  The file name was &amp;quot;mysql-5.0.24a-win32.zip,&amp;quot; if you can't find it you can use this [http://www.bailopan.net/mysql-5.0.24a-win32.zip direct link] (may not be valid in the future).&lt;br /&gt;
&lt;br /&gt;
You can remove all folders from the distribution except for the &amp;quot;lib&amp;quot; and &amp;quot;include&amp;quot; folders which comprise the MySQL SDK.&lt;br /&gt;
&lt;br /&gt;
==Linux==&lt;br /&gt;
As of this writing, SourceMod's Makefiles are hardcoded to use a binary called &amp;quot;gcc-4.1&amp;quot;  You can override this, for example:&lt;br /&gt;
&amp;lt;pre&amp;gt;make CPP=gcc&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Otherwise, you can also just create a symlink:&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo ln -s /usr/bin/gcc /usr/bin/gcc-4.1&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that you must use &amp;lt;tt&amp;gt;gcc&amp;lt;/tt&amp;gt; and not &amp;lt;tt&amp;gt;g++&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
SourceMod's Makefiles have strict directory organizational rules.  You must have a top-level folder.  For this document, we'll assume it is called &amp;lt;tt&amp;gt;sourcemod&amp;lt;/tt&amp;gt;, though it can be named anything.  The layout of &amp;lt;tt&amp;gt;sourcemod&amp;lt;/tt&amp;gt; must be:&lt;br /&gt;
*&amp;lt;tt&amp;gt;sourcemod&amp;lt;/tt&amp;gt;/&lt;br /&gt;
**&amp;lt;tt&amp;gt;hl2sdk&amp;lt;/tt&amp;gt; - symlink or folder containing the HL2SDK&lt;br /&gt;
**&amp;lt;tt&amp;gt;hl2sdk-ob&amp;lt;/tt&amp;gt; - symlink or folder containing the HL2SDK for Orange Box/TF&lt;br /&gt;
**&amp;lt;tt&amp;gt;mmsource-1.7&amp;lt;/tt&amp;gt; - symlink or folder containing any Metamod:Source version 1.7 or higher.&lt;br /&gt;
**&amp;lt;tt&amp;gt;sourcemod-central&amp;lt;/tt&amp;gt; - folder containing SourceMod's source code tree.  This can be named anything, as long as it's a valid SourceMod tree (like [http://hg.alliedmods.net/sourcemod-central sourcemod-central]).  You can also use [http://hg.alliedmods.net/sourcemod-1.1 sourcemod-1.1].&lt;br /&gt;
**&amp;lt;tt&amp;gt;mysql-5.0&amp;lt;/tt&amp;gt; - symlink or folder containing a MySQL 5.0 distribution&lt;br /&gt;
&lt;br /&gt;
If you are using a 64-bit version of Linux, you may need to install extra packages to be able to compile SourceMod.  On Debian-based distros, these are typically:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#prerequisites&lt;br /&gt;
#apt-get install g++-4.1 gcc-4.1 make subversion&lt;br /&gt;
#apt-get instal libz libz-dev&lt;br /&gt;
#only needed if you want to use the build tool&lt;br /&gt;
#apt-get install mono mono-devel&lt;br /&gt;
#32-bit support&lt;br /&gt;
apt-get install ia32-libs&lt;br /&gt;
apt-get install lib32z1 lib32z1-dev&lt;br /&gt;
apt-get install libc6-dev-i386 libc6-i386&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Windows==&lt;br /&gt;
On Windows we don't require a particular directory layout.  Instead, environment variables are used.  The directions below apply to Windows XP, and are assumed to be similar for other versions of Windows.&lt;br /&gt;
*Open the Control Panel (for example, via Start -&amp;gt; Settings).&lt;br /&gt;
*Open the System control.  If you don't see it, you may need to switch to &amp;quot;Classic view&amp;quot; (either via the left-hand pane or by going to Tools -&amp;gt; Folder Options).&lt;br /&gt;
*Click the Advanced tab.&lt;br /&gt;
*Click the Environment Variables button.&lt;br /&gt;
&lt;br /&gt;
You can add your environment variables to either your User settings or your System settings.  Create a new variable for each item in the list below.  The item names are in &amp;lt;tt&amp;gt;fixed-width font&amp;lt;/tt&amp;gt; and their value descriptions follow.&lt;br /&gt;
*&amp;lt;tt&amp;gt;MMSOURCE17&amp;lt;/tt&amp;gt; - Path to Metamod:Source 1.7+&lt;br /&gt;
*&amp;lt;tt&amp;gt;MMSOURCE18&amp;lt;/tt&amp;gt; - Path to Metamod:Source 1.8+&lt;br /&gt;
*&amp;lt;tt&amp;gt;HL2SDK&amp;lt;/tt&amp;gt; - Path to HL2SDK Ep1/Original&lt;br /&gt;
*&amp;lt;tt&amp;gt;HL2SDKOB&amp;lt;/tt&amp;gt; - Path to HL2SDK Ep2/OrangeBox for mods&lt;br /&gt;
*&amp;lt;tt&amp;gt;HL2SDKOBVALVE&amp;lt;/tt&amp;gt; - Path to HL2SDK Ep2/OrangeBox for Valve games (TF2 and DoD:S)&lt;br /&gt;
*&amp;lt;tt&amp;gt;HL2SDKL4D&amp;lt;/tt&amp;gt; - Path to HL2SDK L4D1&lt;br /&gt;
*&amp;lt;tt&amp;gt;HL2SDKL4D2&amp;lt;/tt&amp;gt; - Path to HL2SDK L4D2&lt;br /&gt;
&lt;br /&gt;
=Building=&lt;br /&gt;
SourceMod has two types of binaries: those with an engine/MM:S dependence, and those without (&amp;quot;normal&amp;quot; binaries).  Normal binaries have two modes:&lt;br /&gt;
*&amp;lt;tt&amp;gt;Release&amp;lt;/tt&amp;gt; - Optimized binary for release.&lt;br /&gt;
*&amp;lt;tt&amp;gt;Debug&amp;lt;/tt&amp;gt; - Unoptimized binary with debugging checks.&lt;br /&gt;
&lt;br /&gt;
Engine/MM:S dependent binaries have three build modes, each paired with either Release or Debug, meaning there are six build options total.  They are:&lt;br /&gt;
*&amp;lt;tt&amp;gt;Original&amp;lt;/tt&amp;gt; - Building against MM:S 1.4 API with HL2SDK&lt;br /&gt;
*&amp;lt;tt&amp;gt;Episode2&amp;lt;/tt&amp;gt; - Building against MM:S 1.6 API with HL2SDK-OB or higher&lt;br /&gt;
&lt;br /&gt;
==Linux==&lt;br /&gt;
For both Normal and Engine/MM:S dependent binaries, the object files and the final binary are placed in a folder called &amp;lt;tt&amp;gt;Release&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;Debug&amp;lt;/tt&amp;gt; (in the same level as the Makefile) depending on which building mechanism you chose.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Our Makefiles are not set up to detect changes in header files.  If you change a header file, you must clean your build.&lt;br /&gt;
&lt;br /&gt;
===Normal Binaries===&lt;br /&gt;
For normal binaries, you can build simply with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;make&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can clean stale object files with:&lt;br /&gt;
&amp;lt;pre&amp;gt;make clean&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or build debug builds with:&lt;br /&gt;
&amp;lt;pre&amp;gt;make DEBUG=true&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Dependent Binaries===&lt;br /&gt;
Binaries that have an Engine or MM:S dependency require one extra parameter, &amp;lt;tt&amp;gt;ENGINE&amp;lt;/tt&amp;gt;.  It must be either &amp;lt;tt&amp;gt;orangebox&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;original&amp;lt;/tt&amp;gt;.  For example, to build a TF-compatible binary in debug mode:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;make ENGINE=orangebox DEBUG=true&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dependent binaries are dropped into one of the following folders:&lt;br /&gt;
*Debug.original&lt;br /&gt;
*Debug.orangebox&lt;br /&gt;
*Release.original&lt;br /&gt;
*Release.orangebox&lt;br /&gt;
&lt;br /&gt;
==Windows==&lt;br /&gt;
Windows project files end with &amp;lt;tt&amp;gt;.vcproj&amp;lt;/tt&amp;gt; and are found in an &amp;lt;tt&amp;gt;msvc8&amp;lt;/tt&amp;gt; folder that resides inside each binary's main source folder.  For example, Core is located in &amp;lt;tt&amp;gt;core/msvc8/sourcemod_mm.vcproj&amp;lt;/tt&amp;gt;.  &lt;br /&gt;
&lt;br /&gt;
Once the file is opened, you can select which build to use by going to Build -&amp;gt; Configuration Manager.  Normal binaries have simply &amp;quot;Debug&amp;quot; and &amp;quot;Release.&amp;quot;  Dependent binaries have the following builds:&lt;br /&gt;
*Debug - Old Metamod&lt;br /&gt;
*Debug - Episode 2 &lt;br /&gt;
*Release - Old Metamod&lt;br /&gt;
*Release - Episode 2 &lt;br /&gt;
&lt;br /&gt;
'''Note''' that dependent binaries will have plain &amp;quot;Debug&amp;quot; and &amp;quot;Release&amp;quot; builds.  These should not be used as they are not configured.&lt;br /&gt;
&lt;br /&gt;
Once you have selected a configuration, you can compile by going to Build -&amp;gt; Build Solution.  The binaries and object files will be written to a folder inside &amp;lt;tt&amp;gt;msvc8&amp;lt;/tt&amp;gt; named after the full configuration name.  For example, using &amp;quot;Debug - Old Metamod&amp;quot; with the &amp;quot;sdktools&amp;quot; extension will result in the binary: &amp;lt;tt&amp;gt;extensions/sdktools/msvc8/Debug - Old Metamod/sdktools.ext.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Visual Studio detects changes to header files intelligently.  It is usually not necessary to rebuild a solution.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Binary Organization=&lt;br /&gt;
Although SourceMod has a somewhat unified building mechanism, each of the binaries has a different purpose.  They can be separated into the following classes:&lt;br /&gt;
&lt;br /&gt;
*Core-Related: Binaries which are required or loaded intrinsically by Core.&lt;br /&gt;
*Extensions: Binaries which are loaded via the extension mechanism.&lt;br /&gt;
*External: Binaries which are standalone or unrelated to SourceMod's live operation (for example, the compiler).&lt;br /&gt;
&lt;br /&gt;
This article is only concerned with the first two types.  &lt;br /&gt;
&lt;br /&gt;
==Core-Related Binaries==&lt;br /&gt;
Binaries related to Core are spread throughout the source code tree.  They are always placed in &amp;lt;tt&amp;gt;sourcemod/bin&amp;lt;/tt&amp;gt; for packaging.  The projects files related to Core are:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tt&amp;gt;loader&amp;lt;/tt&amp;gt; - This is a very small wrapper binary responsible for detecting the MM:S version and game engine, and deciding which SourceMod version to load.  The output binary is &amp;lt;tt&amp;gt;sourcemod_mm_i486.so&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;sourcemod_mm.dll&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;core&amp;lt;/tt&amp;gt; - This is Core itself, and is a dependent binary.  It has three outputs:&lt;br /&gt;
**Original: &amp;lt;tt&amp;gt;sourcemod.1.ep1.so&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;sourcemod.1.ep1.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
**Episode 1: &amp;lt;tt&amp;gt;sourcemod.1.ep1.so&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;sourcemod.2.ep1.dll&amp;lt;/tt&amp;gt; (unsupported, not packaged)&lt;br /&gt;
**Episode 2: &amp;lt;tt&amp;gt;sourcemod.1.ep1.so&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;sourcemod.2.ep2.dll&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;sourcepawn/jit/x86&amp;lt;/tt&amp;gt; - This is the SourcePawn JIT for generating IA32/x86 instructions from &amp;lt;tt&amp;gt;.smx&amp;lt;/tt&amp;gt; files.  Currently the source code for this is not made available.  It is built as &amp;lt;tt&amp;gt;sourcepawn.jit.x86.so&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;sourcepawn.jit.x86.dll&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is technically not necessary to use the loader.  It is provided as a convenience so users do not have to perform extra steps while installing SourceMod.  However, it is highly recommend that you do use it in order to maintain similarity with the default SourceMod package.&lt;br /&gt;
&lt;br /&gt;
==Extensions==&lt;br /&gt;
Extensions are found in the &amp;lt;tt&amp;gt;extensions&amp;lt;/tt&amp;gt; folder of the source tree.  SDKTools, Cstrike, and the upcoming TF extension are engine/MM:S dependent (and the rest are generally not).&lt;br /&gt;
&lt;br /&gt;
Extensions always are named &amp;lt;tt&amp;gt;name.ext.so&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;name.ext.dll&amp;lt;/tt&amp;gt; where &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; is a unique identifier.  This is true even of dependent binaries.  &lt;br /&gt;
&lt;br /&gt;
When loading extensions, SourceMod looks in two separate folders.  First, it checks the ''dependent extension folder'', which is &amp;lt;tt&amp;gt;extensions/auto.x.y&amp;lt;/tt&amp;gt; where &amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt; is the MM:S version (1 for 1.4, 2 for 1.6) and &amp;lt;tt&amp;gt;y&amp;lt;/tt&amp;gt; is the Engine version (1 for Original/Ep1, 2 for Ep2/OrangeBox).  If no matching extension is found there, it looks in &amp;lt;tt&amp;gt;extensions&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For example, the SDKTools binary on Counter-Strike would be loaded from &amp;lt;tt&amp;gt;extensions/auto.1.ep1&amp;lt;/tt&amp;gt;, but the GeoIP binary (which is not dependent) would be loaded from &amp;lt;tt&amp;gt;extensions&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Removing SSE=&lt;br /&gt;
SourceMod binaries are built against SSE by default.  SSE is an important set of optimizations, that, according to Valve's hardware survey, are supported on 99.6% percent of respondents' computers.  If you are in this 0.4% which does not have SSE support, you should consider buying a newer processor.  Only early Pentium 3-grade processors did not have SSE support (for example, the very early Durons), and it is likely your Source server will not perform adequately to support more than few players.&lt;br /&gt;
&lt;br /&gt;
Nonetheless, SourceMod's binaries can all be recompiled to remove its SSE dependence.&lt;br /&gt;
&lt;br /&gt;
==Linux==&lt;br /&gt;
Edit the Makefile of the binary you are trying to compile.  Remove all instances of these flags.  They can simply be erased, there is no need to replace them with anything.&lt;br /&gt;
*&amp;lt;tt&amp;gt;-msse&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;-mfpmath=sse&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure to clean the build after changing the Makefile.&lt;br /&gt;
&lt;br /&gt;
==Windows==&lt;br /&gt;
Load the project file into Visual Studio.  Go to Project -&amp;gt; Properties.  Expand &amp;quot;Configuration Properties,&amp;quot; and then &amp;quot;C/C++&amp;quot; under it.  Select &amp;quot;Code Generation.&amp;quot;  Change the setting &amp;quot;Enable Enhanced Instruction Set&amp;quot; to &amp;quot;Not Set.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
'''Note:''' You must change this setting '''for each build configuration''' that you wish to use.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Documentation]]&lt;br /&gt;
[[Category:SourceMod Development]]&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Upgrading_SourceMod&amp;diff=7394</id>
		<title>Upgrading SourceMod</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Upgrading_SourceMod&amp;diff=7394"/>
		<updated>2009-08-28T10:31:41Z</updated>

		<summary type="html">&lt;p&gt;Fyren: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When upgrading SourceMod, backwards compatibility is guaranteed except in rare cases.  To completely upgrade, you should:&lt;br /&gt;
&lt;br /&gt;
*If you are upgrading to a stable release (not a nightly build), check its release notes for any specific instructions.&lt;br /&gt;
*Upgrade all &amp;lt;tt&amp;gt;.so&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; binaries in the following folders:&lt;br /&gt;
**&amp;lt;tt&amp;gt;sourcemod/bin&amp;lt;/tt&amp;gt;&lt;br /&gt;
**&amp;lt;tt&amp;gt;sourcemod/extensions&amp;lt;/tt&amp;gt;&lt;br /&gt;
*Upgrade all of the &amp;lt;tt&amp;gt;.txt&amp;lt;/tt&amp;gt; files in the &amp;lt;tt&amp;gt;sourcemod/gamedata&amp;lt;/tt&amp;gt; folder.&lt;br /&gt;
*Upgrade all of the &amp;lt;tt&amp;gt;.txt&amp;lt;/tt&amp;gt; files in the &amp;lt;tt&amp;gt;sourcemod/translations&amp;lt;/tt&amp;gt; folder.&lt;br /&gt;
*Upgrade all of the default &amp;lt;tt&amp;gt;.smx&amp;lt;/tt&amp;gt; binaries in the &amp;lt;tt&amp;gt;sourcemod/plugins&amp;lt;/tt&amp;gt; folder.&lt;br /&gt;
*Read the release notes to see if there were any configuration files that got new features.  If so, you should look and see if you want to tweak those new settings.  You may want to use a program such as [http://www.scootersoftware.com/ Beyond Compare] or [http://winmerge.org/ WinMerge].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note:''' If a plugin stops working due to a SourceMod upgrade, file a bug report and the development team will assess the situation.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' It is extremely important to update all &amp;lt;tt&amp;gt;gamedata&amp;lt;/tt&amp;gt; files, as those specify how SourceMod interacts with mod-specific properties.  &lt;br /&gt;
&lt;br /&gt;
'''Note:''' As of SourceMod 1.2.2, the &amp;quot;auto&amp;quot; folders for SourceMod extensions are no longer used by default. Third party extensions, however, may still use them.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' If you update your base SourceMod plugins, you must update your translation files (and vice versa).  If you absolutely don't want to update your SourceMod base plugins, you should at least update the &amp;lt;tt&amp;gt;core.phrases.txt&amp;lt;/tt&amp;gt; translation file.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' You only need to update the .inc files if you are a plugin developer.  If you do update .inc files, you must update the compiler (spcomp.exe for Windows, spcomp for Linux) as well.&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Documentation]]&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=SourceMod_1.2.3_Release_Notes&amp;diff=7393</id>
		<title>SourceMod 1.2.3 Release Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=SourceMod_1.2.3_Release_Notes&amp;diff=7393"/>
		<updated>2009-08-28T10:15:41Z</updated>

		<summary type="html">&lt;p&gt;Fyren: Created page with '__FORCETOC__ SourceMod 1.2.3 is a minor bug-fix update.  If you need help upgrading, see Upgrading SourceMod.  To see the full 1.2 release notes, [[SourceMod 1.2.0 Release No...'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__FORCETOC__&lt;br /&gt;
SourceMod 1.2.3 is a minor bug-fix update.  If you need help upgrading, see [[Upgrading SourceMod]].  To see the full 1.2 release notes, [[SourceMod 1.2.0 Release Notes|click here]].&lt;br /&gt;
&lt;br /&gt;
*'''This release DOES NOT have configuration changes.'''&lt;br /&gt;
*'''This release DOES NOT break compatibility.'''&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
=Compatibility=&lt;br /&gt;
This release is fully backwards compatible.  It is not, however, forwards compatible.  Plugins compiled against SourceMod 1.2 will not run on 1.1 or 1.0.  If you encounter any compatibility problems, file a bug.&lt;br /&gt;
&lt;br /&gt;
=Translations=&lt;br /&gt;
SourceMod 1.2 comes with the following languages translated, thanks to [http://www.sourcemod.net/translator/?go=translate&amp;amp;op=status community translators]:&lt;br /&gt;
*Brazilian Portuguese&lt;br /&gt;
*Chinese Simplified&lt;br /&gt;
*Danish&lt;br /&gt;
*Dutch&lt;br /&gt;
*French&lt;br /&gt;
*German&lt;br /&gt;
*Hungarian&lt;br /&gt;
*Italian&lt;br /&gt;
*Japanese&lt;br /&gt;
*Latvian&lt;br /&gt;
*Norwegian&lt;br /&gt;
*Polish&lt;br /&gt;
*Romanian&lt;br /&gt;
*Russian&lt;br /&gt;
*Spanish&lt;br /&gt;
*Turkish&lt;br /&gt;
&lt;br /&gt;
=Changelog=&lt;br /&gt;
*Fixed extension name lookup. ({{bz|3975}}).&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=SourceMod_Release_Notes&amp;diff=7392</id>
		<title>SourceMod Release Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=SourceMod_Release_Notes&amp;diff=7392"/>
		<updated>2009-08-28T10:14:25Z</updated>

		<summary type="html">&lt;p&gt;Fyren: +1.2.3&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[SourceMod]] Release notes for each release:&lt;br /&gt;
&lt;br /&gt;
*[[SourceMod 1.2.3 Release Notes]]&lt;br /&gt;
*[[SourceMod 1.2.2 Release Notes]]&lt;br /&gt;
*[[SourceMod 1.2.1 Release Notes]]&lt;br /&gt;
*[[SourceMod 1.2.0 Release Notes]]&lt;br /&gt;
*[[SourceMod 1.1.2 Release Notes]]&lt;br /&gt;
*[[SourceMod 1.1.1 Release Notes]]&lt;br /&gt;
*[[SourceMod 1.1.0 Release Notes]]&lt;br /&gt;
*[[SourceMod 1.0.4 Release Notes]]&lt;br /&gt;
*[[SourceMod 1.0.3 Release Notes]]&lt;br /&gt;
*[[SourceMod 1.0.2 Release Notes]]&lt;br /&gt;
*[[SourceMod 1.0.1 Release Notes]]&lt;br /&gt;
*[[SourceMod 1.0 Release Notes]]&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Category:Game_Resources&amp;diff=7296</id>
		<title>Category:Game Resources</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Category:Game_Resources&amp;diff=7296"/>
		<updated>2009-05-28T11:13:43Z</updated>

		<summary type="html">&lt;p&gt;Fyren: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In this category you can find resources for specific mods.&lt;br /&gt;
&lt;br /&gt;
==Left 4 Dead==&lt;br /&gt;
[[Left_4_Dead_Events|Events]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Left_4_Voting|Voting]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Left_4_Dead_Netprops|NetProps]]&lt;br /&gt;
&lt;br /&gt;
==Team Fortress 2==&lt;br /&gt;
[[Team_Fortress_2_Events|Events]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://alliedmods.net/~pred/tf2classes.txt Classnames]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://alliedmods.net/~pred/ctfplayer-vtable-220509.txt CTFPlayer Virtual Functions] - Updated 22/05/09&amp;lt;br&amp;gt;&lt;br /&gt;
[http://alliedmods.net/~pred/tf-net-220509.txt Entity Properties] - Updated 22/05/09&amp;lt;br&amp;gt;&lt;br /&gt;
[http://alliedmods.net/~pred/tf-data-220509.txt DataMap Properties] - Updated 22/05/09&amp;lt;br&amp;gt;&lt;br /&gt;
[[Mod_TempEnt_List_(Source)#Team_Fortress_2|Temp Ents]]&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[http://alliedmods.net/~pred/CTFKnife%20vtable.txt CTFKnife Virtual Functions]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://alliedmods.net/~pred/CTFWeaponBase%20Vtable.txt CTFWeaponBase Virtual Functions]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Achievement IDs]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Team_Fortress_2_Weapons|Team Fortress 2 Weapon Entity Names]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Counter-Strike: Source==&lt;br /&gt;
[[Counter-Strike:_Source_Events|Events]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://alliedmods.net/~pred/csclasses.txt Classnames]&amp;lt;br&amp;gt;&lt;br /&gt;
[[CCSPlayer_offset_list_(SourceMM)|CCSPlayer Virtual Functions]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[CBaseCombatWeapon_CSS_offset_list_(SourceMM)|CBaseCombatWeapon Virtual Functions]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://alliedmods.net/~pred/csdump.txt Entity Properties]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://alliedmods.net/~pred/csdatamaps.txt DataMap Properties]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Mod_TempEnt_List_(Source)#Counter-Strike:_Source|Temp Ents]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Counter-Strike:_Source_Weapons| Counter-Strike: Source Weapons]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://wiki.alliedmods.net/images/Counter-Strike_Source_-_Cvar_List.txt Cvar List]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Timers_(SourceMod_Scripting)&amp;diff=7295</id>
		<title>Timers (SourceMod Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Timers_(SourceMod_Scripting)&amp;diff=7295"/>
		<updated>2009-05-28T11:11:43Z</updated>

		<summary type="html">&lt;p&gt;Fyren: the example is correct as is and won't leak, the edited version will leak&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Timers in [[SourceMod]] are timed events that occur once or repeatedly at a given interval.&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
Timers allow you to set an interval, a function to use as the event callback, and an optional Handle to pass through the callback.  This is useful for saving data asynchronously.&lt;br /&gt;
&lt;br /&gt;
All timer functions are in &amp;lt;tt&amp;gt;plugins/include/timers.inc&amp;lt;/tt&amp;gt;.  &lt;br /&gt;
&lt;br /&gt;
=Basic Usage=&lt;br /&gt;
==One-Time Timers==&lt;br /&gt;
One-time timers are timers that only execute once.  An example of a one-time timer might look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	CreateTimer(5.0, LoadStuff)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action:LoadStuff(Handle:timer)&lt;br /&gt;
{&lt;br /&gt;
	PrintToServer(&amp;quot;Loading stuff!&amp;quot;)&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code will print &amp;quot;Loading stuff!&amp;quot; to the server console five seconds after the map loads.  The return value has no meaning for one-time timers.&lt;br /&gt;
&lt;br /&gt;
==Repeatable Timers==&lt;br /&gt;
Repeatable timers execute infinitely many times, once every interval.  Based on the return value, they either continue or cancel.&lt;br /&gt;
&lt;br /&gt;
For example, say you want to display a message five times, once every three seconds:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
DoMessage()&lt;br /&gt;
{&lt;br /&gt;
	CreateTimer(3.0, PrintMsg, _, TIMER_REPEAT)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action:PrintMsg(Handle:timer)&lt;br /&gt;
{&lt;br /&gt;
	static NumPrinted = 0&lt;br /&gt;
	if (NumPrinted++ &amp;gt;= 5)&lt;br /&gt;
	{&lt;br /&gt;
		PrintToServer(&amp;quot;Warning! This is a message.&amp;quot;)&lt;br /&gt;
		NumPrinted = 0&lt;br /&gt;
&lt;br /&gt;
		return Plugin_Stop&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Continue&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &amp;lt;tt&amp;gt;Plugin_Stop&amp;lt;/tt&amp;gt; stops the timer, and &amp;lt;tt&amp;gt;Plugin_Continue&amp;lt;/tt&amp;gt; allows it to continue repeating.&lt;br /&gt;
&lt;br /&gt;
=Passing Data=&lt;br /&gt;
==Simple Values==&lt;br /&gt;
As mentioned earlier, timers let you pass values on to the callback function.  This value can be any type.  For example, let's say we want to print a message to a player fifteen seconds after they connect.  However, we want to cancel the timer if the player disconnects.  Implementing this is very easy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;#define MAX_PLAYERS 256&lt;br /&gt;
&lt;br /&gt;
new Handle:WelcomeTimers[MAX_PLAYERS+1]&lt;br /&gt;
&lt;br /&gt;
public OnClientPutInServer(client)&lt;br /&gt;
{&lt;br /&gt;
	WelcomeTimers[client] = CreateTimer(15.0, WelcomePlayer, client)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public OnClientDisconnect(client)&lt;br /&gt;
{&lt;br /&gt;
	if (WelcomeTimers[client] != INVALID_HANDLE)&lt;br /&gt;
	{&lt;br /&gt;
		KillTimer(WelcomeTimers[client])&lt;br /&gt;
		WelcomeTimers[client] = INVALID_HANDLE&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action:WelcomePlayer(Handle:timer, any:client)&lt;br /&gt;
{&lt;br /&gt;
	PrintToConsole(client, &amp;quot;Welcome to the server!&amp;quot;)&lt;br /&gt;
	WelcomeTimers[client] = INVALID_HANDLE&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Handles==&lt;br /&gt;
If you want to pass a Handle as a value, you have the option of using &amp;lt;tt&amp;gt;TIMER_HNDL_CLOSE&amp;lt;/tt&amp;gt;, which will automatically call &amp;lt;tt&amp;gt;CloseHandle()&amp;lt;/tt&amp;gt; for you once the timer dies.  &lt;br /&gt;
&lt;br /&gt;
==Data Packs==&lt;br /&gt;
Data packs are packable structures that can be used to hold asynchronous data (data that must be saved and unpacked for later).  They are especially useful for timers, and thus there exists a helper function, called &amp;lt;tt&amp;gt;CreateDataTimer()&amp;lt;/tt&amp;gt;, which creates a timer using a data pack handle.  The handle is created and closed automatically for you.&lt;br /&gt;
&lt;br /&gt;
The above example could be rewritten as:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#define MAX_PLAYERS 256&lt;br /&gt;
&lt;br /&gt;
new Handle:WelcomeTimers[MAX_PLAYERS+1]&lt;br /&gt;
&lt;br /&gt;
public OnClientPutInServer(client)&lt;br /&gt;
{&lt;br /&gt;
	new Handle:pack&lt;br /&gt;
	WelcomeTimers[client] = CreateDataTimer(15.0, WelcomePlayer, pack)&lt;br /&gt;
	WritePackCell(pack, client)&lt;br /&gt;
	WritePackString(pack, &amp;quot;Welcome to the server!&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public OnClientDisconnect(client)&lt;br /&gt;
{&lt;br /&gt;
	if (WelcomeTimers[client] != INVALID_HANDLE)&lt;br /&gt;
	{&lt;br /&gt;
		KillTimer(WelcomeTimers[client])&lt;br /&gt;
		WelcomeTimers[client] = INVALID_HANDLE&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action:WelcomePlayer(Handle:timer, Handle:pack)&lt;br /&gt;
{&lt;br /&gt;
	decl String:str[128]&lt;br /&gt;
	new client&lt;br /&gt;
&lt;br /&gt;
	/* Set to the beginning and unpack it */&lt;br /&gt;
	ResetPack(pack)&lt;br /&gt;
	client = ReadPackCell(pack)&lt;br /&gt;
	ReadPackString(pack, str, sizeof(str))&lt;br /&gt;
&lt;br /&gt;
	PrintToConsole(client, &amp;quot;%s&amp;quot;, str)&lt;br /&gt;
	WelcomeTimers[client] = INVALID_HANDLE&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Notes=&lt;br /&gt;
==Accuracy==&lt;br /&gt;
The smallest possible interval is 0.1 seconds.  Timers have high precision (floating point) but low accuracy, as the current time is based on the in-game tick count, not the system clock.  This has two implications:&lt;br /&gt;
*If the server is paused (not ticking), timers will not run.&lt;br /&gt;
*The server will not always tick at an exact interval.  &lt;br /&gt;
&lt;br /&gt;
For example, a 1.234 second interval timer starting from time &amp;lt;tt&amp;gt;t&amp;lt;/tt&amp;gt; might not tick until &amp;lt;tt&amp;gt;t+1.242&amp;lt;/tt&amp;gt; at a tickrate of 66 ticks per second.&lt;br /&gt;
&lt;br /&gt;
==Timer Death==&lt;br /&gt;
All timers are guaranteed to die either by:&lt;br /&gt;
*&amp;lt;tt&amp;gt;CloseHandle()&amp;lt;/tt&amp;gt; being called (or on plugin unload);&lt;br /&gt;
*&amp;lt;tt&amp;gt;KillTimer()&amp;lt;/tt&amp;gt; being called;&lt;br /&gt;
*&amp;lt;tt&amp;gt;Plugin_Stop&amp;lt;/tt&amp;gt; being returned from a repeatable timer;&lt;br /&gt;
*&amp;lt;tt&amp;gt;TriggerTimer()&amp;lt;/tt&amp;gt; being called on a one-time timer;&lt;br /&gt;
*Execution of a one-time timer finishes.&lt;br /&gt;
&lt;br /&gt;
When a timer dies, if &amp;lt;tt&amp;gt;TIMER_HNDL_CLOSE&amp;lt;/tt&amp;gt; is set, the Handle will always be closed with the permissions that &amp;lt;tt&amp;gt;CloseHandle()&amp;lt;/tt&amp;gt; uses by default.  Since timers cannot be cloned, there should be no ownership issues.&lt;br /&gt;
&lt;br /&gt;
==Changing Intervals==&lt;br /&gt;
The interval of a timer cannot be changed as of this writing.  The timer must be killed and a new one created.&lt;br /&gt;
&lt;br /&gt;
==AMX Mod X==&lt;br /&gt;
Unlike [[AMX Mod X]]'s &amp;lt;tt&amp;gt;set_task&amp;lt;/tt&amp;gt; function, you cannot pass arrays using &amp;lt;tt&amp;gt;CreateTimer&amp;lt;/tt&amp;gt;.  To accomplish this, you should use the data pack functionality explained above.&lt;br /&gt;
&lt;br /&gt;
Similarly, there are no flags for counted repeats (non-infinite loops) or timers based on the map start or end.  These must be done manually.&lt;br /&gt;
&lt;br /&gt;
=External Links=&lt;br /&gt;
*[http://www.sourcemod.net/devlog/?p=130 On Timer Design, Part 3] (SourceMod DevLog)&lt;br /&gt;
*[http://www.sourcemod.net/devlog/?p=119 On Timer Design, Part 2] (SourceMod DevLog)&lt;br /&gt;
*[http://www.sourcemod.net/devlog/?p=118 On Timer Design, Part 1] (SourceMod DevLog)&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Scripting]]&lt;br /&gt;
&lt;br /&gt;
{{LanguageSwitch}}&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Achievement_IDs&amp;diff=6986</id>
		<title>Achievement IDs</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Achievement_IDs&amp;diff=6986"/>
		<updated>2009-03-05T05:27:40Z</updated>

		<summary type="html">&lt;p&gt;Fyren: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Achievement Identification Numbers ==&lt;br /&gt;
&lt;br /&gt;
VALVe uses :&lt;br /&gt;
&lt;br /&gt;
'''CTFPlayer::AwardAchievement(int iAchievementID)''' &lt;br /&gt;
&lt;br /&gt;
in order to award a player an achievement. Each achievement has a specific ID number. The list below is a (hopefully) complete list of ID numbers.&lt;br /&gt;
&lt;br /&gt;
Format: &amp;lt;ID Number&amp;gt;: &amp;lt;Name&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Special Thanks to '''CShadowRun''' and '''predcrab''' for all their help!&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== General Achievements ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;127: Sentry Gunner&lt;br /&gt;
128: Nemesis&lt;br /&gt;
129: Hard To Kill&lt;br /&gt;
130: Master of Disguise&lt;br /&gt;
131: With Friends Like These&lt;br /&gt;
132: Dynasty&lt;br /&gt;
133: Hardcore&lt;br /&gt;
134: Powerhouse Offense&lt;br /&gt;
135: Lightning Offense&lt;br /&gt;
136: Relentless Offense&lt;br /&gt;
137: Impenetrable Defense&lt;br /&gt;
138: Impossible Defense&lt;br /&gt;
139: Head of the Class&lt;br /&gt;
140: World Traveler&lt;br /&gt;
141: Team Doctor&lt;br /&gt;
142: Flamethrower&lt;br /&gt;
145: Grey Matter&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Medic Achievements ===&lt;br /&gt;
&amp;lt;pre&amp;gt;1401: First Do No Harm&lt;br /&gt;
1402: Quadruple Bypass&lt;br /&gt;
1403: Group Health&lt;br /&gt;
1404: Surgical Prep&lt;br /&gt;
1405: Trauma Queen&lt;br /&gt;
1406: Double Blind Trial&lt;br /&gt;
1407: Play Doctor&lt;br /&gt;
1408: Triage&lt;br /&gt;
1409: Preventative Medicine&lt;br /&gt;
1410: Consultation&lt;br /&gt;
1411: Does It Hurt When I Do This?&lt;br /&gt;
1412: Peer Review&lt;br /&gt;
1413: Big Pharma&lt;br /&gt;
1414: You'll Feel a Little Prick&lt;br /&gt;
1415: Autoclave&lt;br /&gt;
1416: Blunt Trauma&lt;br /&gt;
1417: Medical Breakthrough&lt;br /&gt;
1418: Blast Assist&lt;br /&gt;
1419: Midwife Crisis&lt;br /&gt;
1420: Ubi concordia, ibi victoria&lt;br /&gt;
1421: Grand Rounds&lt;br /&gt;
1422: Infernal Medicine&lt;br /&gt;
1423: Doctor Assisted Homicide&lt;br /&gt;
1424: Placebo Effect&lt;br /&gt;
1425: Sawbones&lt;br /&gt;
1426: Intern&lt;br /&gt;
1427: Specialist&lt;br /&gt;
1428: Chief of Staff&lt;br /&gt;
1429: Hypocritical Oath&lt;br /&gt;
1430: Medical Intervention&lt;br /&gt;
1431: Second Opinion&lt;br /&gt;
1432: Autopsy Report&lt;br /&gt;
1433: FYI I am A Medic&lt;br /&gt;
1434: Family Practice&lt;br /&gt;
1435: House Call&lt;br /&gt;
1436: Bedside Manner&lt;br /&gt;
1437: Milestone 1&lt;br /&gt;
1438: Milestone 2&lt;br /&gt;
1439: Milestone 3&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pyro Achievements ===&lt;br /&gt;
&amp;lt;pre&amp;gt;1601: Combined Fire&lt;br /&gt;
1602: Weenie Roast&lt;br /&gt;
1603: Baptism By Fire&lt;br /&gt;
1604: Fire and Forget&lt;br /&gt;
1605: Firewall&lt;br /&gt;
1606: Cooking the Books&lt;br /&gt;
1607: Spontaneous Combustion&lt;br /&gt;
1608: Trailblazer&lt;br /&gt;
1609: Camp Fire&lt;br /&gt;
1610: Lumberjack&lt;br /&gt;
1611: Clearcutter&lt;br /&gt;
1612: Hot on Your Heels&lt;br /&gt;
1613: I Fry&lt;br /&gt;
1614: Firewatch&lt;br /&gt;
1615: Burn Ward&lt;br /&gt;
1616: Hot Potato&lt;br /&gt;
1617: Makin' Bacon&lt;br /&gt;
1618: Plan B&lt;br /&gt;
1619: Pyrotechnics&lt;br /&gt;
1620: Arsonist&lt;br /&gt;
1621: Controlled Burn&lt;br /&gt;
1622: Firefighter&lt;br /&gt;
1623: Pyromancer&lt;br /&gt;
1624: Next of Kindling&lt;br /&gt;
1625: OMGWTFBBQ&lt;br /&gt;
1626: Second Degree Burn&lt;br /&gt;
1627: Got A Light?&lt;br /&gt;
1628: BarbeQueQ&lt;br /&gt;
1629: Hotshot&lt;br /&gt;
1630: Dance Dance Immolation&lt;br /&gt;
1631: Dead Heat&lt;br /&gt;
1632: Pilot Light&lt;br /&gt;
1633: Freezer Burn&lt;br /&gt;
1634: Fire Chief&lt;br /&gt;
1635: Attention Getter&lt;br /&gt;
1637: Milestone 1&lt;br /&gt;
1638: Milestone 2&lt;br /&gt;
1639: Milestone 3&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Heavy Achievements===&lt;br /&gt;
&amp;lt;pre&amp;gt;1501: Iron Kurtain&lt;br /&gt;
1502: Party Loyalty&lt;br /&gt;
1503: Division of Labor&lt;br /&gt;
1504: Red Oktoberfest&lt;br /&gt;
1505: Show Trial&lt;br /&gt;
1506: Crime and Punishment&lt;br /&gt;
1507: Class Struggle&lt;br /&gt;
1508: Soviet Block&lt;br /&gt;
1509: Stalin the Kart&lt;br /&gt;
1510: Supreme Soviet&lt;br /&gt;
1511: Factory Worker&lt;br /&gt;
1512: Soviet Union&lt;br /&gt;
1513: Own the Means of Production&lt;br /&gt;
1514: Krazy Ivan&lt;br /&gt;
1515: Rasputin&lt;br /&gt;
1516: Icing on the Cake&lt;br /&gt;
1517: Crock Block&lt;br /&gt;
1518: Kollectivization&lt;br /&gt;
1519: Spyalectical Materialism&lt;br /&gt;
1520: Permanent Revolution&lt;br /&gt;
1521: Heavy Industry&lt;br /&gt;
1522: Communist Mani-Fisto&lt;br /&gt;
1523: Redistribution of Health&lt;br /&gt;
1524: Rationing&lt;br /&gt;
1525: Vanguard Party&lt;br /&gt;
1527: Pushkin the Kart&lt;br /&gt;
1528: Marxman&lt;br /&gt;
1529: Gorky Parked&lt;br /&gt;
1530: Purge&lt;br /&gt;
1531: Lenin A Hand&lt;br /&gt;
1532: Five Second Plan&lt;br /&gt;
1533: Photostroika&lt;br /&gt;
1534: Konspicuous Konsumption&lt;br /&gt;
1535: Don't Touch Sandvich&lt;br /&gt;
1536: Borscht Belt&lt;br /&gt;
1537: Milestone 1&lt;br /&gt;
1538: Milestone 2&lt;br /&gt;
1539: Milestone 3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Scout Achievements===&lt;br /&gt;
&amp;lt;pre&amp;gt;1001: First Blood&lt;br /&gt;
1002: First Blood, Part 2&lt;br /&gt;
1003: Quick Hook&lt;br /&gt;
1004: A Year to Remember&lt;br /&gt;
1005: The Cycle&lt;br /&gt;
1006: Closer&lt;br /&gt;
1007: If You Build it&lt;br /&gt;
1008: Gun Down&lt;br /&gt;
1009: Butter Up&lt;br /&gt;
1010: Doctoring the ball&lt;br /&gt;
1011: Dodgers 1, Giants 0&lt;br /&gt;
1012: Batting the Doctor&lt;br /&gt;
1013: I'm Bat Man&lt;br /&gt;
1014: Triple Steal&lt;br /&gt;
1015: Pop Fly&lt;br /&gt;
1016: Round-Tripper&lt;br /&gt;
1017: Artful Dodger&lt;br /&gt;
1018: Fall Classic&lt;br /&gt;
1019: Strike Zone&lt;br /&gt;
1020: Foul Territory&lt;br /&gt;
1021: The Big Hurt&lt;br /&gt;
1022: Brushback&lt;br /&gt;
1023: Moon Shot&lt;br /&gt;
1024: Beanball&lt;br /&gt;
1025: Retire the Runner&lt;br /&gt;
1026: Caught Napping&lt;br /&gt;
1027: Side Retired&lt;br /&gt;
1028: Triple Play&lt;br /&gt;
1029: Stealing Home&lt;br /&gt;
1030: Set the Table&lt;br /&gt;
1031: Block the Plate&lt;br /&gt;
1032: Belittled Beleaguer&lt;br /&gt;
1033: No-Hitter&lt;br /&gt;
1034: Race for the Pennant&lt;br /&gt;
1035: Out of the Park&lt;br /&gt;
1036: Milestone 1&lt;br /&gt;
1037: Milestone 2&lt;br /&gt;
1038: Milestone 3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Metamod:Source&amp;diff=6905</id>
		<title>Metamod:Source</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Metamod:Source&amp;diff=6905"/>
		<updated>2009-02-15T14:21:41Z</updated>

		<summary type="html">&lt;p&gt;Fyren: rv&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;:{{owned_project}}&lt;br /&gt;
==Introduction==&lt;br /&gt;
Metamod:Source is an API manager and interception handler that sits in between the [[Half-Life_2|Half-Life 2]] Engine (Source) and a subsequent Game Modification (MOD). It can dynamically load &amp;quot;Metamod:Source Plugins&amp;quot;, written in C++, to intercept, override, and hook Engine and GameDLL API interfaces. It also allows for inter-plugin communication.  As a backend it contains [[SourceHook]], a powerful library for safely manipulating virtual table hooks.&lt;br /&gt;
&lt;br /&gt;
[[Category:Half-Life 2]]&lt;br /&gt;
[[Category:Metamod:Source Documentation]]&lt;br /&gt;
&lt;br /&gt;
==Where to Download==&lt;br /&gt;
Metamod:Source is hosted on [http://sourceforge.net/projects/sourcemm Source Forge] or can be accessed via the [http://www.sourcemm.net/ Metamod:Source Home Page].&lt;br /&gt;
&lt;br /&gt;
==Naming Conventions==&lt;br /&gt;
The name &amp;quot;SourceMM&amp;quot; is no longer used.&lt;br /&gt;
&lt;br /&gt;
==History==&lt;br /&gt;
Metamod:Source is derived from the [[Metamod]] concept of intercepting calls between a game's engine and mod library.  While not based on the same code, the API is designed to be similar and familiar to [[Half-Life 1]] programmers.&lt;br /&gt;
&lt;br /&gt;
====SourceMod Core1====&lt;br /&gt;
Initially, the [[SourceMod]] project was started as the next-generation continuation of the [[AMX Mod X]] project.  It was designed to be a meta-interface layer for inter-communicating plugins.  However, as development continued, it was soon realized that the [[Valve Server Plugin]] interface would not be sufficient to provide proper engine access.&lt;br /&gt;
&lt;br /&gt;
[[User:PM|Pavol Marko]] (core1 developer) decided to add &amp;quot;SourceHook&amp;quot; to SourceMod core1.  It was embedded as a large library for hooking specific virtual table functions.  After multiple revisions (see [[SourceHook]] history), it became apparent that 1)SourceHook needed to be game and interface generic, and 2)SourceMod and SourceHook needed to be split into two separate projects.  The logic behind this was that SourceHook needed to be a layer above [[Valve Server Plugin]]s, in order to properly manage hooks with the least possibility of conflicts.  Furthermore, SourceMod should be a plugin to the SourceHook interface, rather than managing it.  This decision can be likened to [[Admin-Mod]]'s early decision to split into the first [[Metamod]] project.&lt;br /&gt;
&lt;br /&gt;
====SourceHook Finalized====&lt;br /&gt;
After four major revisions, [[SourceHook]] was mature enough to be used in a production environment.  While [[User:PM|PM]] concentrated on fleshing out [[SourceHook]], [[User:BAILOPAN|BAILOPAN]] and [[User:Damaged Soul|DS]] created the GameDLL wrapper portion.&lt;br /&gt;
&lt;br /&gt;
====Version 1.0====&lt;br /&gt;
On May 6, 2005, Metamod:Source 1.0 was released with SourceHook v4.1 as a backend.  GameDLL wrapping was achieved by providing the engine with fake copies of the IServerGame* interfaces.  Once the true GameDLL location was known it would be loaded by Metamod:Source.  The fake interface then directly wrapped calls to the real GameDLL.&lt;br /&gt;
&lt;br /&gt;
====Version 1.1====&lt;br /&gt;
On October 21, 2005, the first major revision of Metamod:Source was released, featuring SourceHook v4.4, internal event listeners, dropped reliance on STL, and rewritten GameDLL hooking code.  The [[Day of Defeat|Day of Defeat:Source]] release by [[VALVe_Software|Valve Software]] revealed that the binary interface between the engine and mod wasn't necessarily public or current, and MM:S's detection was improved for compatibility and speed.  Furthermore, Metamod:Source stopped wrapping the GameDLL interfaces and began using SourceHook to hook them.&lt;br /&gt;
&lt;br /&gt;
====Version 1.2====&lt;br /&gt;
On January 7th, 2006, Metamod:Source was updated for SourceHook v4.3, but received no major API changes.&lt;br /&gt;
&lt;br /&gt;
====Version 1.3====&lt;br /&gt;
On August 16th, 2006, Metamod:Source was updated for SourceHook v4.4, minor API changes, bug fixes, and a sync to the latest HL2SDK.&lt;br /&gt;
&lt;br /&gt;
====Version 1.4====&lt;br /&gt;
On April 5th, 2007, Metamod:Source was updated with API for [[Valve Server Plugin]] interface hooking and crash-safe user message enumeration. An experimental gameinfo.txt update tool was also added. No SourceHook changes were made in this release.&lt;br /&gt;
&lt;br /&gt;
====Version 1.6====&lt;br /&gt;
Currently in development, Metamod:Source received a near complete overhaul to abstract engine-specific code to support Orange Box.  Additionally, SourceHook received a massive overhaul and is now v5.0, adding global hooks and various major API simplifications.  It is the first backwards compatibility break since 1.1.&lt;br /&gt;
&lt;br /&gt;
==Design Considerations==&lt;br /&gt;
====Metamod====&lt;br /&gt;
Originally, Metamod:Source was a plugin co-existing with SourceMod.  However, there are factories, pointers, and certain capabilities not possible from a [[Valve Server Plugin]].  Furthermore, the [[Half-Life 2]] engine does not properly unload VSPs, making debugging and resource unloading more difficult.  Eventually it was decided the added functionality and fine-tuned control outweighed the extra cost of having to configure an intercepting binary.&lt;br /&gt;
&lt;br /&gt;
====Plugins====&lt;br /&gt;
Plugins are specific to Metamod:Source.  This means that [[Valve Server Plugin]]s and [[Open_Source_Plugins_for_Metamod:Source|Metamod:Source Plugins]] are entirely separate in the API characteristics.  While it is certainly possible to expose the necessary interfaces to VSPs, it creates an added layer of complexity for dealing with things that Metamod:Source might not directly control.  For example, when a Metamod:Source plugin is removed at runtime, all of the necessary hooks are also removed.  A VSP has no clear callback for detecting this event, therefore it would be more difficult to ensure proper unloading.  VSP and MM:S plugins also have different ways of attaching and detaching server [[Cvars|cvars]] and [[Console commands|concmds]].&lt;br /&gt;
&lt;br /&gt;
By keeping the plugin system isolated, Metamod:Source can also provide a unique set of console commands and API.  For example, plugins can listen for certain Metamod:Source-specific events and provide communication channels with other plugins.&lt;br /&gt;
&lt;br /&gt;
====Hooking====&lt;br /&gt;
Metamod:Source is powered by [[SourceHook]], a versatile library for hooking virtual functions.  The original [[Half-Life 1]] engine used structs of function pointers which could easily be modified as they passed from one library to another.  However, HL2 is comprised almost entirely of pure virtual interfaces.  SourceHook was designed for declaring single hooks against a given virtual function and a this pointer, which is not only faster than a blanket hooking system like Metamod's, but more flexible and precise.&lt;br /&gt;
&lt;br /&gt;
Hooking under Metamod:Source has a number of features that don't exist in a hooking system style like Metamod's, and it achieves something closer to [[Detours|detours]], rather than Metamod, which is hardcoded.  For example&lt;br /&gt;
*You can change parent parameters during a hooked call&lt;br /&gt;
*You can hook member functions, both by a pre-existing declaration or given vtable offset&lt;br /&gt;
*You can call the original function and still fire its associated hooks, or you can call it without firing hooks in order to prevent infinite recursion&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
For more information on installing, configuring, and coding for Metamod:Source, see [[:Category:Documentation (SourceMM)|Documentation]].&lt;br /&gt;
&lt;br /&gt;
==The Future==&lt;br /&gt;
While Metamod:Source is a stable/production product, more features are on the horizon.  There are distant plans for a [[Detours|detouring]] library and a library for efficiently automated [[Signature Scanning|signature scanning]].&lt;br /&gt;
&lt;br /&gt;
==License==&lt;br /&gt;
Metamod:Source is licensed under the [[zLib/libpng License]].  It is free to use for both open-source and proprietary projects.&lt;br /&gt;
&lt;br /&gt;
==External Links==&lt;br /&gt;
*[http://www.sourcemm.net/ Metamod:Source Website]&lt;br /&gt;
*[http://www.metamod.org/ Metamod Website]&lt;br /&gt;
*[http://www.sourcemod.net/ SourceMod Website]&lt;br /&gt;
*[http://resonus.net/doxygen_sourcemm/ Doxygen of Metamod:Source]&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=SourceMod&amp;diff=6904</id>
		<title>SourceMod</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=SourceMod&amp;diff=6904"/>
		<updated>2009-02-15T14:19:04Z</updated>

		<summary type="html">&lt;p&gt;Fyren: rv&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;:{{owned_project|project=SourceMod|website=www.sourcemod.net}}&lt;br /&gt;
=Introduction=&lt;br /&gt;
SourceMod is a [[SourceMM|Metamod:Source]] plugin for [[Half-Life 2]].  It provides comprehensive scripting for the Source engine and mods written using the Source SDK.  It has features for administration systems, commands, console variables, events, network messages, timed actions, math and string routines, entity modification, and more.  It also features a safely versioned, object oriented API usable from &amp;quot;extensions&amp;quot; written in C++.  The extension API can be used to add scripting language callbacks and native features.&lt;br /&gt;
&lt;br /&gt;
SourceMod scripts are written in the SourcePawn language, which is derived from [[Pawn]].  Some of the differences include:&lt;br /&gt;
*Passing functions as &amp;quot;objects,&amp;quot; instead of by name&lt;br /&gt;
*Natively packed and tagged strings&lt;br /&gt;
*Dynamic local variables&lt;br /&gt;
*A '&amp;lt;tt&amp;gt;decl&amp;lt;/tt&amp;gt;' operator for creating uninitialized variables&lt;br /&gt;
*A new virtual machine and JIT, both rewritten in C++&lt;br /&gt;
*A new file format&lt;br /&gt;
&lt;br /&gt;
=History=&lt;br /&gt;
==Initial Project==&lt;br /&gt;
SourceMod was officially announced on October 7th, 2004, as a successor to [[AMX Mod X]] for the Half-Life 1 engine.  It was targetted as a complete rewrite of AMX Mod X, with a fundamental changes:&lt;br /&gt;
*Use of multiple (pluggable) scripting languages&lt;br /&gt;
*JavaScript support&lt;br /&gt;
*Unloadability&lt;br /&gt;
*An object-oriented module API&lt;br /&gt;
&lt;br /&gt;
The Source SDK was released on December 1st, 2004.  A few weeks later, SourceMod released its source code on December 25th.  After this, development began to stagnate.  The concept of multiple languages was over-ambitious and improper.  The system was largely too complex and too unorganized for developers to understand.  Most importantly, the integral calling abstraction layer, designed to let Core talk to plugins without knowing the target scripting layer, was never viable.  Because of this and the inherent complexity of MetaEng, scripts were not testable.&lt;br /&gt;
&lt;br /&gt;
By May of 2005, SourceMod had become completely abandoned.  The codebase was scrapped for a rewrite, called &amp;quot;Core 2.&amp;quot;  This was also quickly abandoned.  This timeline and the details therein are explained on the SourceMod [http://www.sourcemod.net/devlog/?p=88 Dev Log].  The remaining members of the SourceMod team went back to AMX Mod X.&lt;br /&gt;
&lt;br /&gt;
==SourceHook==&lt;br /&gt;
By January of 2005, it was apparent that Valve's API would not be sufficient for plugin development in C++.  SourceMod and AMX Mod X Developer Pavol &amp;quot;PM OnoTo&amp;quot; Marko started working on an API for safely hooking virtual functions via vtables.  &lt;br /&gt;
&lt;br /&gt;
By March of 2005, it was apparent that this technology would be more useful as a separate project.  Thus, SourceHook broke from SourceMod and the [[SourceMM|Metamod:Source]] project was started.  Metamod:Source was first released on May 26, 2005.&lt;br /&gt;
&lt;br /&gt;
==Current Project==&lt;br /&gt;
In March of 2006, a public survey was held to determine if the community still wanted SourceMod.  Since the response was good, the project was restarted, but in secret, to avoid the same public relations mistakes.  From March to September, SourcePawn was written, which included:&lt;br /&gt;
*A new JIT, written completely in C++&lt;br /&gt;
*A new virtual machine and API, written in C++ with object oriented API&lt;br /&gt;
*A new file format&lt;br /&gt;
*Various new language features&lt;br /&gt;
&lt;br /&gt;
During November 2006 to January 2007, SourceMod evolved into a usable scripting platform based on SourcePawn.  As of March 16, 2007, it contained enough scripting-level features to be usable, and builds were made available to the public.&lt;br /&gt;
&lt;br /&gt;
SourceMod remains an ongoing development project which is still in its infancy.&lt;br /&gt;
&lt;br /&gt;
=Development Team=&lt;br /&gt;
*See the [http://www.sourcemod.net/credits.php credits page].&lt;br /&gt;
&lt;br /&gt;
=Future Plans=&lt;br /&gt;
SourceMod will be expanded to have a comprehensive administration plugin set, SQL capatibility, more utility functions, and more Half-Life 2 engine functions.&lt;br /&gt;
&lt;br /&gt;
=License=&lt;br /&gt;
SourceMod is licensed under the [[GNU General Public License]].  The JIT is licensed under its own freeware license.&lt;br /&gt;
&lt;br /&gt;
=External Links=&lt;br /&gt;
*[http://www.sourcemod.net/ SourceMod Website]&lt;br /&gt;
*[http://www.metamodsource.net/ Metamod:Source Website]&lt;br /&gt;
*[http://www.sourcebans.net/ SourceBans Plugin Website]&lt;br /&gt;
*[http://www.n00bsalad.net/sourcemodmirror/ N00bsalad.net Sourcemod Mirror Downloads]&lt;br /&gt;
&lt;br /&gt;
[[Category:Half-Life_2]]&lt;br /&gt;
[[Category:SourceMod]]&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Installing_SourceMod&amp;diff=6903</id>
		<title>Installing SourceMod</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Installing_SourceMod&amp;diff=6903"/>
		<updated>2009-02-15T14:16:09Z</updated>

		<summary type="html">&lt;p&gt;Fyren: rv&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Installing SourceMod is very simple, and it can be added with almost no configuration changes.&lt;br /&gt;
&lt;br /&gt;
=Prerequisites=&lt;br /&gt;
A GUI Web Browser to retrive Metamod and SourceMod compressed archives.&lt;br /&gt;
A tool to copy archive to your dedicated server host.&lt;br /&gt;
&lt;br /&gt;
SourceMod requires [[Metamod:Source]] 1.4.3 or higher. [http://www.metamodsource.net/ Click here] to visit the Metamod:Source homepage. Instructions to install SourceMM muanually can be found [http://wiki.alliedmods.net/index.php/Installing_Metamod:Source here].&lt;br /&gt;
&lt;br /&gt;
SourceMod will run on any mod built using the Source SDK.  It also supports &amp;quot;The Ship,&amp;quot; which uses the Source engine.&lt;br /&gt;
&lt;br /&gt;
=Uploading/Installing=&lt;br /&gt;
==Local Server==&lt;br /&gt;
To install SourceMod locally, simply extract the &amp;lt;tt&amp;gt;.zip&amp;lt;/tt&amp;gt; (Windows) or &amp;lt;tt&amp;gt;.tar.gz&amp;lt;/tt&amp;gt; (Linux) package to your mod folder (i.e. &amp;lt;tt&amp;gt;cstrike&amp;lt;/tt&amp;gt; for Counter-Strike, &amp;lt;tt&amp;gt;dod&amp;lt;/tt&amp;gt; for Day of Defeat, et cetera).&lt;br /&gt;
[http://www.sourcemod.net/downloads.php Download Here]&lt;br /&gt;
&lt;br /&gt;
==Remote Server==&lt;br /&gt;
To install SourceMod remotely, first extract the &amp;lt;tt&amp;gt;.zip&amp;lt;/tt&amp;gt; (Windows) or &amp;lt;tt&amp;gt;.tar.gz&amp;lt;/tt&amp;gt; (Linux) package to your local computer (for example, your Desktop).  You will see an &amp;lt;tt&amp;gt;addons&amp;lt;/tt&amp;gt; folder.  &lt;br /&gt;
&lt;br /&gt;
Using a tool such as [http://www.google.com/search?q=FTP FTP], locate your mod folder (i.e. &amp;lt;tt&amp;gt;cstrike&amp;lt;/tt&amp;gt; for Counter-Strike, &amp;lt;tt&amp;gt;dod&amp;lt;/tt&amp;gt; for Day of Defeat, et cetera).  Underneath this folder, you should have an &amp;lt;tt&amp;gt;addons&amp;lt;/tt&amp;gt; folder (if not, Metamod:Source is probably not installed).  From your local &amp;lt;tt&amp;gt;addons&amp;lt;/tt&amp;gt; folder, upload the entire contents to your remote &amp;lt;tt&amp;gt;addons&amp;lt;/tt&amp;gt; folder.  When done, your remote &amp;lt;tt&amp;gt;addons&amp;lt;/tt&amp;gt; folder should have a &amp;lt;tt&amp;gt;sourcemod&amp;lt;/tt&amp;gt; folder.&lt;br /&gt;
&lt;br /&gt;
If you have trouble with these steps, you need to get acquainted with FTP and server management.  However, you can also ask your server provider for help.  Some providers also have web interfaces for managing your server.&lt;br /&gt;
&lt;br /&gt;
Alternatively, if you copied the tar.gz to your srcds directory, execute the following from the cstrike sub directory:&lt;br /&gt;
tar -xzf ../sourcemod-1.1.0.tar.gz&lt;br /&gt;
&lt;br /&gt;
=Checking the Install=&lt;br /&gt;
Your folder layout should look like:&lt;br /&gt;
*&amp;lt;tt&amp;gt;[mod]&amp;lt;/tt&amp;gt; - Your mod's folder&lt;br /&gt;
**&amp;lt;tt&amp;gt;addons&amp;lt;/tt&amp;gt;&lt;br /&gt;
***&amp;lt;tt&amp;gt;metamod&amp;lt;/tt&amp;gt; - Metamod:Source&lt;br /&gt;
***&amp;lt;tt&amp;gt;sourcemod&amp;lt;/tt&amp;gt; - SourceMod&lt;br /&gt;
&lt;br /&gt;
Once SourceMod is uploaded/copied and configured with Metamod:Source, restart your server completely.  If it is local, shut it down and restart it.  If it is remote, you may need to ask your server provider for help.  However, it is often safe to issue a &amp;quot;quit&amp;quot; command via [[rcon]], and most providers will automatically restart your server.&lt;br /&gt;
&lt;br /&gt;
First, in your [[server console]] (not client console), type:&lt;br /&gt;
&amp;lt;pre&amp;gt;meta list&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the install worked, you will see something like:&lt;br /&gt;
&amp;lt;pre&amp;gt;] meta list&lt;br /&gt;
Listing 1 plugin:&lt;br /&gt;
    [01] SourceMod (1.1.0.2489) by AlliedModders LLC&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You should then be able to use the SourceMod root console command, which can be invoked with simply:&lt;br /&gt;
&amp;lt;pre&amp;gt;sm&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;] sm version&lt;br /&gt;
 SourceMod Version Information:&lt;br /&gt;
    SourceMod Version: 1.1.0.2489&lt;br /&gt;
    SourcePawn Engine: SourcePawn 1.1, jit-x86 (build 1.1.0-svn)&lt;br /&gt;
    SourcePawn API: v1 = 4, v2 = 2&lt;br /&gt;
    Compiled on: Sep  5 2008 02:02:12&lt;br /&gt;
    http://www.sourcemod.net/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lastly, assuming you have already setup your administration user, you can test the in game menu by joining the server, and in the client console type the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;sm_admin&amp;lt;/pre&amp;gt;&lt;br /&gt;
You should see a menu popup with all you options.&lt;br /&gt;
&lt;br /&gt;
=Troubleshooting=&lt;br /&gt;
If the install failed, you will generally see one of four symptoms.  &lt;br /&gt;
&lt;br /&gt;
==Metamod reports NOFILE or FAILED==&lt;br /&gt;
If &amp;quot;meta list&amp;quot; replies with something like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;] meta list&lt;br /&gt;
-Id- Name                  Version     Author           Status  &lt;br /&gt;
[01] -                     -           -                NOFILE  &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most likely, either the files are not located in the correct place, or the file could not be loaded.  For more information, use the following command (except use the correct list number):&lt;br /&gt;
&amp;lt;pre&amp;gt;meta list 1&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Metamod lists no plugins==&lt;br /&gt;
If &amp;quot;meta list&amp;quot; replies with something like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;] meta list&lt;br /&gt;
-Id- Name                  Version     Author           Status  &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You forgot to add SourceMod to the &amp;lt;tt&amp;gt;addons/metamod/metaplugins.ini&amp;lt;/tt&amp;gt; file.&lt;br /&gt;
Or if that doesn't fix your problem, make sure you are using the correct build of Sourcemod (zip = windows, tar = linux).&lt;br /&gt;
&lt;br /&gt;
==Metamod says nothing==&lt;br /&gt;
If &amp;quot;meta list&amp;quot; has no reply at all, Metamod:Source is not properly installed. [http://wiki.alliedmods.net/index.php/Installing_SourceMM This wiki page] may provide you with clues on how to solve this problem.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Documentation]]&lt;/div&gt;</summary>
		<author><name>Fyren</name></author>
		
	</entry>
</feed>