<?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=Nergal</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=Nergal"/>
	<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/Special:Contributions/Nergal"/>
	<updated>2026-06-07T01:42:04Z</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=11382</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=11382"/>
		<updated>2022-12-11T21:10:51Z</updated>

		<summary type="html">&lt;p&gt;Nergal: /* Reading/Checking Handles */&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 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>Nergal</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Natives_(SourceMod_Development)&amp;diff=11177</id>
		<title>Natives (SourceMod Development)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Natives_(SourceMod_Development)&amp;diff=11177"/>
		<updated>2021-03-10T15:54:49Z</updated>

		<summary type="html">&lt;p&gt;Nergal: Updating pawn examples to newer syntax&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Natives are functions which are available to plugins via Core itself, or a C++ extension.  They are called &amp;quot;natives&amp;quot; because they must be translated via a ''native interface''.  This article explains the various parameter passing conventions in SourcePawn, as well as how to use them in your own natives.&lt;br /&gt;
&lt;br /&gt;
To understand the contents of this article, you will need to read [[Writing_Extensions#Creating_Native_Functions|Creating Natives]], the Native section in the introductory article on creating extensions.&lt;br /&gt;
&lt;br /&gt;
In this article, &amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt; refers to the C/C++ data type, and &amp;lt;tt&amp;gt;Float&amp;lt;/tt&amp;gt; (note capital 'F') refers to the SourcePawn [[Tags (Scripting)|tag]].&lt;br /&gt;
&lt;br /&gt;
=By Value versus By Reference=&lt;br /&gt;
There are two ways to pass integers/Floats to native implementations.  They are ''by value'' (ByVal) and ''by reference'' (ByRef).  ByVal means that a copy of the value is passed to the native.  This is the default behaviour.  ByRef means a ''reference'' is passed to the native, and this reference points to the value.  Both will be explained below.&lt;br /&gt;
&lt;br /&gt;
Note that arrays and strings, as will be explained later, are always passed by reference.  This is because they are usually larger structures, and passing them ByVal would require copying their data, wasting CPU cycles.&lt;br /&gt;
&lt;br /&gt;
==By Value==&lt;br /&gt;
Passing by value is the default behaviour for primitive data types (integers, Floats, or any tag that's cell-based).  Data is treated normally as raw, copied input.  Observe the following native:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Returns the number decremented by one.&lt;br /&gt;
 *&lt;br /&gt;
 * @param num		Number to decrement.&lt;br /&gt;
 * @return		Decremented number.&lt;br /&gt;
 */&lt;br /&gt;
native int Decrement(int num);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
How would we use this native?  Since &amp;lt;tt&amp;gt;num&amp;lt;/tt&amp;gt; is passed as a value, it cannot change in the native code.  This means we have to use the return value as such:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//Decrements a number 5 times&lt;br /&gt;
int Example(int num)&lt;br /&gt;
{&lt;br /&gt;
	num = Decrement(num);&lt;br /&gt;
	num = Decrement(num);&lt;br /&gt;
	num = Decrement(num);&lt;br /&gt;
	num = Decrement(num);&lt;br /&gt;
	num = Decrement(num);&lt;br /&gt;
	return num;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==By Reference==&lt;br /&gt;
Let's reuse the above example to use reference passing.  Observe the new native below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Subtracts one from the given number, by reference.&lt;br /&gt;
 *&lt;br /&gt;
 * @param num		Number to subtract, by reference.&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native int Decrement(int&amp;amp; num);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the ampersand ('&amp;amp;') before the parameter name -- this specifies that it is passed by reference.  Now, let's see how this would look in our script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
int Example(int num)&lt;br /&gt;
{&lt;br /&gt;
	Decrement(num);&lt;br /&gt;
	Decrement(num);&lt;br /&gt;
	Decrement(num);&lt;br /&gt;
	Decrement(num);&lt;br /&gt;
	Decrement(num);&lt;br /&gt;
	return num;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, &amp;lt;tt&amp;gt;Decrement&amp;lt;/tt&amp;gt; is acting on the &amp;lt;tt&amp;gt;num&amp;lt;/tt&amp;gt; variable ''itself'', not a copy of it.  Thus, num will decrease 5 times.  In fact, scripts can even do this internally.  We can shorten the example even more:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;int Example(int&amp;amp; num)&lt;br /&gt;
{&lt;br /&gt;
	Decrement(num);&lt;br /&gt;
	Decrement(num);&lt;br /&gt;
	Decrement(num);&lt;br /&gt;
	Decrement(num);&lt;br /&gt;
	Decrement(num);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==When to use By Ref==&lt;br /&gt;
There is a misconception that passing by reference is always better than by value.  After all, copying data sounds excessive.  However, by value in SourcePawn only works on 32bit values, and thus copying the value is inherent to the processor, and trivial.&lt;br /&gt;
&lt;br /&gt;
On the other hand, passing by reference is slightly more expensive.  First, the compiler has to generate a little extra code to compute the local address of the variable.  Second, the native code itself has to translate the local address to a ''real virtual address'' (native memory).&lt;br /&gt;
&lt;br /&gt;
It is a good idea to only use by reference when you need it.  A common usage is when you need to return more than one piece of data, and you can't fit it into the return value of your native or function.  In this case, by reference is ideal.&lt;br /&gt;
&lt;br /&gt;
=Integers/Floats=&lt;br /&gt;
&lt;br /&gt;
==By Value==&lt;br /&gt;
Natives based purely on by-value floating point or integer input are generally the easiest to make.  Let's take a simple function which takes in a Float and an integer, and returns a Float:&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Raises a number to an integer power.&lt;br /&gt;
 *&lt;br /&gt;
 * @param fNum		Base number (Float).&lt;br /&gt;
 * @param exp		Exponent (integer).&lt;br /&gt;
 * @return		Computed exponent result as a Float.&lt;br /&gt;
 */&lt;br /&gt;
native float FloatIntPower(float fNum, int exp);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An implementation of this native might look like:&lt;br /&gt;
&amp;lt;cpp&amp;gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
static cell_t sm_FloatIntPower(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	float f1 = sp_ctof(params[1]);&lt;br /&gt;
	int num = params[2];&lt;br /&gt;
	&lt;br /&gt;
	float result = (float)pow(f1, (double)f2);&lt;br /&gt;
	return sp_ftoc(result);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Integers, as we saw in the introduction, are accessed from the parameter stack normally.  Floats, however, must be ''reinterpret casted'' from a &amp;lt;tt&amp;gt;cell_t&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt;.  Two inline functions are provided for this:&lt;br /&gt;
*&amp;lt;tt&amp;gt;sp_ctof&amp;lt;/tt&amp;gt;: Convert a &amp;lt;tt&amp;gt;cell_t&amp;lt;/tt&amp;gt; to a &amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;sp_ftoc&amp;lt;/tt&amp;gt;: Convert a &amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt; to a &amp;lt;tt&amp;gt;cell_t&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==By Reference==&lt;br /&gt;
By reference is a little more tricky.  Let's first implement our &amp;lt;tt&amp;gt;Decrement&amp;lt;/tt&amp;gt; native from earlier.  A refresher:&lt;br /&gt;
&amp;lt;pawn&amp;gt;native void Decrement(int&amp;amp; num);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we try to use our above code, &amp;lt;tt&amp;gt;params[1]&amp;lt;/tt&amp;gt; will no longer hold a value.  Instead, it holds a ''local address'' in the plugin.  We must use the &amp;lt;tt&amp;gt;LocalToPhysAddr&amp;lt;/tt&amp;gt; function to translate this.  It takes in a local address and returns back a physical pointer, which we can then modify.  This will modify the value in the script.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;static cell_t sm_Decrement(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	cell_t *addr;&lt;br /&gt;
&lt;br /&gt;
	/* Translate the address. */&lt;br /&gt;
	pContext-&amp;gt;LocalToPhysAddr(params[1], &amp;amp;addr);&lt;br /&gt;
&lt;br /&gt;
	/* Decrement the number */&lt;br /&gt;
	*addr -= 1;&lt;br /&gt;
&lt;br /&gt;
	/* We have to return something, even if the plugin doesn't use the value */&lt;br /&gt;
	return 1;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
''Note: LocalToPhysAddr can return an error code.  For all practical purposes, this will never error, unless there is some memory or corruption issue, so checking it isn't necessary.''&lt;br /&gt;
&lt;br /&gt;
This works the same way for floats.  Let's say we change our native to this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Decrements a Float by an integer, and stores the result by reference.&lt;br /&gt;
 *&lt;br /&gt;
 * @param fNum		Float number to decrement (by ref).&lt;br /&gt;
 * @param decamt	Amount to decrement by.&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native void Decrement(float&amp;amp; fNum, int decamt);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example is fairly contrived -- our native simply performs a subtract operation.  But let's look at the implementation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;static cell_t sm_Decrement(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	cell_t *addr;&lt;br /&gt;
&lt;br /&gt;
	/* Translate the address. */&lt;br /&gt;
	pContext-&amp;gt;LocalToPhysAddr(params[1], &amp;amp;addr);&lt;br /&gt;
&lt;br /&gt;
	/* Get the value */&lt;br /&gt;
	float val = sp_ctof(*addr);&lt;br /&gt;
	/* Decrement */&lt;br /&gt;
	val -= params[2];&lt;br /&gt;
	/* Store back */&lt;br /&gt;
	*addr = sp_ftoc(val);&lt;br /&gt;
&lt;br /&gt;
	/* We have to return something, even if the plugin doesn't use the value */&lt;br /&gt;
	return 1;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that even though the first parameter was passed by reference, the second was not, and is accessed normally.&lt;br /&gt;
&lt;br /&gt;
=Arrays=&lt;br /&gt;
&lt;br /&gt;
==Basic Arrays==&lt;br /&gt;
Arrays are always passed by reference.  The first example is an array which contains a list of numbers to sum.  Observe the native:&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Averages an array of numbers.&lt;br /&gt;
 *&lt;br /&gt;
 * @param array		Array of numbers to average.&lt;br /&gt;
 * @param num		Number of slots in the array.&lt;br /&gt;
 * @return		Average number as a Float.&lt;br /&gt;
 */&lt;br /&gt;
native float Average(int[] array, int num);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usage might look like:&lt;br /&gt;
&amp;lt;pawn&amp;gt;float Example()&lt;br /&gt;
{&lt;br /&gt;
	int numbers[5] = {5, 6, 1, 3, 8};&lt;br /&gt;
	return Average(numbers, 5);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The implementation, like the by ref examples above, requires &amp;lt;tt&amp;gt;LocalToPhysAddr&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;cpp&amp;gt;static cell_t sm_Average(IPluginContext *pContext, cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	cell_t *array;&lt;br /&gt;
	float sum = 0.0f, average;&lt;br /&gt;
&lt;br /&gt;
	if (params[2] &amp;lt; 1)&lt;br /&gt;
	{&lt;br /&gt;
		/* 0 works without sp_ftoc() */&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	pContext-&amp;gt;LocalToPhysAddr(params[1], &amp;amp;array);&lt;br /&gt;
	for (cell_t i=0; i&amp;lt;params[2]; i++)&lt;br /&gt;
	{&lt;br /&gt;
		sum += array[i];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	average = sum / params[2];&lt;br /&gt;
&lt;br /&gt;
	return sp_ftoc(average);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Float Arrays==&lt;br /&gt;
This works similarly for Float arrays.  Let's take Vectors an example, with the following native:&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Adds two vectors together.&lt;br /&gt;
 *&lt;br /&gt;
 * @param r	Array to store the result in.&lt;br /&gt;
 * @param v1	First vector to add.&lt;br /&gt;
 * @param v2	Second vector to add.&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native void AddVectors(float r[3], const float v1[3], const float v2[3]);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The implementation is straightforward:&lt;br /&gt;
&amp;lt;cpp&amp;gt;static cell_t sm_AddVectors(IPluginContext *pContext, cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	cell_t *v1, *v2;&lt;br /&gt;
	float result[3];&lt;br /&gt;
	&lt;br /&gt;
	pContext-&amp;gt;LocalToPhysAddr(params[2], &amp;amp;v1);&lt;br /&gt;
	pContext-&amp;gt;LocalToPhysAddr(params[3], &amp;amp;v2);&lt;br /&gt;
&lt;br /&gt;
	result[0] = sp_ctof(v1[0]) + sp_ctof(v2[0]);&lt;br /&gt;
	result[1] = sp_ctof(v1[1]) + sp_ctof(v2[1]);&lt;br /&gt;
	result[2] = sp_ctof(v1[2]) + sp_ctof(v2[2]);&lt;br /&gt;
&lt;br /&gt;
	cell_t *r;&lt;br /&gt;
	pContext-&amp;gt;LocalToPhysAddr(params[1], &amp;amp;r);&lt;br /&gt;
	r[0] = sp_ftoc(result[0]);&lt;br /&gt;
	r[1] = sp_ftoc(result[1]);&lt;br /&gt;
	r[2] = sp_ftoc(result[2]);&lt;br /&gt;
	&lt;br /&gt;
	return 1;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that we only store the result after we have computed the input, rather than store directly.  This is a bit more work, but is good practice in case users re-use data inputs, and risk overwriting inputs as they are written.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;float origin[3];&lt;br /&gt;
AddVectors(origin, origin, origin);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Strings=&lt;br /&gt;
Strings are just like arrays, in that they are passed by reference.  The only difference is that each character is stored in a byte, not a 32bit &amp;lt;tt&amp;gt;cell_t&amp;lt;/tt&amp;gt;.  However, to make coding a bit easier for you, the coder, there are separate functions.&lt;br /&gt;
*&amp;lt;tt&amp;gt;LocalToString&amp;lt;/tt&amp;gt;: Converts a local address to a physical string address.&lt;br /&gt;
*&amp;lt;tt&amp;gt;StringToLocal&amp;lt;/tt&amp;gt;: Copies a physical string into a local address buffer.&lt;br /&gt;
*&amp;lt;tt&amp;gt;StringToLocalUTF8&amp;lt;/tt&amp;gt;: Same as &amp;lt;tt&amp;gt;StringToLocal&amp;lt;/tt&amp;gt;, but only copies the maximum amount possible without cutting off any multi byte characters.&lt;br /&gt;
&lt;br /&gt;
First, let's take an easy example: the infamous strlen.&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Returns the length of a string.&lt;br /&gt;
 * &lt;br /&gt;
 * @param string	String to calculate.&lt;br /&gt;
 * @return		Number of bytes in the string.&lt;br /&gt;
 */&lt;br /&gt;
native int strlen(const char[] string);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Implementation:&lt;br /&gt;
&amp;lt;cpp&amp;gt;static cell_t sm_StrLen(IPluginContext *pContext, cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	char *str;&lt;br /&gt;
	pContext-&amp;gt;LocalToString(params[1], &amp;amp;str);&lt;br /&gt;
	return strlen(str);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, let's say we want to modify the string.  There is an important note here: since the string is passed by reference, when you modify the string, it is also modified in the plugin.  This is a huge difference from AMX Mod X, where strings were essentially by value in most cases, and you had to copy results back.&lt;br /&gt;
&lt;br /&gt;
Thus, if we wanted to copy a new result into &amp;lt;tt&amp;gt;str&amp;lt;/tt&amp;gt; in the above implementation, it would be very easy.  If we were implementing &amp;lt;tt&amp;gt;strcpy()&amp;lt;/tt&amp;gt;, we would have to use &amp;lt;tt&amp;gt;memmove()&amp;lt;/tt&amp;gt; to make sure there are no overlaps.  Let's do this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Copies one string onto another.&lt;br /&gt;
 *&lt;br /&gt;
 * @param dest		Destination buffer to copy to.&lt;br /&gt;
 * @param length	Maximum length of the buffer.&lt;br /&gt;
 * @param source	Source to copy from.&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native void StringCopy(char[] dest, int length, const char[] source);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Implementation using &amp;lt;tt&amp;gt;memmove&amp;lt;/tt&amp;gt; for safety:&lt;br /&gt;
&amp;lt;cpp&amp;gt;static cell_t sm_StringCopy(IPluginContext *pContext, cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	char *dest, *src;&lt;br /&gt;
	size_t len;&lt;br /&gt;
&lt;br /&gt;
	pContext-&amp;gt;LocalToString(params[1], &amp;amp;dest);&lt;br /&gt;
	pContext-&amp;gt;LocalToString(params[3], &amp;amp;src);&lt;br /&gt;
	&lt;br /&gt;
	/* Perform bounds checking */&lt;br /&gt;
	len = strlen(src);&lt;br /&gt;
	if (len &amp;gt;= params[2])&lt;br /&gt;
	{&lt;br /&gt;
		len = params[2] - 1;&lt;br /&gt;
	} else {&lt;br /&gt;
		len = params[2];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Copy */&lt;br /&gt;
	memmove(dest, src, len);&lt;br /&gt;
&lt;br /&gt;
	dest[len] = '\0';&lt;br /&gt;
&lt;br /&gt;
	return 1;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can also use &amp;lt;tt&amp;gt;StringToLocal&amp;lt;/tt&amp;gt;, which would requires a temporary buffer for the original string:&lt;br /&gt;
&amp;lt;cpp&amp;gt;static cell_t sm_StringCopy(IPluginContext *pContext, cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	char *src;&lt;br /&gt;
	char buffer[2048];&lt;br /&gt;
	size_t len;&lt;br /&gt;
 &lt;br /&gt;
	pContext-&amp;gt;LocalToString(params[3], &amp;amp;src);&lt;br /&gt;
 &lt;br /&gt;
	snprintf(buffer, sizeof(buffer), &amp;quot;%s&amp;quot;, src);&lt;br /&gt;
	pContext-&amp;gt;StringToLocal(params[1], params[2], buffer);&lt;br /&gt;
 &lt;br /&gt;
	return 1;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Generally, you will be using &amp;lt;tt&amp;gt;StringToLocal&amp;lt;/tt&amp;gt; for setting strings from outside sources, because it calculates addresses and overflows for you.  However, you must make sure that you are not overwriting memory as you are reading it, or else programmers who are using certain types of array slicing may find themselves getting unexpected results.&lt;br /&gt;
&lt;br /&gt;
=Advanced=&lt;br /&gt;
==Default Arguments==&lt;br /&gt;
Any type of parameter can have a default argument.  For example, here is a native where every argument has a default parameter:&lt;br /&gt;
&amp;lt;pawn&amp;gt;native void RandomStuff(int a=0, float b=1.0, int&amp;amp; c=0, const char[] d=&amp;quot;&amp;quot;, int e[3] = {0,1,2});&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that even by-reference parameters can have default arguments, as shown above.  This does not change the code; it just means the address will contain the default value.  &lt;br /&gt;
&lt;br /&gt;
Scripts can force default values.  Example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;native void RandomStuff(int a, int b, int c=0, int d=0);&lt;br /&gt;
&lt;br /&gt;
void Example()&lt;br /&gt;
{&lt;br /&gt;
	RandomStuff(1, 2, _, d);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The underscore ('_') means &amp;quot;use the default value for this argument.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Variable Arguments==&lt;br /&gt;
Variable arguments means any number of arguments can be passed.  An example of this looks like:&lt;br /&gt;
&amp;lt;pawn&amp;gt;native FormatText(const char[] format, any ...);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;...&amp;lt;/tt&amp;gt; characters mean any number of parameters can follow.&lt;br /&gt;
&lt;br /&gt;
'''There is one important note about variable arguments.  They are always passed by reference.'''  This means if you have a function which supports variable arguments, and an integer is passed, you will need to use &amp;lt;tt&amp;gt;LocalToPhysAddr&amp;lt;/tt&amp;gt; as required with by reference parameters.  &lt;br /&gt;
&lt;br /&gt;
==Argument Counts/Backwards Compatibility==&lt;br /&gt;
In native handlers, the &amp;lt;tt&amp;gt;params&amp;lt;/tt&amp;gt; array has a 0th index which stores the number of parameters it contains.  This is useful for both Default Arguments and Variable Arguments.  &lt;br /&gt;
&lt;br /&gt;
For example, consider the following native:&lt;br /&gt;
&amp;lt;pawn&amp;gt;native void DoSomething(int index);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Let's say that this native exists in plugins for six months.  After that, you decide to add a new parameter.  You want two conditions to be true after you release this update:&lt;br /&gt;
*Old plugins in binary form should still work on newer installations.&lt;br /&gt;
*Old plugins should still compile fine on the new API.&lt;br /&gt;
&lt;br /&gt;
The second condition is solved by using default arguments.  You should choose a value that will mimic the old functionality of the native.&lt;br /&gt;
&amp;lt;pawn&amp;gt;native void DoSomething(int index, int newparam = 0);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, when changing the implementation, you should detect whether &amp;lt;tt&amp;gt;params[0]&amp;lt;/tt&amp;gt; contains ''one parameter'' or ''two parameters''.  If it only contains one, you know to use the old version.  If it contains two, you know to use the later version and accept the second parameter.&lt;br /&gt;
&lt;br /&gt;
Similarly, you can use the &amp;lt;tt&amp;gt;params[0]&amp;lt;/tt&amp;gt; count to detect how many arguments were passed to a variable argument native.  This is used primarily in [[Format Class Functions (SourceMod Scripting)|Format Class Functions]] for parameter-count validation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Throwing Errors/Invoking the Debugger=&lt;br /&gt;
Often, you will write a native and realize that you need to tell the plugin that a serious error has occurred.  A good example of this is if you are writing a function which requires a player index, but that index is beyond the reasonable bounds for the maximum players in the server.&lt;br /&gt;
&lt;br /&gt;
In this case, it is a good idea to throw a ''runtime error''.  This is an error that halts the plugin and invokes a call trace from the debugger.  The halt is not permanent, but it does break the execution flow of the current callback.&lt;br /&gt;
&lt;br /&gt;
There are two ways to throw a native error: &amp;lt;tt&amp;gt;ThrowNativeErrorEx()&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;ThrowNativeError()&amp;lt;/tt&amp;gt;.  The former lets you specify a detailed error code from &amp;lt;tt&amp;gt;sp_vm_types.h&amp;lt;/tt&amp;gt;.  The latter is a helper function for generic errors, and it returns 0, allowing you to return with the function itself.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;static cell_t GetPlayerFrags(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	if (params[1] &amp;lt; 0 || params[1] &amp;gt; maxplayers)&lt;br /&gt;
	{&lt;br /&gt;
		return pContext-&amp;gt;ThrowNativeError(&amp;quot;Invalid client index: %d&amp;quot;, params[1]);&lt;br /&gt;
	}&lt;br /&gt;
	/* ... rest of code ... */&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Don't worry about including extra information, such as your native name or the module name.  The debugger knows all of this information and will decide what to print to the user.&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Development]]&lt;/div&gt;</summary>
		<author><name>Nergal</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Introduction_to_SourcePawn_1.7&amp;diff=9835</id>
		<title>Introduction to SourcePawn 1.7</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Introduction_to_SourcePawn_1.7&amp;diff=9835"/>
		<updated>2015-03-09T13:19:55Z</updated>

		<summary type="html">&lt;p&gt;Nergal: /* Expressions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide is designed to give you a very basic overview to fundamentals of scripting in SourcePawn. [[Pawn]] is a &amp;quot;scripting&amp;quot; language used to embed functionality in other programs. That means it is not a standalone language, like C++ or Java, and its details will differ based on the application. SourcePawn is the version of Pawn used in [[SourceMod]].&lt;br /&gt;
&lt;br /&gt;
This guide does not tell you how to write SourceMod plugins; it is intended as an overview of the syntax and semantics of the language instead. Read the separate article, [[Introduction to SourceMod Plugins]] for SourceMod API specifics. &lt;br /&gt;
&lt;br /&gt;
=Non-Programmer Intro=&lt;br /&gt;
This section is intended for non-programmers. If you're still confused, you may want to pick up a book on another language, such as PHP, Python, or Java, to get a better idea of what programming is like.&lt;br /&gt;
&lt;br /&gt;
==Symbols/Keywords==&lt;br /&gt;
A symbol is a series of letters, numbers, and/or underscores, that uniquely represents something. Symbols are case-sensitive, and usually start with a letter.&lt;br /&gt;
&lt;br /&gt;
There are a few reserved symbols that have special meaning. For example, &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;return&amp;lt;/tt&amp;gt; are special constructs in the language that will explained later. They cannot be used as symbol names.&lt;br /&gt;
&lt;br /&gt;
==Variables==&lt;br /&gt;
There a few important constructs you should know before you begin to script. The first is a '''variable'''. A variable is a symbol, or name, that holds data. For example, the variable &amp;quot;a&amp;quot; could hold the number &amp;quot;2&amp;quot;, &amp;quot;16&amp;quot;, &amp;quot;0&amp;quot;, et cetera. Since a variable holds data, it also allocates the memory needed to store that data.&lt;br /&gt;
&lt;br /&gt;
In addition to a name, variables have a '''type'''. A type tells the program how to interpret the data, and how much memory the data will use. Pawn has three types of data that are most commonly used:&lt;br /&gt;
* Integers, using the &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt; type. Integer types may store a whole number from -2147483648 to 2147483647.&lt;br /&gt;
* Floats, using the &amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt; type. Float types may store fractional numbers in a huge range, though they are not as precise as integers.&lt;br /&gt;
* Characters, using the &amp;lt;tt&amp;gt;char&amp;lt;/tt&amp;gt; type. Character types store one byte of character information, typically an [http://www.asciitable.com/ ASCII] character.&lt;br /&gt;
* Booleans, using the &amp;lt;tt&amp;gt;bool&amp;lt;/tt&amp;gt; type. Booleans store either true or false.&lt;br /&gt;
&lt;br /&gt;
Example of creating variables and assigning values:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;int money = 5400;&lt;br /&gt;
float percent = 67.3;&lt;br /&gt;
bool enabled = false;&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Functions==&lt;br /&gt;
The next important concept is '''functions'''. Functions are symbols or names that perform an action. When you invoke, or call them, they carry out a specific sequence of code and then return a result. There are a few types of functions, but every function is activated the same way. Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
show(56);     // Calls the &amp;quot;show&amp;quot; function, and gives it the number 56.&lt;br /&gt;
enable();     // Calls the &amp;quot;s &amp;quot;enable&amp;quot; function with no values.&lt;br /&gt;
bool visible = show(a);    //Calls the &amp;quot;show&amp;quot; function, stores its result in a variable.&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Every piece of data passed to a function is called a '''parameter'''. A function can have any number of parameters (there is a &amp;quot;reasonable&amp;quot; limit of 32 in SourceMod). Parameters will be explained further in the article.&lt;br /&gt;
&lt;br /&gt;
==Comments==&lt;br /&gt;
Note any text that appears after a &amp;quot;//&amp;quot; is considered a &amp;quot;comment&amp;quot; and is not actual code. There are two comment styles:&lt;br /&gt;
*&amp;lt;tt&amp;gt;//&amp;lt;/tt&amp;gt; - Double slash, everything following on that line is ignored.&lt;br /&gt;
*&amp;lt;tt&amp;gt;/* */&amp;lt;/tt&amp;gt; - Multi-line comment, everything in between the asterisks is ignored. You cannot nest these.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Block Coding==&lt;br /&gt;
The next concept is block coding. You can group code into &amp;quot;blocks&amp;quot; separated by { and }. This effectively makes one large block of code act as one statement. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;{&lt;br /&gt;
   here;&lt;br /&gt;
   is;&lt;br /&gt;
   some;&lt;br /&gt;
   code;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Block coding using braces is used everywhere in programming. Blocks of code can be nested within each other. It is a good idea to adapt a consistent and readable indentation style early on to prevent spaghetti-looking code.&lt;br /&gt;
&lt;br /&gt;
=Language Paradigms=&lt;br /&gt;
Pawn may seem similar to other languages, like C, but it has fundamental differences. It is not important that you immediately understand these differences, but they may be helpful if you're familiar with another language already.&lt;br /&gt;
*'''Pawn is sort of typed.''' Before SourceMod 1.7, Pawn did not have types. Older code and older natives will reflect this by using tags and the &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt; keyword. As of SourceMod 1.7, we recommend that all code use types. For more information see [[SourcePawn Transitional Syntax]].&lt;br /&gt;
*'''Pawn is not garbage collected.''' Pawn, as a language, has no built-in memory allocation, and thus has no garbage. If a function allocates memory, you may be responsible for freeing it.&lt;br /&gt;
*'''Pawn is not object oriented.''' Pawn does not have structs or objects. As of SourceMod 1.7, it has limited sugaring for treating some data types as objects, but users cannot create their own objects or classes.&lt;br /&gt;
*'''Pawn is single-threaded.''' As of this writing, Pawn is not thread safe. &lt;br /&gt;
*'''Pawn is compiled.''' Pawn is compiled to an intermediate, machine-independent code, which is stored in a &amp;quot;.smx&amp;quot; file. When loading .smx files, SourceMod translates this code to machine code for the platform and CPU it's running on.&lt;br /&gt;
&lt;br /&gt;
Early language design decisions were made by ITB CompuPhase. It is designed for low-level embedded devices and is thus very small and very fast.&lt;br /&gt;
&lt;br /&gt;
=Variables=&lt;br /&gt;
Pawn currently supports the following basic variable types:&lt;br /&gt;
*&amp;lt;tt&amp;gt;bool&amp;lt;/tt&amp;gt; - true or false.&lt;br /&gt;
*&amp;lt;tt&amp;gt;char&amp;lt;/tt&amp;gt; - an 8-bit ASCII character.&lt;br /&gt;
*&amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt; - a 32-bit signed integer.&lt;br /&gt;
*&amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt; - a 32-bit IEEE-754 floating point number.&lt;br /&gt;
*&amp;lt;tt&amp;gt;Handle&amp;lt;/tt&amp;gt; - the base type of a SourceMod object&lt;br /&gt;
&lt;br /&gt;
Other types may exist when defined in include files - for example, enums create new types for named integers, and many types derive from &amp;lt;tt&amp;gt;Handle&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Strings, currently, are 0-terminated arrays of &amp;lt;tt&amp;gt;char&amp;lt;/tt&amp;gt;s. They're described a little further ahead.&lt;br /&gt;
&lt;br /&gt;
==Declaration==&lt;br /&gt;
Below we include some examples of variable declarations, both valid and invalid. Keep in mind that SourcePawn has recently added new syntax, and that's what's documented below. Older code may use older declaration syntax, which is no longer supported.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
int a = 5;&lt;br /&gt;
float b = 5.0;&lt;br /&gt;
bool c = true;&lt;br /&gt;
bool d = false;&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Invalid variable usage:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
int a = 5.0;         // Type mismatch. 5.0 is a float.&lt;br /&gt;
float b = 5;         // Type mismatch. 5 is an integer.&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If a variable is not assigned upon declaration, it will be set to 0. For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
int a;        // Set to 0&lt;br /&gt;
float b;      // Set to 0.0&lt;br /&gt;
bool c;       // Set to false&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Assignment==&lt;br /&gt;
Variables can be re-assigned data after they are created. For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;int a;&lt;br /&gt;
float b;&lt;br /&gt;
bool c;&lt;br /&gt;
&lt;br /&gt;
a = 5;&lt;br /&gt;
b = 5.0;&lt;br /&gt;
c = true;&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Arrays=&lt;br /&gt;
An array is a sequence of data in a list. Arrays are useful for storing multiple pieces of data in one variable, or mapping one type of data to another.&lt;br /&gt;
&lt;br /&gt;
==Declaration==&lt;br /&gt;
An array is declared using brackets. Some examples of arrays:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
int players[32];     // Stores 32 integers.&lt;br /&gt;
float origin[3];     // Stores 3 floating point numbers&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default, arrays are initialized to 0. You can assign them different default values, however:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
int numbers[5] = {1, 2, 3, 4, 5};       // Stores 1, 2, 3, 4, 5.&lt;br /&gt;
float origin[3] = {1.0, 2.0, 3.0};      // Stores 1.0, 2.0, 3.0.&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can leave out the array size if you're going to pre-assign data to it. For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
int numbers[] = {1, 3, 5, 7, 9};&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The compiler will automatically deduce that you intended an array of size 5.&lt;br /&gt;
&lt;br /&gt;
When array is declared with brackets after its name, Pawn considers that array to have a '''fixed size'''. The size of a fixed-size array is always known. Some arrays can be '''dynamically sized''', by putting the brackets before the name. For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
int[] numbers = new int[MaxClients]&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This creates an array of size &amp;lt;tt&amp;gt;MaxClients&amp;lt;/tt&amp;gt;, which could be anything, so the size of the array is not known until the array is allocated.&lt;br /&gt;
&lt;br /&gt;
==Usage==&lt;br /&gt;
Using an array is just like using a normal variable. The only difference is the array must be '''indexed'''. Indexing an array means choosing the element which you wish to use.&lt;br /&gt;
&lt;br /&gt;
For example, here is an example of the above code using indexes:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
int numbers[5];&lt;br /&gt;
float origin[3];&lt;br /&gt;
&lt;br /&gt;
numbers[0] = 1;&lt;br /&gt;
numbers[1] = 2;&lt;br /&gt;
numbers[2] = 3;&lt;br /&gt;
numbers[3] = 4;&lt;br /&gt;
numbers[4] = 5;&lt;br /&gt;
origin[0] = 1.0;&lt;br /&gt;
origin[1] = 2.0;&lt;br /&gt;
origin[2] = 3.0;&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the '''index''' is what's in between the brackets. The index always starts from 0. That is, if an array has N elements, its valid indexes are from 0 to N-1. Accessing the data at these indexes works like a normal variable.&lt;br /&gt;
&lt;br /&gt;
Using an incorrect index will cause an error. For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
int numbers[5];&lt;br /&gt;
&lt;br /&gt;
numbers[5] = 20;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This may look correct, but 5 is not a valid index. The highest valid index is 4.&lt;br /&gt;
&lt;br /&gt;
You can use any expression as an index. For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;int a, numbers[5];&lt;br /&gt;
&lt;br /&gt;
a = 1;                   // Set a = 1&lt;br /&gt;
numbers[a] = 4;          // Set numbers[1] = 4&lt;br /&gt;
numbers[numbers[a]] = 2; // Set numbers[4] = 2&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Expressions will be discussed in depth later in the article.&lt;br /&gt;
&lt;br /&gt;
=Strings=&lt;br /&gt;
Strings are a construct for storing text (or even raw binary data). A string is just an array of characters, except that the final character must be 0 (called the null terminator). Without a null terminator, Pawn would not know where to stop reading the string. All strings are [http://en.wikipedia.org/wiki/UTF-8 UTF-8] in SourcePawn.&lt;br /&gt;
&lt;br /&gt;
In general, you must have an idea of how large a string will be before you store it. SourcePawn does not yet have the capability of pre-determining storage space for strings.&lt;br /&gt;
&lt;br /&gt;
==Usage==&lt;br /&gt;
Strings are usually declared as arrays. For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
char message[] = &amp;quot;Hello!&amp;quot;;&lt;br /&gt;
char clams[6] = &amp;quot;Clams&amp;quot;;&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These are equivalent to doing:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
char message[7];&lt;br /&gt;
char clams[6];&lt;br /&gt;
&lt;br /&gt;
message[0] = 'H';&lt;br /&gt;
message[1] = 'e';&lt;br /&gt;
message[2] = 'l';&lt;br /&gt;
message[3] = 'l';&lt;br /&gt;
message[4] = 'o';&lt;br /&gt;
message[5] = '!';&lt;br /&gt;
message[6] = 0;&lt;br /&gt;
clams[0] = 'C';&lt;br /&gt;
clams[1] = 'l';&lt;br /&gt;
clams[2] = 'a';&lt;br /&gt;
clams[3] = 'm';&lt;br /&gt;
clams[4] = 's';&lt;br /&gt;
clams[5] = 0;&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Although strings are rarely initialized in this manner, it is very important to remember the concept of the null terminator, which signals the end of a string. The compiler, and most SourceMod functions will automatically null-terminate for you, so it is mainly important when manipulating strings directly.&lt;br /&gt;
&lt;br /&gt;
Note that a string is enclosed in double-quotes, but a character is enclosed in single quotes.&lt;br /&gt;
&lt;br /&gt;
==Characters==&lt;br /&gt;
A character of text can be used in either a String or a cell. For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;char text[] = &amp;quot;Crab&amp;quot;;&lt;br /&gt;
char clam'&lt;br /&gt;
&lt;br /&gt;
clam = 'D';         //Set clam to 'D'&lt;br /&gt;
text[0] = 'A';      //Change the 'C' to 'A', it is now 'Arab'&lt;br /&gt;
clam = text[0];     //Set clam to 'A'&lt;br /&gt;
text[1] = clam;     //Change the 'r' to 'A', is is now 'AAab'&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What you can't do is mix character arrays with strings. The internal storage is different. For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
int clams[] = &amp;quot;Clams&amp;quot;;                       // Invalid.&lt;br /&gt;
int clams[] = {'C', 'l', 'a', 'm', 's', 0};  // Valid, but NOT A STRING.&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Functions=&lt;br /&gt;
Functions, as stated before, are isolated blocks of code that perform an action. They can be invoked, or '''called''', with '''parameters''' that give specific options.&lt;br /&gt;
&lt;br /&gt;
There are two types of ways functions are called:&lt;br /&gt;
*'''direct call''' - You specifically call a function in your code.&lt;br /&gt;
*'''callback''' - The application calls a function in your code, as if it were an event trigger.&lt;br /&gt;
&lt;br /&gt;
There are six types of functions:&lt;br /&gt;
*'''native''': A direct, internal function provided by the application.&lt;br /&gt;
*'''public''': A callback function that is visible to the application and other scripts.&lt;br /&gt;
*'''normal''': A normal function that only you can call.&lt;br /&gt;
*'''static''': The scope of this function is restricted to the current file, can be used in combination with stock.&lt;br /&gt;
*'''stock''': A normal function provided by an include file. If unused, it won't be compiled.&lt;br /&gt;
*'''forward''': This function is a global event provided by the application. If you implement it, it will be a callback.&lt;br /&gt;
&lt;br /&gt;
All code in Pawn must exist in functions. This is in contrast to languages like PHP, Perl, and Python which let you write global code. That is because Pawn is a callback-based language: it responds to actions from a parent application, and functions must be written to handle those actions. Although our examples often contain free-floating code, this is purely for demonstration purposes. Free-floating code in our examples implies the code is part of some function.&lt;br /&gt;
&lt;br /&gt;
==Declaration==&lt;br /&gt;
Unlike variables, functions do not need to be declared before you use them. Functions have two pieces, the '''signature''' and the '''body'''. The signature contains the name of your function and the parameters it will accept. The body is the contents of its code.&lt;br /&gt;
&lt;br /&gt;
Example of a function:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
void AddTwoNumbers(int first, int second)&lt;br /&gt;
{&lt;br /&gt;
  int sum = first + second;&lt;br /&gt;
  return sum;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a simple function. The prototype is this line:&lt;br /&gt;
&amp;lt;pawn&amp;gt;void AddTwoNumbers(int first, int second)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Broken down, it means:&lt;br /&gt;
*&amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt; - Return value type (integer).&lt;br /&gt;
*&amp;lt;tt&amp;gt;AddTwoNumbers&amp;lt;/tt&amp;gt; - Name of the function.&lt;br /&gt;
*&amp;lt;tt&amp;gt;int first&amp;lt;/tt&amp;gt; - First parameter, an integer.&lt;br /&gt;
*&amp;lt;tt&amp;gt;int second&amp;lt;/tt&amp;gt; - Second parameter, an integer.&lt;br /&gt;
&lt;br /&gt;
The body is a block of code. It creates a new variable, called &amp;lt;tt&amp;gt;sum&amp;lt;/tt&amp;gt;, and assigns it the value of the two parameters added together (more on expressions later). The important thing to notice is the &amp;lt;tt&amp;gt;return&amp;lt;/tt&amp;gt; statement, which tells the function to end and return a value to the caller of the function. All functions return something on completion, unless they return a special type called &amp;lt;tt&amp;gt;void&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A function can accept any type of input, and it can return any non-array type.&lt;br /&gt;
&lt;br /&gt;
You can, of course, pass variables to functions:&lt;br /&gt;
&amp;lt;pawn&amp;gt;int numbers[3] = {1, 2, 0};&lt;br /&gt;
&lt;br /&gt;
numbers[2] = AddTwoNumbers(numbers[0], numbers[1]);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that cells are passed '''by value'''. That is, their value cannot be changed by the function. For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;int a = 5;&lt;br /&gt;
&lt;br /&gt;
ChangeValue(a);&lt;br /&gt;
&lt;br /&gt;
ChangeValue(b)&lt;br /&gt;
{&lt;br /&gt;
   b = 5;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code would not change the value of &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt;. That is because a copy of the value in &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; is passed instead of &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; itself. &lt;br /&gt;
&lt;br /&gt;
More examples of functions will be provided throughout the article.&lt;br /&gt;
&lt;br /&gt;
==Publics==&lt;br /&gt;
Public functions are used to implement callbacks. You should not create a public function unless it is specifically implementing a callback. For example, here are two callbacks from &amp;lt;tt&amp;gt;sourcemod.inc&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;forward void OnPluginStart();&lt;br /&gt;
forward void OnClientDisconnected(int client);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To implement and receive these two events, you would write functions as such:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
   /* Code here */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void OnClientDisconnected(int client)&lt;br /&gt;
{&lt;br /&gt;
   /* Code here */&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The '''public''' keyword signals to the parent application that it should attach the function to the appropriate forwarded event.&lt;br /&gt;
&lt;br /&gt;
==Natives==&lt;br /&gt;
Natives are builtin functions provided by SourceMod. You can call them as if they were a normal function. For example, SourceMod has the following function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;native float FloatRound(float num);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It can be called like so:&lt;br /&gt;
&amp;lt;pawn&amp;gt;int rounded = FloatRound(5.2);     // rounded will be 5&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Array Parameters==&lt;br /&gt;
You can pass arrays or Strings as parameters. It is important to note that these are passed '''by reference'''. That is, rather than making a copy of the data, the data is referenced directly. There is a simple way of explaining this more concretely.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
int example[] = {1, 2, 3, 4, 5};&lt;br /&gt;
&lt;br /&gt;
ChangeArray(example, 2, 29);&lt;br /&gt;
&lt;br /&gt;
void ChangeArray(int[] array, int index, int value)&lt;br /&gt;
{&lt;br /&gt;
   array[index] = value;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The function sets the given index in the array to a given value. When it is run on our example array, it changes index 2 to from the value 3 to 29. I.e.:&lt;br /&gt;
&amp;lt;pawn&amp;gt;example[2] = 29;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note two important things here. First, arrays are not copied when they are passed to functions - they are passed ''by reference'', so the view of the array is consistent at all times. Second, the brackets changed position in our function signature. This is because our function accepts an array of any size, and since we don't know the size, we must use the dynamic array syntax.&lt;br /&gt;
&lt;br /&gt;
To prevent an array from being modified in a function, you can mark it as &amp;lt;tt&amp;gt;const&amp;lt;/tt&amp;gt;. This will raise an error on code that attempts to modify it. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;void CantChangeArray(const array[], int index, int value)&lt;br /&gt;
{&lt;br /&gt;
   array[index] = value;    //Won't compile&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is a good idea to use &amp;lt;tt&amp;gt;const&amp;lt;/tt&amp;gt; in array parameters if you know the array won't be modified; this can prevent coding mistakes.&lt;br /&gt;
&lt;br /&gt;
=Expressions=&lt;br /&gt;
Expressions are exactly the same as they are in mathematics. They are groups of operators/symbols which evaluate to one piece of data. They are often parenthetical (comprised of parenthesis). They contain a strict &amp;quot;order of operations.&amp;quot;  They can contain variables, functions, numbers, and expressions themselves can be nested inside other expressions, or even passed as parameters.&lt;br /&gt;
&lt;br /&gt;
The simplest expression is a single number. For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
0;   //Returns the number 0&lt;br /&gt;
(0); //Returns the number 0 as well&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Although expressions can return any value, they are also said to either return ''zero or non-zero''. In that sense, ''zero'' is ''false'', and ''non-zero'' is ''true''. For example, -1 is '''true''' in Pawn, since it is non-zero. Do not assume negative numbers are false.&lt;br /&gt;
&lt;br /&gt;
The order of operations for expressions is similar to C. PMDAS: Parenthesis, Multiplication, Division, Addition, Subtraction. Here are some example expressions:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
5 + 6;                   //Evaluates to 11&lt;br /&gt;
5 * 6 + 3;               //Evaluates to 33&lt;br /&gt;
5 * (6 + 3);             //Evaluates to 45&lt;br /&gt;
5.0 + 2.3;               //Evaluates to 7.3&lt;br /&gt;
(5 * 6) % 7;             //Modulo operator, evaluates to 2&lt;br /&gt;
(5 + 3) / 2 * 4 - 9;     //Evaluates to -8&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As noted, expressions can contain variables, or even functions:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
int a = 5 * 6;&lt;br /&gt;
int b = a * 3;      //Evaluates to 90&lt;br /&gt;
int c = AddTwoNumbers(a, b) + (a * b);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note:  String manipulation routines may be found in the string.inc file located in the include subdirectory. They may be browsed through the [http://docs.sourcemod.net/api/ API Reference] as well.&lt;br /&gt;
&lt;br /&gt;
==Operators==&lt;br /&gt;
There are a few extra helpful operators in Pawn. The first set simplifies self-aggregation expressions. For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;new a = 5;&lt;br /&gt;
&lt;br /&gt;
a = a + 5;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Can be rewritten as:&lt;br /&gt;
&amp;lt;pawn&amp;gt;int a = 5;&lt;br /&gt;
a += 5;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is true of the following operators in Pawn:&lt;br /&gt;
*Four-function: *, /, -, +&lt;br /&gt;
*Bit-wise: |, &amp;amp;, ^, ~, &amp;lt;&amp;lt;, &amp;gt;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, there are increment/decrement operators:&lt;br /&gt;
&amp;lt;pawn&amp;gt;a = a + 1;&lt;br /&gt;
a = a - 1;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Can be simplified as:&lt;br /&gt;
&amp;lt;pawn&amp;gt;a++;&lt;br /&gt;
a--;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As an advanced note, the ++ or -- can come before the variable (pre-increment, pre-decrement) or after the variable (post-increment, post-decrement). The difference is in how the rest of the expression containing them sees their result.&lt;br /&gt;
&lt;br /&gt;
* ''Pre:'' The variable is incremented before evaluation, and the rest of the expression sees the new value.&lt;br /&gt;
* ''Post:'' The variable is incremented after evaluation, and the rest of the expression sees the old value.&lt;br /&gt;
&lt;br /&gt;
In other words, &amp;lt;tt&amp;gt;a++&amp;lt;/tt&amp;gt; evaluates to the value of &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; while &amp;lt;tt&amp;gt;++a&amp;lt;/tt&amp;gt; evaluates to the value of &amp;lt;tt&amp;gt;a + 1&amp;lt;/tt&amp;gt;. In both cases &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; is incremented by &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;int a = 5;&lt;br /&gt;
int b = a++;   // b = 5, a = 6  (1)&lt;br /&gt;
int c = ++a;   // a = 7, c = 7  (2)&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In (1) &amp;lt;tt&amp;gt;b&amp;lt;/tt&amp;gt; is assigned &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt;'s ''old'' value ''before'' it is incremented to &amp;lt;tt&amp;gt;6&amp;lt;/tt&amp;gt;, but in (2) &amp;lt;tt&amp;gt;c&amp;lt;/tt&amp;gt; is assigned &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt;'s ''int'' value ''after'' it is incremented to &amp;lt;tt&amp;gt;7&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Comparison Operators==&lt;br /&gt;
There are six operators for comparing two values numerically, and the result is either true (non-zero) or false (zero):&lt;br /&gt;
*&amp;lt;tt&amp;gt;a == b&amp;lt;/tt&amp;gt; - True if a and b have the same value.&lt;br /&gt;
*&amp;lt;tt&amp;gt;a != b&amp;lt;/tt&amp;gt; - True if a and b have different values.&lt;br /&gt;
*&amp;lt;tt&amp;gt;a &amp;amp;gt; b&amp;lt;/tt&amp;gt; - True if a is greater than b&lt;br /&gt;
*&amp;lt;tt&amp;gt;a &amp;amp;gt;= b&amp;lt;/tt&amp;gt; - True if a is greater than or equal to b&lt;br /&gt;
*&amp;lt;tt&amp;gt;a &amp;amp;lt; b&amp;lt;/tt&amp;gt; - True if a is less than b&lt;br /&gt;
*&amp;lt;tt&amp;gt;a &amp;amp;lt;= b&amp;lt;/tt&amp;gt; - True if a is less than or equal to b&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
(1 != 3);         //Evaluates to true because 1 is not equal to 3.&lt;br /&gt;
(3 + 3 == 6);     //Evaluates to true because 3+3 is 6.&lt;br /&gt;
(5 - 2 &amp;gt;= 4);     //Evaluates to false because 3 is less than 4.&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that these operators do not work on arrays or strings. That is, you cannot compare either using &amp;lt;tt&amp;gt;==&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Truth Operators==&lt;br /&gt;
These truth values can be combined using three boolean operators:&lt;br /&gt;
*&amp;lt;tt&amp;gt;a &amp;amp;&amp;amp; b&amp;lt;/tt&amp;gt; - True if both a and b are true. False if a or b (or both) is false.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
! &amp;lt;tt&amp;gt;&amp;amp;&amp;amp;&amp;lt;/tt&amp;gt; !! 0 !! 1&lt;br /&gt;
|-&lt;br /&gt;
! 0&lt;br /&gt;
| 0 || 0&lt;br /&gt;
|-&lt;br /&gt;
! 1&lt;br /&gt;
| 0 || 1&lt;br /&gt;
|}&lt;br /&gt;
*&amp;lt;tt&amp;gt;a || b&amp;lt;/tt&amp;gt; - True if a or b (or both) is true. False if both a and b are false.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
! &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;||&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; !! 0 !! 1&lt;br /&gt;
|-&lt;br /&gt;
! 0&lt;br /&gt;
| 0 || 1&lt;br /&gt;
|-&lt;br /&gt;
! 1&lt;br /&gt;
| 1 || 1&lt;br /&gt;
|}&lt;br /&gt;
*&amp;lt;tt&amp;gt;!a&amp;lt;/tt&amp;gt; - True if a is false. False if a is true.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
! &amp;lt;tt&amp;gt;!&amp;lt;/tt&amp;gt; !! 0 !! 1&lt;br /&gt;
|- &lt;br /&gt;
!&lt;br /&gt;
| 1 || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
(1 || 0);         //Evaluates to true because the expression 1 is true&lt;br /&gt;
(1 &amp;amp;&amp;amp; 0);         //Evaluates to false because the expression 0 is false&lt;br /&gt;
(!1 || 0);        //Evaluates to false because !1 is false.&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Left/Right Values==&lt;br /&gt;
Two important concepts are left-hand and right-hand values, or l-values and r-values. An l-value is what appears on the left-hand side of a variable assignment, and an r-value is what appears on the right side of a variable assignment.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
int a = 5;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; is an l-value and &amp;lt;tt&amp;gt;5&amp;lt;/tt&amp;gt; is an r-value.&lt;br /&gt;
&lt;br /&gt;
The rules:&lt;br /&gt;
*'''Expressions are never l-values'''.&lt;br /&gt;
*'''Variables are both l-values and r-values'''.&lt;br /&gt;
&lt;br /&gt;
=Conditionals=&lt;br /&gt;
Conditional statements let you only run code if a certain condition is matched.&lt;br /&gt;
&lt;br /&gt;
==If Statements==&lt;br /&gt;
If statements test one or more conditions. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
if (a == 5)&lt;br /&gt;
{&lt;br /&gt;
   /* Code that will run if the expression was true */&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
They can be extended to handle more cases as well:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
if (a == 5)&lt;br /&gt;
{&lt;br /&gt;
   /* Code */&lt;br /&gt;
}&lt;br /&gt;
else if (a == 6)&lt;br /&gt;
{&lt;br /&gt;
   /* Code  */&lt;br /&gt;
}&lt;br /&gt;
else if (a == 7)&lt;br /&gt;
{&lt;br /&gt;
   /* Code */&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also handle the case of no expression being matched. For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
if (a == 5)&lt;br /&gt;
{&lt;br /&gt;
   /* Code */&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   /* Code that will run if no expressions were true */&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Switch Statements==&lt;br /&gt;
Switch statements are restricted if statements. They test one expression for a series of possible values. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
switch (a)&lt;br /&gt;
{&lt;br /&gt;
   case 5:&lt;br /&gt;
   {&lt;br /&gt;
      /* code */&lt;br /&gt;
   }&lt;br /&gt;
   case 6:&lt;br /&gt;
   {&lt;br /&gt;
      /* code */&lt;br /&gt;
   }&lt;br /&gt;
   case 7:&lt;br /&gt;
   {&lt;br /&gt;
      /* code */&lt;br /&gt;
   }&lt;br /&gt;
   case 8, 9, 10:&lt;br /&gt;
   {&lt;br /&gt;
      /* Code */&lt;br /&gt;
   }&lt;br /&gt;
   default:&lt;br /&gt;
   {&lt;br /&gt;
      /* will run if no case matched */&lt;br /&gt;
   }&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unlike some other languages, switches are not fall-through. That is, multiple cases will never be run. When a case matches its code is executed, and the switch is then immediately terminated.&lt;br /&gt;
&lt;br /&gt;
=Loops=&lt;br /&gt;
Loops allow you to conveniently repeat a block of code while a given condition remains true. &lt;br /&gt;
&lt;br /&gt;
==For Loops==&lt;br /&gt;
For loops are loops which have four parts:&lt;br /&gt;
*The '''initialization''' statement - run once before the first loop.&lt;br /&gt;
*The '''condition''' statement - checks whether the next loop should run, including the first one. The loop terminates when this expression evaluates to false.&lt;br /&gt;
*The '''iteration''' statement - run after each loop.&lt;br /&gt;
*The '''body''' block - run each time the '''condition''' statement evaluates to true.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
for ( /* initialization */ ; /* condition */ ; /* iteration */ )&lt;br /&gt;
{&lt;br /&gt;
   /* body */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A simple example is a function to sum an array:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
new array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};&lt;br /&gt;
new sum = SumArray(array, 10);&lt;br /&gt;
&lt;br /&gt;
SumArray(const array[], count)&lt;br /&gt;
{&lt;br /&gt;
   new total;&lt;br /&gt;
&lt;br /&gt;
   for (new i = 0; i &amp;lt; count; i++)&lt;br /&gt;
   {&lt;br /&gt;
      total += array[i];&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   return total;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Broken down:&lt;br /&gt;
*&amp;lt;tt&amp;gt;new i = 0&amp;lt;/tt&amp;gt; - Creates a new variable for the loop, sets it to 0.&lt;br /&gt;
*&amp;lt;tt&amp;gt;i &amp;lt; count&amp;lt;/tt&amp;gt; - Only runs the loop if &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; is less than &amp;lt;tt&amp;gt;count&amp;lt;/tt&amp;gt;. This ensures that the loop stops reading at a certain point. In this case, we don't want to read invalid indexes in the array.&lt;br /&gt;
*&amp;lt;tt&amp;gt;i++&amp;lt;/tt&amp;gt; - Increments &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; by one after each loop. This ensures that the loop doesn't run forever; eventually &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; will become too big and the loop will end.&lt;br /&gt;
&lt;br /&gt;
Thus, the &amp;lt;tt&amp;gt;SumArray&amp;lt;/tt&amp;gt; function will loop through each valid index of the array, each time adding that value of the array into a sum. For loops are very common for processing arrays like this.&lt;br /&gt;
&lt;br /&gt;
==While Loops==&lt;br /&gt;
While loops are less common than for loops but are actually the simplest possible loop. They have only two parts:&lt;br /&gt;
*The '''condition''' statement - checked before each loop. The loop terminates when it evaluates to false.&lt;br /&gt;
*The '''body''' block - run each time through the loop.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
while ( /* condition */ )&lt;br /&gt;
{&lt;br /&gt;
   /* body */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As long as the condition expression remains true, the loop will continue. Every for loop can be rewritten as a while loop:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/* initialization */&lt;br /&gt;
while ( /* condition */ )&lt;br /&gt;
{&lt;br /&gt;
   /* body */&lt;br /&gt;
   /* iteration */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is the previous for loop rewritten as a while loop:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
SumArray(const array[], count)&lt;br /&gt;
{&lt;br /&gt;
   new total, i;&lt;br /&gt;
&lt;br /&gt;
   while (i &amp;lt; count)&lt;br /&gt;
   {&lt;br /&gt;
      total += array[i];&lt;br /&gt;
      i++;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   return total;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also '''do...while''' loops which are even less common. These are the same as while loops except the condition check is AFTER each loop, rather than before. This means the loop is always run at least once. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
do&lt;br /&gt;
{&lt;br /&gt;
   /* body */&lt;br /&gt;
}&lt;br /&gt;
while ( /* condition */ );&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Loop Control==&lt;br /&gt;
There are two cases in which you want to selectively control a loop:&lt;br /&gt;
*'''skipping''' one iteration of the loop but continuing as normal, or;&lt;br /&gt;
*'''breaking''' the loop entirely before it's finished.&lt;br /&gt;
&lt;br /&gt;
Let's say you have a function which takes in an array and searches for a matching number. You want it to stop once the number is found:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Returns the array index where the value is, or -1 if not found.&lt;br /&gt;
 */&lt;br /&gt;
SearchInArray(const array[], count, value)&lt;br /&gt;
{&lt;br /&gt;
   new index = -1;&lt;br /&gt;
 &lt;br /&gt;
   for (new i = 0; i &amp;lt; count; i++)&lt;br /&gt;
   {&lt;br /&gt;
      if (array[i] == value)&lt;br /&gt;
      {&lt;br /&gt;
         index = i;&lt;br /&gt;
         break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   return index;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Certainly, this function could simply &amp;lt;tt&amp;gt;return i&amp;lt;/tt&amp;gt; instead, but the example shows how &amp;lt;tt&amp;gt;break&amp;lt;/tt&amp;gt; will terminate the loop.&lt;br /&gt;
&lt;br /&gt;
Similarly, the &amp;lt;tt&amp;gt;continue&amp;lt;/tt&amp;gt; keyword skips an iteration of a loop. For example, let's say we wanted to sum all even numbers:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
SumEvenNumbers(const array[], count)&lt;br /&gt;
{&lt;br /&gt;
   new sum;&lt;br /&gt;
 &lt;br /&gt;
   for (new i = 0; i &amp;lt; count; i++)&lt;br /&gt;
   {&lt;br /&gt;
      /* If divisibility by 2 is 1, we know it's odd */&lt;br /&gt;
      if (array[i] % 2 == 1)&lt;br /&gt;
      {&lt;br /&gt;
         /* Skip the rest of this loop iteration */&lt;br /&gt;
         continue;&lt;br /&gt;
      }&lt;br /&gt;
      sum += array[i];&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;
&lt;br /&gt;
=Scope=&lt;br /&gt;
Scope refers to the '''visibility''' of code. That is, code at one level may not be &amp;quot;visible&amp;quot; to code at another level. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
new A, B, C;&lt;br /&gt;
&lt;br /&gt;
Function1()&lt;br /&gt;
{&lt;br /&gt;
   new B;&lt;br /&gt;
&lt;br /&gt;
   Function2();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Function2()&lt;br /&gt;
{&lt;br /&gt;
   new C;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, &amp;lt;tt&amp;gt;A&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;B&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;C&amp;lt;/tt&amp;gt; exist at '''global scope'''. They can be seen by any function. However, the &amp;lt;tt&amp;gt;B&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;Function1&amp;lt;/tt&amp;gt; is not the same variable as the &amp;lt;tt&amp;gt;B&amp;lt;/tt&amp;gt; at the global level. Instead, it is at '''local scope''', and is thus a '''local variable'''.&lt;br /&gt;
&lt;br /&gt;
Similarly, &amp;lt;tt&amp;gt;Function1&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Function2&amp;lt;/tt&amp;gt; know nothing about each other's variables.&lt;br /&gt;
&lt;br /&gt;
Not only is the variable private to &amp;lt;tt&amp;gt;Function1&amp;lt;/tt&amp;gt;, but it is re-created each time the function is invoked. Imagine this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
Function1()&lt;br /&gt;
{&lt;br /&gt;
   new B;&lt;br /&gt;
&lt;br /&gt;
   Function1();&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above example, &amp;lt;tt&amp;gt;Function1&amp;lt;/tt&amp;gt; calls itself. Of course, this is infinite recursion (a bad thing), but the idea is that each time the function runs, there is a new copy of &amp;lt;tt&amp;gt;B&amp;lt;/tt&amp;gt;. When the function ends, &amp;lt;tt&amp;gt;B&amp;lt;/tt&amp;gt; is destroyed, and the value is lost.&lt;br /&gt;
&lt;br /&gt;
This property can be simplified by saying that a variable's scope is equal to the nesting level it is in. That is, a variable at global scope is visible globally to all functions. A variable at local scope is visible to all code blocks &amp;quot;beneath&amp;quot; its nesting level. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;Function1()&lt;br /&gt;
{&lt;br /&gt;
   new A;&lt;br /&gt;
&lt;br /&gt;
   if (A)&lt;br /&gt;
   {&lt;br /&gt;
      A = 5;&lt;br /&gt;
   }&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code is valid since A's scope extends throughout the function. The following code, however, is not valid:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
Function1()&lt;br /&gt;
{&lt;br /&gt;
   new A;&lt;br /&gt;
&lt;br /&gt;
   if (A)&lt;br /&gt;
   {&lt;br /&gt;
      new B = 5;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   B = 5;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;lt;tt&amp;gt;B&amp;lt;/tt&amp;gt; is declared in a new code block. That means &amp;lt;tt&amp;gt;B&amp;lt;/tt&amp;gt; is only accessible to that code block (and all sub-blocks nested within). As soon as the code block terminates, &amp;lt;tt&amp;gt;B&amp;lt;/tt&amp;gt; is no longer valid.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Dynamic Arrays=&lt;br /&gt;
Dynamic arrays are arrays which don't have a hardcoded size. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;Function1(size)&lt;br /&gt;
{&lt;br /&gt;
   new array[size];&lt;br /&gt;
&lt;br /&gt;
   /* Code */&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dynamic arrays can have any expression as their size as long as the expression evaluates to a number larger than 0. Like normal arrays, SourcePawn does not know the array size after it is created; you have to save it if you want it later.&lt;br /&gt;
&lt;br /&gt;
Dynamic arrays are only valid at the local scope level, since code cannot exist globally.&lt;br /&gt;
&lt;br /&gt;
=Extended Variable Declarations=&lt;br /&gt;
Variables can be declared in more ways than simply &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==decl==&lt;br /&gt;
===Purpose===&lt;br /&gt;
By default, all variables in Pawn are initialized to zero. If there is an explicit initializer, the variable is initialized to the expression after the &amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; token. At a local scope, this can be a run-time expense. The &amp;lt;tt&amp;gt;decl&amp;lt;/tt&amp;gt; keyword (which is only valid at local scope) was introduced to let users decide if they want variables initialized or not.&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;tt&amp;gt;decl&amp;lt;/tt&amp;gt; should not be used on single cell variables. There is almost never any benefit.&lt;br /&gt;
&lt;br /&gt;
===Explanation===&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
new c = 5;&lt;br /&gt;
new d;&lt;br /&gt;
new String:blah[512];&lt;br /&gt;
&lt;br /&gt;
Format(blah, sizeof(blah), &amp;quot;%d %d&amp;quot;, c, d);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this code, &amp;lt;tt&amp;gt;c&amp;lt;/tt&amp;gt; is equal to 5 and &amp;lt;tt&amp;gt;d&amp;lt;/tt&amp;gt; is equal to 0. The run-time expense of this initialization is negligible. However, &amp;lt;tt&amp;gt;blah&amp;lt;/tt&amp;gt; is a large array, and the expense of initializing the entire array to 0s could be detrimental in certain situations. &lt;br /&gt;
&lt;br /&gt;
Note that &amp;lt;tt&amp;gt;blah&amp;lt;/tt&amp;gt; does not need to be zeroed. In between being declared with &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt; and stored with &amp;lt;tt&amp;gt;Format()&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;blah&amp;lt;/tt&amp;gt; is never loaded or read. Thus this code would be more efficiently written as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
new c = 5;&lt;br /&gt;
new d;&lt;br /&gt;
decl String:blah[512];&lt;br /&gt;
&lt;br /&gt;
Format(blah, sizeof(blah), &amp;quot;%d %d&amp;quot;, c, d);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Caveats===&lt;br /&gt;
The downside to &amp;lt;tt&amp;gt;decl&amp;lt;/tt&amp;gt; is that it means its variables will start with &amp;quot;garbage&amp;quot; contents. For example, if we were to use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
new c = 5;&lt;br /&gt;
new d;&lt;br /&gt;
decl String:blah[512];&lt;br /&gt;
&lt;br /&gt;
PrintToServer(&amp;quot;%s&amp;quot;, blah);&lt;br /&gt;
&lt;br /&gt;
Format(blah, sizeof(blah), &amp;quot;%d %d&amp;quot;, c, d);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code may crash the server, because &amp;lt;tt&amp;gt;blah&amp;lt;/tt&amp;gt; may be completely corrupt (strings require a terminator, and that may not be present). Similarly, if we did:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
new c = 5;&lt;br /&gt;
decl d;&lt;br /&gt;
decl String:blah[512];&lt;br /&gt;
&lt;br /&gt;
Format(blah, sizeof(blah), &amp;quot;%d %d&amp;quot;, c, d);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The value of &amp;lt;tt&amp;gt;d&amp;lt;/tt&amp;gt; is now undefined. It could be any value, negative or positive. &lt;br /&gt;
&lt;br /&gt;
Note that it is easy to efficiently make strings safe. The example below shows how to terminate a garbage string:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
decl String:blah[512];&lt;br /&gt;
&lt;br /&gt;
blah[0] = '\0';&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Golden Rules===&lt;br /&gt;
*'''Only use decl if in between declaring and loading/reading the value, you are absolutely sure there is at least one store/set operation that gives the variable valid data.'''&lt;br /&gt;
*'''Do not prematurely optimize.'''  Likewise, there is no need to use &amp;lt;tt&amp;gt;decl&amp;lt;/tt&amp;gt; on non-arrays, because there is no added expense for initializing a single cell value.&lt;br /&gt;
&lt;br /&gt;
===Notes===&lt;br /&gt;
This example is NOT as efficient as a &amp;lt;tt&amp;gt;decl&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
new String:blah[512] = &amp;quot;a&amp;quot;;&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Even though the string is only one character, the &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt; operator guarantees the rest of the array will be zeroed as well.&lt;br /&gt;
&lt;br /&gt;
Also note, it is valid to explicitly initialize a &amp;lt;tt&amp;gt;decl&amp;lt;/tt&amp;gt; '''ONLY''' with strings:&lt;br /&gt;
&amp;lt;pawn&amp;gt;decl String:blah[512] = &amp;quot;a&amp;quot;;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, any other tag will fail to compile, because the purpose of &amp;lt;tt&amp;gt;decl&amp;lt;/tt&amp;gt; is to avoid any initialization:&lt;br /&gt;
&amp;lt;pawn&amp;gt;decl Float:blah[512] = {1.0};&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==static==&lt;br /&gt;
The &amp;lt;tt&amp;gt;static&amp;lt;/tt&amp;gt; keyword is available at global and local scope. It has different meanings in each.&lt;br /&gt;
&lt;br /&gt;
===Global static===&lt;br /&gt;
A global static variable can only be accessed from within the same file. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;//file1.inc&lt;br /&gt;
static Float:g_value1 = 0.15f;&lt;br /&gt;
&lt;br /&gt;
//file2.inc&lt;br /&gt;
static Float:g_value2 = 0.15f;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If a plugin includes both of these files, it will not be able to use either &amp;lt;tt&amp;gt;g_value1&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;g_value2&amp;lt;/tt&amp;gt;. This is a simple information hiding mechanism, and is similar to declaring member variables as &amp;lt;tt&amp;gt;private&amp;lt;/tt&amp;gt; in languages like C++, Java, or C#.&lt;br /&gt;
&lt;br /&gt;
===Local static===&lt;br /&gt;
A local static variable is a global variable that is only visible from its local lexical scope. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
MyFunction(inc)&lt;br /&gt;
{&lt;br /&gt;
   static counter = -1;&lt;br /&gt;
&lt;br /&gt;
   counter += inc;&lt;br /&gt;
&lt;br /&gt;
   return counter;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, &amp;lt;tt&amp;gt;counter&amp;lt;/tt&amp;gt; is technically a global variable -- it is initialized once to -1 and is never initialized again. It does not exist on the stack. That means each time &amp;lt;tt&amp;gt;MyFunction&amp;lt;/tt&amp;gt; runs, the &amp;lt;tt&amp;gt;counter&amp;lt;/tt&amp;gt; variable and its storage in memory is the same.&lt;br /&gt;
&lt;br /&gt;
Take this example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;MyFunction(5);&lt;br /&gt;
MyFunction(6);&lt;br /&gt;
MyFunction(10);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, &amp;lt;tt&amp;gt;counter&amp;lt;/tt&amp;gt; will be &amp;lt;tt&amp;gt;-1 + 5 + 6 + 10&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;20&amp;lt;/tt&amp;gt;, because it persists beyond the frame of the function. Note this may pose problems for recursive functions: if your function may be recursive, then &amp;lt;tt&amp;gt;static&amp;lt;/tt&amp;gt; is usually not a good idea unless your code is re-entrant. &lt;br /&gt;
&lt;br /&gt;
The benefit of a local static variable is that you don't have to clutter your script with global variables. As long as the variable doesn't need to be read by another function, you can squirrel it inside the function and its persistence will be guaranteed.&lt;br /&gt;
&lt;br /&gt;
Note that statics can exist in any local scope:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
MyFunction(inc)&lt;br /&gt;
{&lt;br /&gt;
   if (inc &amp;gt; 0)&lt;br /&gt;
   {&lt;br /&gt;
      static counter;&lt;br /&gt;
      return (counter += inc);&lt;br /&gt;
   }&lt;br /&gt;
   return -1;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Scripting]]&lt;br /&gt;
&lt;br /&gt;
{{LanguageSwitch}}&lt;/div&gt;</summary>
		<author><name>Nergal</name></author>
		
	</entry>
</feed>