<?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=Mooshua</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=Mooshua"/>
	<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/Special:Contributions/Mooshua"/>
	<updated>2026-05-25T20:45:53Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.6</generator>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=DHooks_(SourceMod_Scripting)&amp;diff=11717</id>
		<title>DHooks (SourceMod Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=DHooks_(SourceMod_Scripting)&amp;diff=11717"/>
		<updated>2024-06-12T23:32:32Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Create basic dhooks page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;DHooks is a hooking and detouring extension for SourceMod plugins. Whereas most existing hook extensions provide a selection of hooks, DHooks allows you to specify the exact hook yourself. DHooks is included with SourceMod starting from 1.12 and newer versions of 1.11.&lt;br /&gt;
&lt;br /&gt;
== DynamicHooks ==&lt;br /&gt;
&lt;br /&gt;
DynamicHooks use SourceHook as a backend, and can only hook virtual tables. To create a DynamicHook, you specify it's virtual offset, hook mode, and return type. You then add each argument individually using the methodmap.&lt;br /&gt;
&lt;br /&gt;
DynamicHooks can hook either a raw thispointer (as an Address), the gamerules object, or an entity index. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
//  Create the initial hook configuration.&lt;br /&gt;
DynamicHook hook = new DynamicHook(/* offset */ 0, HookType_Raw, ReturnType_Void, ThisPointer_Address);&lt;br /&gt;
{&lt;br /&gt;
    hook.AddParam(HookParamType_CharPtr);&lt;br /&gt;
&lt;br /&gt;
    //  Choose a custom pass type of register&lt;br /&gt;
    //  (DHooks will try to automatically detect the register)&lt;br /&gt;
    hook.AddParam(HookParamType_CharPtr, -1, DHookPass_ByRef, DHookRegister_XMM6);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//  Hook an entity by it's entity index&lt;br /&gt;
hook.HookEntity(HookMode_Post, /*ent index*/ edict, /* callbacks and more ... */);&lt;br /&gt;
&lt;br /&gt;
//  Hook a raw address&lt;br /&gt;
hook.HookRaw(HookMode_Post, /*address*/ thisptr, /* callback here.... */);&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Gamedata ==&lt;br /&gt;
&lt;br /&gt;
DHooks parses the &amp;lt;tt&amp;gt;Functions&amp;lt;/tt&amp;gt; block of a gamedata file. You can include an OS name in most places to limit values to a specific OS.&lt;br /&gt;
&lt;br /&gt;
Functions are referenced by name, which must be unique across the install&lt;br /&gt;
&lt;br /&gt;
{{Sad|Dhooks handles names globally, so if two functions have the same name in different gamedata files they will conflict!}}&lt;br /&gt;
&lt;br /&gt;
    &amp;quot;FunctionName&amp;quot;&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;signature&amp;quot; &amp;quot;&amp;quot;&lt;br /&gt;
        &amp;quot;address&amp;quot;   &amp;quot;&amp;quot;&lt;br /&gt;
        &amp;quot;offset&amp;quot;    &amp;quot;&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
        &amp;quot;callconv&amp;quot; &amp;quot;cdecl/thiscall/stdcall/fastcall&amp;quot;&lt;br /&gt;
        &amp;quot;hooktype&amp;quot; &amp;quot;entity/gamerules/raw&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
        &amp;quot;return&amp;quot; &amp;quot;&amp;quot;&lt;br /&gt;
        &amp;quot;this&amp;quot;   &amp;quot;ignore/entity/address&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
        &amp;quot;arguments&amp;quot;&lt;br /&gt;
        {&lt;br /&gt;
            arg_name&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;type&amp;quot; &amp;quot;&amp;quot;&lt;br /&gt;
                &amp;quot;size&amp;quot; &amp;quot;&amp;quot;&lt;br /&gt;
                &amp;quot;flags&amp;quot;    &amp;quot;byval/byref/odtor/octor/oassignop/ocopyctor/ounalign&amp;quot;&lt;br /&gt;
                &amp;quot;register&amp;quot; &amp;quot;theres a lot&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
You can call &amp;lt;tt&amp;gt;FromConf&amp;lt;/tt&amp;gt; on a hook to load the appropriate function from a gamedata file:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
//  Must have an offset, no address or signature&lt;br /&gt;
DynamicHook.FromConf(gamedata, &amp;quot;FunctionName&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
//  Must have a signature or address!&lt;br /&gt;
DynamicDetour.FromConf(gamedata, &amp;quot;FunctionName&amp;quot;);&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Scripting]]&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Category:SourceMod_Documentation&amp;diff=11716</id>
		<title>Category:SourceMod Documentation</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Category:SourceMod_Documentation&amp;diff=11716"/>
		<updated>2024-06-12T23:04:11Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ForSysadmins|SourceMod}}&lt;br /&gt;
&lt;br /&gt;
'''Installation'''&lt;br /&gt;
*[[Installing SourceMod]]&lt;br /&gt;
*[[Upgrading SourceMod]]&lt;br /&gt;
&lt;br /&gt;
'''Configuration'''&lt;br /&gt;
*[[SourceMod Configuration|General Overview]]&lt;br /&gt;
*[[Adding Admins (SourceMod)|Adding Admins]]&lt;br /&gt;
*[[Adding Groups (SourceMod)|Adding Groups]]&lt;br /&gt;
*[[Overriding Command Access (SourceMod)|Overriding Command Access]]&lt;br /&gt;
*[[SQL Admins (SourceMod)|SQL Admins]]&lt;br /&gt;
*[[Admin Menu Configuration (SourceMod)|Admin Menu Configuration]]&lt;br /&gt;
*[[Dynamic Admin Menu (SourceMod) | Dynamic Admin Menu Configuration]]&lt;br /&gt;
*[[Reserved Slots (SourceMod)|Reserved Slots]]&lt;br /&gt;
*[[Map Management Plugins (SourceMod)|Map Management Plugins]]&lt;br /&gt;
*[[Multiple_or_Forked_Servers_(SourceMod)|Multiple or Forked Servers]]&lt;br /&gt;
&lt;br /&gt;
'''Information'''&lt;br /&gt;
*[[Admin Commands (SourceMod)|Admin Commands]]&lt;br /&gt;
*[[Public Commands (SourceMod)|Public Commands]]&lt;br /&gt;
*[[Base Plugins (SourceMod)|Base Plugin List]]&lt;br /&gt;
*[[War Mode (SourceMod)|War Mode]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod]]&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Category:SourceMod_Scripting&amp;diff=11715</id>
		<title>Category:SourceMod Scripting</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Category:SourceMod_Scripting&amp;diff=11715"/>
		<updated>2024-06-12T23:03:46Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ForDevelopers}}&lt;br /&gt;
&lt;br /&gt;
This category contains articles about scripting for SourceMod with SourcePawn.&lt;br /&gt;
&lt;br /&gt;
===Introductions===&lt;br /&gt;
*[[Introduction to SourcePawn 1.7]] - Learning language syntax.&lt;br /&gt;
*[[SourcePawn Transitional Syntax]] - Learning transitional syntax.&lt;br /&gt;
*[[Introduction to SourceMod Plugins]] - Writing your &amp;quot;first plugin.&amp;quot;&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/ API Reference] - Searchable scripting API reference.&lt;br /&gt;
&lt;br /&gt;
===Basic API===&lt;br /&gt;
*[[AutoConfigs (SourceMod Scripting)|AutoConfigs]] - Automatic .cfg creation for cvars.&lt;br /&gt;
*[[Commands (SourceMod Scripting)|Commands]] - Console commands/input.&lt;br /&gt;
*[[ConVars (SourceMod Scripting)|ConVars]] - Console variables (cvars).&lt;br /&gt;
*[[Events (SourceMod Scripting)|Events]] - Half-Life 2 Game Events.&lt;br /&gt;
*[[KeyValues (SourceMod Scripting)|KeyValues]] - KeyValues file parsing/writing.&lt;br /&gt;
*[[Menu API (SourceMod)|Menus]] - Building and drawing menus.&lt;br /&gt;
*[[SQL (SourceMod Scripting)|SQL]] - Using databases (MySQL, SQLite).&lt;br /&gt;
*[[Timers (SourceMod Scripting)|Timers]] - Timed callbacks.&lt;br /&gt;
*[[DataPacks|DataPacks]] -  A good way to store asynchronous data.&lt;br /&gt;
*[[Translations (SourceMod Scripting)|Translations]] - Internationalization.&lt;br /&gt;
*[[Entity References (SourceMod)|Entity References]] - A safe way of storing entities.&lt;br /&gt;
*[[Checking Admin Flags (SourceMod Scripting)|Checking Admin Flags]] - Limit commands to certain users&lt;br /&gt;
&lt;br /&gt;
===Advanced API===&lt;br /&gt;
*[[Admin API (SourceMod)|Administration API]] - Using the Admin Cache.&lt;br /&gt;
*[[Admin Menu (SourceMod Scripting)|Admin Menu API]] - Attaching to the Admin Menu.&lt;br /&gt;
*[[Creating Natives (SourceMod Scripting)|Creating Natives]] - Exposing API to other plugins.&lt;br /&gt;
*[[Function Calling API (SourceMod Scripting)|Function Calling API]] - Calling external functions.&lt;br /&gt;
*[[Optional Requirements (SourceMod Scripting)|Optional Requirements]] - Managing dependencies.&lt;br /&gt;
*[[SDKTools (SourceMod Scripting)|SDKTools]] - Using the powerful SDK abstraction layer.&lt;br /&gt;
*[[TempEnts (SourceMod SDKTools)|Temporary Entities]] - Using temporary entities.&lt;br /&gt;
&lt;br /&gt;
===Information===&lt;br /&gt;
*[[Format Class Functions (SourceMod Scripting)|Format Class Functions]] - All about text formatting.&lt;br /&gt;
*[[Handles (SourceMod Scripting)|Handles]] - Overview of Handles and some common types.&lt;br /&gt;
*[[Optimizing Plugins (SourceMod Scripting)|Optimizing Plugins]] - Optimization hints.&lt;br /&gt;
*[[Tags (Scripting)|Tags]] - All about tags.&lt;br /&gt;
*[[Vectors Explained (Scripting)|Vectors Explained]] - Explanation of Vector types.&lt;br /&gt;
&lt;br /&gt;
===Resources===&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/ API Reference] - Searchable scripting API reference.&lt;br /&gt;
*[[Entity Properties]] - Explanation of Source entity properties.&lt;br /&gt;
*[[Game Events (Source)|Game Events]] - Game events listings for popular mods.&lt;br /&gt;
*[[Mod TempEnt List (Source)|Temp Entity Lists]] - Temporary entities for popular mods.&lt;br /&gt;
*[[SourceMod Profiler]] - Performance tracking and optimizing.&lt;br /&gt;
*[[Vice_keys]] - Decryption keys for ctx files&lt;br /&gt;
*[[Weapon Names(Source)]] - Weapon Names / weapon entity names&lt;br /&gt;
[[Category:SourceMod]]&lt;br /&gt;
[[Category:SourceMod Development]]&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Category:SourceMod_Development&amp;diff=11714</id>
		<title>Category:SourceMod Development</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Category:SourceMod_Development&amp;diff=11714"/>
		<updated>2024-06-12T23:03:27Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ForAdvancedDevelopers|SourceMod}}&lt;br /&gt;
&lt;br /&gt;
This category contains articles about developing for SourceMod extensions.  [[:Category:SourceMod_Scripting|Click here for the scripting category]].&lt;br /&gt;
&lt;br /&gt;
==Scripting==&lt;br /&gt;
*[[:Category:SourceMod_Scripting|Scripting Tutorials]]&lt;br /&gt;
*[https://sm.alliedmods.net/new-api/ Scripting Reference]&lt;br /&gt;
&lt;br /&gt;
==Introductions==&lt;br /&gt;
*[[SourceMod SDK]]&lt;br /&gt;
*[[Writing Extensions]]&lt;br /&gt;
*[[Writing Extensions from Metamod:Source Plugins]]&lt;br /&gt;
*[http://docs.sourcemod.net/dox Doxygen of SourceMod API]&lt;br /&gt;
&lt;br /&gt;
==Detailed Tutorials==&lt;br /&gt;
*[[Admin API (SourceMod)|Administration API]]&lt;br /&gt;
*[[Compiling SourceMod]]&lt;br /&gt;
*[[Handle API (SourceMod)|Handle System API]]&lt;br /&gt;
*[[Menu API (SourceMod)|Menu System API]]&lt;br /&gt;
*[[Natives (SourceMod Development)|Writing Native Functions]]&lt;br /&gt;
*[[Finding Virtual Offsets]]&lt;br /&gt;
&lt;br /&gt;
==Resources==&lt;br /&gt;
&lt;br /&gt;
*[[Virtual_Offsets_(Source_Mods)|Virtual Offsets List]]&lt;br /&gt;
*[[Entity Properties]]&lt;br /&gt;
*[[Game Events (Source)|Game Events]]&lt;br /&gt;
*[[Mod TempEnt List (Source)|Temporary Entity Lists]]&lt;br /&gt;
*[[Useful Signatures (Source)|Useful Signatures]]&lt;br /&gt;
*[[:Category:Metamod:Source Development|Metamod:Source Development]]&lt;br /&gt;
*[[:Category:Game_Resources|Mod Specific Resources]]&lt;br /&gt;
*[[User_Messages|User Messages]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod]]&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Template:ForAdvancedDevelopers&amp;diff=11713</id>
		<title>Template:ForAdvancedDevelopers</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Template:ForAdvancedDevelopers&amp;diff=11713"/>
		<updated>2024-06-12T23:02:36Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Created page with &amp;quot;&amp;lt;div style=&amp;quot;padding: 0.75em 1.5em; border-width: 2px; border-color: Orange; border-style:solid; background-color: Moccasin; max-width: 60rem;&amp;quot;&amp;gt; File:Wires.png|frameless|128p...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;padding: 0.75em 1.5em; border-width: 2px; border-color: Orange; border-style:solid; background-color: Moccasin; max-width: 60rem;&amp;quot;&amp;gt;&lt;br /&gt;
[[File:Wires.png|frameless|128px|left|link=|alt=]]&lt;br /&gt;
&amp;lt;b style=&amp;quot;font-size: 20px&amp;quot;&amp;gt;&lt;br /&gt;
For Internal Development&lt;br /&gt;
&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
This page is geared towards helping developers learn how to use the behind-the-scenes parts of {{{1|SourceMod}}} itself.&lt;br /&gt;
If you're looking to contribute to or extend {{{1|SourceMod}}}, this is probably the page for you!&lt;br /&gt;
Look inside and see the wires that make {{{1|SourceMod}}} tick&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=File:Wires.png&amp;diff=11712</id>
		<title>File:Wires.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=File:Wires.png&amp;diff=11712"/>
		<updated>2024-06-12T22:58:57Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Look Inside
Wires

Copyright Unknown&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
Look Inside&lt;br /&gt;
Wires&lt;br /&gt;
&lt;br /&gt;
Copyright Unknown&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=SourceHook_Development&amp;diff=11711</id>
		<title>SourceHook Development</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=SourceHook_Development&amp;diff=11711"/>
		<updated>2024-06-12T22:48:17Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Move embedding to it's own page: SourceHook Standalone&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;SourceHook is a powerful API (Application Programming Interface) for detouring (hooking) virtual functions.  Unlike static detours, SourceHook needs only to swap addresses in and out of an object's virtual table.  This makes it fast and generally very platform-safe.&lt;br /&gt;
&lt;br /&gt;
SourceHook is coupled with Don Clugston's [http://www.codeproject.com/cpp/FastDelegate.asp FastDelegate] headers.  Virtual hooks can be detoured to any static function of the same prototype, or any member function (of any class) as long as the prototype matches.&lt;br /&gt;
&lt;br /&gt;
All code in SourceHook is part of the SourceHook namespace.  Thus, it may be prudent to declare this before using SourceHook structures or types:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;using namespace SourceHook;&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Simple Hooks=&lt;br /&gt;
SourceHook has the following steps of operation:&lt;br /&gt;
&lt;br /&gt;
* Declare the prototype of the function you are going to hook. This generates compile-time code that is able to pinpoint exactly how to go about hooking the function.&lt;br /&gt;
* Hook the function - as a member function of another class or a regular static function.&lt;br /&gt;
* Before the hooked function is called, all of the &amp;quot;pre&amp;quot; hook handlers attached to it are called. Each hook can set a special flag, the highest of which is chosen as a final operation. This flag specifies whether the original function should be called or not.&lt;br /&gt;
* Once all the hooks have been called, SourceHook decides whether to call the original function. Another set of hooks are called directly after, called &amp;quot;post&amp;quot; hook handlers. You can specify whether each hook is a post or pre hook - it simply changes whether it's called before or after the original call is made.&lt;br /&gt;
* After you are done using a hook, you must safely remove it before the object is destroyed (otherwise, memory will be leaked).&lt;br /&gt;
&lt;br /&gt;
==Declaration==&lt;br /&gt;
As an example, take the following class prototype:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class IVEngineServer&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   /*...*/&lt;br /&gt;
   virtual void LogPrint( const char *msg ) = 0;&lt;br /&gt;
   virtual bool IsDedicated() = 0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
extern IVEngineServer *engine;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The first step is to figure out how to declare its prototype to SourceHook. This function is void, and has one parameter. The declaration macro follows these formats:&lt;br /&gt;
&lt;br /&gt;
*{{bcode|SH_DECL_HOOK}}n - n is the number of parameters&lt;br /&gt;
**The parameters are: Class name, member function name, attributes, overloaded?, the return type, and a list of the parameter types.&lt;br /&gt;
*{{bcode|SH_DECL_HOOKn_void}} - n is the number of parameters&lt;br /&gt;
**_void specifies that the function does not return a value. The format is the same as above except the &amp;quot;return type&amp;quot; parameter is missing.&lt;br /&gt;
*'''Note:''' Not covered here are the SH_DECL_HOOKn[_void]_vafmt hooks. These can hook string-formattable variable argument lists. You do not pass the string format or ellipses parameter. SourceHook will automatically format the string for your hook.&lt;br /&gt;
&lt;br /&gt;
Our macro will look like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SH_DECL_HOOK1_void(IVEngineServer, LogPrint, SH_NOATTRIB, 0, const char *);&lt;br /&gt;
SH_DECL_HOOK0(IVEngineServer, IsDedicated, SH_NOATTRIB, 0, bool);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Broken down for the first line:&lt;br /&gt;
*There is 1 parameter.&lt;br /&gt;
*The function has no return value.&lt;br /&gt;
*&amp;lt;tt&amp;gt;IVEngineServer&amp;lt;/tt&amp;gt; is the class containing the function.&lt;br /&gt;
*&amp;lt;tt&amp;gt;LogPrint&amp;lt;/tt&amp;gt; is the function being hooked.&lt;br /&gt;
*The function as no attributes (for example, it is not const).&lt;br /&gt;
*The function is not overloaded.&lt;br /&gt;
*The first (and only) argument is a &amp;lt;tt&amp;gt;const char *&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second line is similar, except the parameter immediately after the overload parameter specifies the return type.  There are no further parameters since it was declared with 0.&lt;br /&gt;
&lt;br /&gt;
==Getting an Interface Instance==&lt;br /&gt;
&lt;br /&gt;
Before you can use an interface, you need to retrieve an instance of it.  This is done with either the &amp;lt;tt&amp;gt;GET_V_IFACE_ANY&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;GET_V_IFACE_CURRENT&amp;lt;/tt&amp;gt; macros.  Both take the same arguments.  &amp;lt;tt&amp;gt;GET_V_IFACE_CURRENT&amp;lt;/tt&amp;gt; is recommended if it works.  &amp;lt;tt&amp;gt;GET_V_IFACE_ANY&amp;lt;/tt&amp;gt; should also work, but may be missing newer functionality.&lt;br /&gt;
&lt;br /&gt;
Normally this initialization needs to be done when your MM:S plugin or SourceMod Extension starts.&lt;br /&gt;
&lt;br /&gt;
You also need to know which factory produces the interface you need.  There are only 4 factories: &amp;lt;tt&amp;gt;GetEngineFactory&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;GetServerFactory&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;GetPhysicsFactory&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;GetFilesystemFactory&amp;lt;/tt&amp;gt;.  Normally you'll want Engine or Server.&lt;br /&gt;
&lt;br /&gt;
You'll also need to know the constant that the game uses for that particular class.  This is usually found in the hl2sdk for your game.  In the case of &amp;lt;tt&amp;gt;IVEngineServer&amp;lt;/tt&amp;gt;, this is &amp;lt;tt&amp;gt;INTERFACEVERSION_VENGINESERVER&amp;lt;/tt&amp;gt; located in public/eiface.h.&lt;br /&gt;
&lt;br /&gt;
So, to retrieve the Interface so you can do something with it, it'd look something like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
IVEngineServer *engine;&lt;br /&gt;
&lt;br /&gt;
// For SourceMod, use the first signature&lt;br /&gt;
//bool MyExtension::OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)&lt;br /&gt;
bool MyPlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late)&lt;br /&gt;
{&lt;br /&gt;
    GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The error and maxlen arguments '''must''' be named error and maxlen respectively, or else certain macros will fail.&lt;br /&gt;
&lt;br /&gt;
Note that MyPlugin should be replaced with your plugin's class.&lt;br /&gt;
&lt;br /&gt;
==Hook Functions==&lt;br /&gt;
Hooks can be declared either ''pre'' or ''post''.  A ''pre'' hook will intercept the original function before it is called.  Pre-hooks can return one of four ''hook actions'':&lt;br /&gt;
*&amp;lt;tt&amp;gt;MRES_IGNORED&amp;lt;/tt&amp;gt; - The original function will be called.&lt;br /&gt;
*&amp;lt;tt&amp;gt;MRES_HANDLED&amp;lt;/tt&amp;gt; - Same as &amp;lt;tt&amp;gt;MRES_IGNORED&amp;lt;/tt&amp;gt;, except subsequent hooks can assume this means something important was changed.&lt;br /&gt;
*&amp;lt;tt&amp;gt;MRES_OVERRIDE&amp;lt;/tt&amp;gt; - The original function will be called, but the new return value will be used instead of the one from the original function.&lt;br /&gt;
*&amp;lt;tt&amp;gt;MRES_SUPERCEDE&amp;lt;/tt&amp;gt; - The original function will not be called.  The new return value (if any) will be used instead.&lt;br /&gt;
&lt;br /&gt;
These enum constants are defined in &amp;lt;tt&amp;gt;&amp;lt;sourcehook.h&amp;gt;&amp;lt;/tt&amp;gt;, and are made available to Metamod:Source plugin developers via &amp;lt;tt&amp;gt;&amp;lt;ISmmPlugin.h&amp;gt;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Once all pre-hooks have been processed, SourceHook takes an action based on the &amp;quot;highest&amp;quot; hook action returned (&amp;lt;tt&amp;gt;MRES_IGNORED&amp;lt;/tt&amp;gt; being lowest, &amp;lt;tt&amp;gt;MRES_SUPERCEDE&amp;lt;/tt&amp;gt; being highest).  Once the action has been processed, all ''post'' hooks are called.  That is to say, even if the original function is never called, post hooks are still processed.  Because a post hook as no chance at true interception, it is important to realize that depending on the information being detoured, the data may be modified or destroyed.  Similarly, a post hook's returned action and value is ignored.&lt;br /&gt;
&lt;br /&gt;
A hook's action is signalled via one of two macros:&lt;br /&gt;
*&amp;lt;tt&amp;gt;RETURN_META&amp;lt;/tt&amp;gt; - Only usable from &amp;lt;tt&amp;gt;void&amp;lt;/tt&amp;gt; functions.  Signals the action to take, then returns.&lt;br /&gt;
*&amp;lt;tt&amp;gt;RETURN_META_VALUE&amp;lt;/tt&amp;gt; - Only usable from non-&amp;lt;tt&amp;gt;void&amp;lt;/tt&amp;gt; functions.  Signals the action to take, then returns the supplied value.&lt;br /&gt;
&lt;br /&gt;
There are two methods of adding or removing hooks.  Hooks can be bound to '''static''' or '''member''' functions.  Both have a similar syntax.  Their macros are:&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_STATIC(Function)&amp;lt;/tt&amp;gt; - Hook to a static function.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_MEMBER(Instance, Function)&amp;lt;/tt&amp;gt; - Hook to a member function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;It is important to realize that a simple hook will only be invoked when used on the same instance.&amp;lt;/b&amp;gt;  That is to say, if there are 500 instances of object X, and a hook is added to function X::Y in instance #8, then the hook will only be invoked from instance #8.  &amp;lt;b&amp;gt;Multiple hooks can be declared on the same instance, and multiple instances can be bound to the same hook, but one hook will only be invoked for the instances it was hooked to.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To have hooks that work across all instances, and thus do not need to be delegated per-instance, see the &amp;quot;Global Hooks&amp;quot; section.  As of SourceHook v5, it is safe to remove hooks on a destroyed instance, as the instance is not actually dereferenced.  However, its virtual table must still be accessible.&lt;br /&gt;
&lt;br /&gt;
==Adding Hooks==&lt;br /&gt;
The macro to add hooks is &amp;lt;tt&amp;gt;SH_[ADD|REMOVE]_HOOK&amp;lt;/tt&amp;gt;.  The syntax is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_[ADD|REMOVE]_HOOK(Interface, Function, Instance, Hook, [post? true,false])&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example of adding a &amp;lt;tt&amp;gt;LogPrint&amp;lt;/tt&amp;gt; hook:&lt;br /&gt;
&amp;lt;cpp&amp;gt;void Hook_LogPrint(const char *msg)&lt;br /&gt;
{&lt;br /&gt;
   if (strcmp(msg, &amp;quot;If this string matches the function will be blocked&amp;quot;) == 0)&lt;br /&gt;
   {&lt;br /&gt;
      RETURN_META(MRES_SUPERCEDE);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /* Not needed, but good style */&lt;br /&gt;
   RETURN_META(MRES_IGNORED);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StartHooks()&lt;br /&gt;
{&lt;br /&gt;
   log_hook = SH_ADD_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(Hook_LogPrint), false);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StopHooks()&lt;br /&gt;
{&lt;br /&gt;
   SH_REMOVE_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(Hook_LogPrint), false);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax is similar for hooking to member functions.  Example equivalent to the above:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class MyHooks&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   void Hook_LogPrint(const char *msg)&lt;br /&gt;
   {&lt;br /&gt;
      if (strcmp(msg, &amp;quot;If this string matches the function will be blocked&amp;quot;) == 0)&lt;br /&gt;
      {&lt;br /&gt;
         RETURN_META(MRES_SUPERCEDE);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      /* Not needed, but good style */&lt;br /&gt;
      RETURN_META(MRES_IGNORED);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   void StartHooks()&lt;br /&gt;
   {&lt;br /&gt;
      SH_ADD_HOOK(IVEngineServer, LogPrint, engine, SH_MEMBER(this, &amp;amp;MyHooks::Hook_LogPrint), false);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   void StopHooks()&lt;br /&gt;
   {&lt;br /&gt;
      SH_REMOVE_HOOK(IVEngineServer, LogPrint, engine, SH_MEMBER(this, &amp;amp;MyHooks::Hook_LogPrint), false);&lt;br /&gt;
   }&lt;br /&gt;
};&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Manual Hooks=&lt;br /&gt;
In some cases, it may be necessary to support multiple, incompatible ABI branches of an interface.  For example, suppose you need to hook an application that may supply either version of these interfaces:&lt;br /&gt;
&lt;br /&gt;
Interface v1:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class Interface&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void Function1() =0;&lt;br /&gt;
   virtual bool Function2(int clam) =0;&lt;br /&gt;
};&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Interface v2:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class Interface&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual bool Function2(int clam) =0;&lt;br /&gt;
};&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Obviously, these two interfaces are backwards incompatible.  Manual hooks allow you to precisely define the structure of the virtual table, bypassing the compiler's rules.  These rules can be re-configured at runtime.&lt;br /&gt;
&lt;br /&gt;
==Declaration==&lt;br /&gt;
Declaring a manual hook is similar to declaring a normal/simple hook.  The syntax is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_DECL_MANUALHOOK&amp;lt;n&amp;gt;[_void](UniqueName, vtblIndex, vtblOffs, thisOffs, [return and param types])&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;UniqueName&amp;lt;/tt&amp;gt; is a unique identifier for the hook.  The &amp;lt;tt&amp;gt;vtblIndex&amp;lt;/tt&amp;gt; is the index into the virtual table at which the function lies.  In most compilers, this index starts from 0.  The &amp;lt;tt&amp;gt;vtblOffs&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;thisOffs&amp;lt;/tt&amp;gt; fields are used for multiple inheritance and are almost always 0 in modern compiler single inheritance.&lt;br /&gt;
&lt;br /&gt;
An example of hooking the two functions from the first interface version:&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_DECL_MANUALHOOK0_void(MHook_Function1, 0, 0, 0);&lt;br /&gt;
SH_DECL_MANUALHOOK1(MHook_Function2, 1, 0, 0, bool, int);&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Reconfiguring==&lt;br /&gt;
A manual hook can be ''reconfigured'', which will update its set offsets.  Reconfiguration automatically removes all hooks on the manual hook.  Let's say we want to reconfigure the &amp;lt;tt&amp;gt;Function2&amp;lt;/tt&amp;gt; hook in the case of the second version being detected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
void SwitchToNewerHooks()&lt;br /&gt;
{&lt;br /&gt;
   SH_MANUALHOOK_RECONFIGURE(MHook_Function2, 0, 0, 0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the hook was referenced by its unique identifier.&lt;br /&gt;
&lt;br /&gt;
==Adding Hooks==&lt;br /&gt;
Adding or removing hook binds is done via the following extra macros:&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_ADD_MANUALHOOK&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_REMOVE_MANUALHOOK&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These work similar to the original functions.  Example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;extern Interface *iface;&lt;br /&gt;
&lt;br /&gt;
bool Hook_Function2(int clam)&lt;br /&gt;
{&lt;br /&gt;
   RETURN_META_VALUE(MRES_IGNORED, false);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StartHooks()&lt;br /&gt;
{&lt;br /&gt;
   SH_ADD_MANUALHOOK(MHook_Function2, iface, SH_STATIC(Hook_Function2), false);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StopHooks()&lt;br /&gt;
{&lt;br /&gt;
   SH_REMOVE_MANUALHOOK(MHook_Function2, iface, SH_STATIC(Hook_Function2), false);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, a member function version would use &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt; instead.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Extended Removal Syntax=&lt;br /&gt;
The syntax described in the above sections is new as of SourceHook v4.5.  &amp;lt;tt&amp;gt;SH_REMOVE_HOOK&amp;lt;/tt&amp;gt; is, for all intents and purposes, optional.  There is another way to remove hooks.&lt;br /&gt;
&lt;br /&gt;
Each &amp;lt;tt&amp;gt;SH_ADD&amp;lt;/tt&amp;gt; macro returns a non-zero &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt; on success.  The same integer can be passed to the &amp;lt;tt&amp;gt;SH_REMOVE_HOOK_ID&amp;lt;/tt&amp;gt; macro, and the hook will be removed.  This alternate removal syntax can simplify code that uses multiple successive or dynamic hooks.&lt;br /&gt;
&lt;br /&gt;
Global hooks, described in a later section, require usage of &amp;lt;tt&amp;gt;SH_REMOVE_HOOK_ID&amp;lt;/tt&amp;gt; - that is, there is no helper macro to simplify removing a global hook.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Old Macros=&lt;br /&gt;
SourceHook v5.0 deprecates older macros that were used in earlier versions.  The macros are:&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_ADD_HOOK_STATICFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_ADD_HOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_STATIC&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_REMOVE_HOOK_STATICFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_REMOVE_HOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_STATIC&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_ADD_HOOK_MEMFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_ADD_HOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_REMOVE_HOOK_MEMFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_REMOVE_HOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_ADD_MANUALHOOK_STATICFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_ADD_MANUALHOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_STATIC&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_REMOVE_MANUALHOOK_STATICFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_REMOVE_MANUALHOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_STATIC&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_ADD_MANUALHOOK_MEMFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_ADD_MANUALHOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_REMOVE_MANUALHOOK_MEMFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_REMOVE_MANUALHOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
These macros are fairly self explanatory.  The parameter where the &amp;lt;tt&amp;gt;SH_STATIC&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt; macro would normally go is instead filled with the parameters to that macro.  &lt;br /&gt;
&lt;br /&gt;
This syntax is considered deprecated, but it is still supported.  Code written with these macros will continue to compile against older SourceHook versions.  If you are writing a plugin which must work against Metamod:Source 1.4 and 1.6, you will want to use the older macros for simplicity.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Global Hooks=&lt;br /&gt;
&amp;lt;b&amp;gt;Note:&amp;lt;/b&amp;gt; Global Hooks are only available in SourceHook v4.5 or later.&lt;br /&gt;
&lt;br /&gt;
Global hooks are unlike normal hooks in that the hook is invoked for ALL instances, rather than solely the given the instance the hook was bound to.  It is important to realize that this feature can be deceiving.  Consider the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class CBaseEntity&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void SetHealth(int health) =0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class CBaseCat : public CBaseEntity&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void SetHealth();&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class CBaseKitten : public CBaseCat&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void SetHealth();&lt;br /&gt;
};&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, &amp;lt;tt&amp;gt;CBaseCat&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;CBaseKitten&amp;lt;/tt&amp;gt; instances have ''separate virtual tables''.  Although they both derive from &amp;lt;tt&amp;gt;CBaseEntity&amp;lt;/tt&amp;gt;, they are separate virtual objects.  &amp;lt;b&amp;gt;Therefore, a global hook on &amp;lt;tt&amp;gt;CBaseEntity&amp;lt;/tt&amp;gt; will receive no invocations, and a hook on &amp;lt;tt&amp;gt;CBaseCat&amp;lt;/tt&amp;gt; will receive only &amp;lt;tt&amp;gt;CBaseCat&amp;lt;/tt&amp;gt; instances, as long as the instance is not a class derived from &amp;lt;tt&amp;gt;CBaseCat&amp;lt;/tt&amp;gt;&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
With this understanding in place, there are two separate syntaxes - one for simple hooks and one for manual hooks.  Additionally, there are two ways of declaring the virtual interface to use:&lt;br /&gt;
*An instance of the class can be passed.&lt;br /&gt;
*The direct address to the virtual table can be passed.&lt;br /&gt;
&lt;br /&gt;
They are essentially equivalent, although one may be more advantageous than the other (for example, if no instances are known, but the vtable address can be extracted via pattern searching).&lt;br /&gt;
&lt;br /&gt;
It is also important to note that global hooks are just a different method of &amp;quot;filtering.&amp;quot;  They fall into either the &amp;quot;simple&amp;quot; or &amp;quot;manual&amp;quot; category, and are otherwise exactly the same to those hooks.  Thus there are no separate return/declaration macros for global hooks.&lt;br /&gt;
&lt;br /&gt;
The macro &amp;lt;tt&amp;gt;META_IFACEPTR&amp;lt;/tt&amp;gt; is especially useful for global hooks.  See [[SourceHook_Development#Interface_Pointers_from_Hooks|Interface Pointers from Hooks]] near the end.&lt;br /&gt;
&lt;br /&gt;
Lastly, global hooks exclusively use the extended hooking syntax.  That means there exists only &amp;lt;tt&amp;gt;SH_ADD&amp;lt;/tt&amp;gt; macros.  &amp;lt;tt&amp;gt;SH_HOOK_REMOVE_ID&amp;lt;/tt&amp;gt; must be used and the hook ID generated via &amp;lt;tt&amp;gt;SH_ADD&amp;lt;/tt&amp;gt; must be cached.&lt;br /&gt;
&lt;br /&gt;
All examples will use the following code as a basis:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class Player&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void TakeDamage(int damage) =0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
void Hook_TakeDamage(int damage);&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Simple Hooks==&lt;br /&gt;
Two extra macros exist for adding a global hook:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
SH_ADD_VPHOOK(Interface, Function, Instance, Handler, Post)&lt;br /&gt;
SH_ADD_DVPHOOK(Interface, Function, VirtualTable, Handler, Post)&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
extern void *player_vtable;&lt;br /&gt;
HookId takedamage_hook = 0;&lt;br /&gt;
&lt;br /&gt;
void StartHooks()&lt;br /&gt;
{&lt;br /&gt;
   takedamage_hook = SH_ADD_DVPHOOK(Player, TakeDamage, player_vtable, SH_STATIC(Hook_TakeDamage), false);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StopHooks()&lt;br /&gt;
{&lt;br /&gt;
   if (takedamage_hook)&lt;br /&gt;
   {&lt;br /&gt;
      SH_REMOVE_HOOK_ID(takedamage_hook);&lt;br /&gt;
   }&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Manual Hooks==&lt;br /&gt;
Similarly, manual hooks are straightforward:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
SH_DECL_MANUALHOOK1_void(MHook_TakeDamage, 0, 0, 0, int);&lt;br /&gt;
&lt;br /&gt;
extern void *player_vtable;&lt;br /&gt;
int takedamage_hook = 0;&lt;br /&gt;
&lt;br /&gt;
void StartHooks()&lt;br /&gt;
{&lt;br /&gt;
   takedamage_hook = SH_ADD_MANUALDVPHOOK(MHook_TakeDamage, player_vtable, SH_STATIC(Hook_TakeDamage), false);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StopHooks()&lt;br /&gt;
{&lt;br /&gt;
   if (takedamage_hook)&lt;br /&gt;
   {&lt;br /&gt;
      SH_REMOVE_HOOK_ID(takedamage_hook);&lt;br /&gt;
   }&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Modifying Parameters=&lt;br /&gt;
Consider another variation of the hooking process.  There is a hook on function X, which has one parameter.  The hook wants to change the value of this parameter transparently.  For example:&lt;br /&gt;
*Caller passes 5 into X.&lt;br /&gt;
*Hook changes the 5 to a 6.&lt;br /&gt;
*Hooked function receives a 6 and continues normally.&lt;br /&gt;
&lt;br /&gt;
SourceHook has a method for achieving this.  As an added bonus, the new parameters are passed to subsequent hooks.  That means the replacement process is as transparent as possible.  For this example, we'll use the following code, with an assumed hook on &amp;lt;tt&amp;gt;Player::TakeDamage&amp;lt;/tt&amp;gt; to the &amp;lt;tt&amp;gt;Hook_TakeDamage&amp;lt;/tt&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class Player&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void TakeDamage(int damage);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
void Hook_TakeDamage(int damage);&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our objective is to multiply the damage by 2.&lt;br /&gt;
&lt;br /&gt;
==Simple Hooks==&lt;br /&gt;
For simple hooks, changing parameters looks similar to an &amp;lt;tt&amp;gt;SH_CALL&amp;lt;/tt&amp;gt;.  The macros are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;RETURN_META_NEWPARAMS(Action, HookFunction, ([params]))&lt;br /&gt;
RETURN_META_VALUE_NEWPARAMS(Action, Value, HookFunction, ([params]))&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
void Hook_TakeDamage(int damage)&lt;br /&gt;
{&lt;br /&gt;
   RETURN_META_NEWPARAMS(MRES_IGNORED, &amp;amp;Player::TakeDamage, (damage * 2));&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the parenthesis enclosing the parameters are required.&lt;br /&gt;
&lt;br /&gt;
==Manual Hooks==&lt;br /&gt;
Manual hooks require slightly different macros.  They are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;RETURN_META_MNEWPARAMS(Action, UniqueName, ([params]));&lt;br /&gt;
RETURN_META_VALUE_MNEWPARAMS(Action, Value, UniqueName, ([params]));&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
SH_DECL_MANUALHOOK1_void(MHook_Player_TakeDamage, 0, 0, 0, int);&lt;br /&gt;
&lt;br /&gt;
void Hook_TakeDamage(int damage)&lt;br /&gt;
{&lt;br /&gt;
   RETURN_META_MNEWPARAMS(MRES_IGNORED, MHook_Player_TakeDamage, (damage *2));&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the parenthesis enclosing the parameters are required.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Bypassing Hooks=&lt;br /&gt;
Often, either to avoid certain functionality or to avoid infinite recursion, it is necessary to bypass all hooks on a hooked function, such that only the original function is called.  For instance, a previous blocked certain messages sent through &amp;lt;tt&amp;gt;LogPrint&amp;lt;/tt&amp;gt;.  In order to send that message, the hook needs to be bypassed.&lt;br /&gt;
&lt;br /&gt;
To way to do this is to use the &amp;lt;tt&amp;gt;SH_CALL&amp;lt;/tt&amp;gt; macro:&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_CALL(Instance, HookFunction)(params)&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_CALL(engine, &amp;amp;IVEngineServer::LogPrint)(&amp;quot;Secret Message&amp;quot;);&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, manual hooks have &amp;lt;tt&amp;gt;SH_MCALL&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_DECL_MANUALHOOK1(MHook_Function2, 1, 0, 0, bool, int);&lt;br /&gt;
&lt;br /&gt;
bool Function2_Bypass(int clam)&lt;br /&gt;
{&lt;br /&gt;
   return SH_MCALL(iface, MHook_Function2)(clam);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Deprecated Syntax==&lt;br /&gt;
The syntax described above is used in SourceHook v5.0 and v4.5.  An older syntax, using a &amp;quot;CallClass&amp;quot; data type, was used in SourceHook v4.4 and lower.  This syntax was deprecated in v4.5 and completely removed in v5.0.  Upgrading from SourceHook v4.4 means that code referencing &amp;lt;tt&amp;gt;SH_GET_CALLCLASS&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SH_REMOVE_CALLCLASS&amp;lt;/tt&amp;gt; must be removed, and &amp;lt;tt&amp;gt;SH_CALL&amp;lt;/tt&amp;gt; simply needs an instance pointer instead.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Other Macros=&lt;br /&gt;
SourceHook contains a large variety of extra macros.  This section is a grab bag of the more commonly used ones.&lt;br /&gt;
&lt;br /&gt;
==Interface Pointers from Hooks==&lt;br /&gt;
Let's say you have the following hook:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;class Player&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void TakeDamage(int damage);&lt;br /&gt;
   float GetDamageModifier();&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
void Hook_TakeDamage(int damage);&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
How can you get the &amp;lt;tt&amp;gt;Player&amp;lt;/tt&amp;gt; instance while in the hook?  This can be achieved via the &amp;lt;tt&amp;gt;META_IFACEPTR&amp;lt;/tt&amp;gt; macro.  Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;void Hook_TakeDamage(int damage)&lt;br /&gt;
{&lt;br /&gt;
   Player *pPlayer = META_IFACEPTR(Player);&lt;br /&gt;
&lt;br /&gt;
   int new_damage = (int)((pPlayer-&amp;gt;GetDamageModifier() + 0.3) * (float)damage);&lt;br /&gt;
&lt;br /&gt;
   RETURN_META_NEWPARAMS(MRES_IGNORED, &amp;amp;Player::TakeDamage, (new_damage));&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the class name should be passed to &amp;lt;tt&amp;gt;META_IFACEPTR&amp;lt;/tt&amp;gt;, not the pointer type.&lt;br /&gt;
&lt;br /&gt;
==Ignoring Reference Returns==&lt;br /&gt;
There is a special macro, &amp;lt;tt&amp;gt;RETURN_META_NOREF&amp;lt;/tt&amp;gt;, for ignoring a return value for reference-returning functions.  Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class ISomething&lt;br /&gt;
{&lt;br /&gt;
public:  &lt;br /&gt;
   virtual int &amp;amp; GetSomething() =0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int &amp;amp; Hook_GetSomething()&lt;br /&gt;
{&lt;br /&gt;
   RETURN_META_NOREF(MRES_IGNORED, int &amp;amp;);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Automatic hookmanager generation=&lt;br /&gt;
Normally, the SH_DECL_ macros generate a so-called &amp;quot;hook manager&amp;quot;, a function which is invoked instead of the original function and then calls the hooks and processes their return and &amp;lt;tt&amp;gt;META_RES&amp;lt;/tt&amp;gt; values.&lt;br /&gt;
&lt;br /&gt;
It is also possible to let SourceHook auto-generate the hook manager. This is neccessary if the function prototype is unknown at compile time (for example if hooks can be defined from third-party plugins of your plugin).&lt;br /&gt;
&lt;br /&gt;
Example Usage from a Metamod:Source plugin:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;quot;sourcehook_pibuilder.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// We want to hook a void (int, float) function&lt;br /&gt;
&lt;br /&gt;
// Request IHookManagerAutoGen interface&lt;br /&gt;
SourceHook::IHookManagerAutoGen *hmag =&lt;br /&gt;
    static_cast&amp;lt;SourceHook::IHookManagerAutoGen *&amp;gt;(ismm-&amp;gt;MetaFactory(MMIFACE_SH_HOOKMANAUTOGEN, NULL, NULL));&lt;br /&gt;
&lt;br /&gt;
// (check for hmag == NULL)&lt;br /&gt;
&lt;br /&gt;
// Build prototype information (using CProtoInfoBuilder helper class).&lt;br /&gt;
SourceHook::CProtoInfoBuilder protoInfo(SourceHook::ProtoInfo::CallConv_ThisCall);&lt;br /&gt;
protoInfo.AddParam(sizeof(int), SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal,&lt;br /&gt;
    NULL, NULL, NULL, NULL);&lt;br /&gt;
protoInfo.AddParam(sizeof(float), SourceHook::PassInfo::PassType_Float, SourceHook::PassInfo::PassFlag_ByVal,&lt;br /&gt;
    NULL, NULL, NULL, NULL);&lt;br /&gt;
&lt;br /&gt;
// Generate the hook manager&lt;br /&gt;
HookManagerPubFunc generatedHookMan = hmag-&amp;gt;MakeHookMan(protoInfo, 0 /* vtable offset */, 0 /* vtable index */);&lt;br /&gt;
&lt;br /&gt;
// Add the hook&lt;br /&gt;
int hookid = g_SHPtr-&amp;gt;AddHook(g_PLID, SourceHook::ISourceHook::Hook_Normal/Hook_VP/Hook_DVP, iface_ptr, thisptr_offs,&lt;br /&gt;
    generatedHookMan, handler, post);&lt;br /&gt;
&lt;br /&gt;
// ... (use the hook)&lt;br /&gt;
&lt;br /&gt;
// After you're done using the hook (cleanup)&lt;br /&gt;
// Remove the hook&lt;br /&gt;
g_SHPtr-&amp;gt;RemoveHookByID(hookid);&lt;br /&gt;
&lt;br /&gt;
// Release hook manager&lt;br /&gt;
hmag-&amp;gt;ReleaseHookMan(generatedHookMan);&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;CProtoInfoBuilder::AddParam&amp;lt;/tt&amp;gt; has 7 parameters:&lt;br /&gt;
* size: size of the type. This is sizeof(type) even if it is passed by reference!&lt;br /&gt;
* passtype: this can be PassType_Basic for integer types (char/short/int/...), PassType_Float for floating-point types (float/double) and PassType_Object for unions, structs and classes.&lt;br /&gt;
* passflags: flags. Has to contain either PassFlag_ByVal or PassFlag_ByRef.&lt;br /&gt;
* pNormalCtor: for PassType_Object, set this to the pointer to the user-defined default constructor of the object, if it has one.&lt;br /&gt;
* pCCtor: for PassType_Object, set this to the pointer to the user-defined copy constructor of the object, if it has one.&lt;br /&gt;
* pODtor: for PassType_Object, set this to the pointer to the user-defined destructor of the object, if it has one.&lt;br /&gt;
* pAssignOperator: for PassType_Object, set this to the pointer to the user-defined assignment operator of the object, if it has one.&lt;br /&gt;
&lt;br /&gt;
If you are hooking a non-void function, also call &amp;lt;tt&amp;gt;CProtoInfoBuilder::SetReturnType&amp;lt;/tt&amp;gt;. It has the same arguments as &amp;lt;tt&amp;gt;AddParam&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;handler&amp;lt;/tt&amp;gt; parameter of &amp;lt;tt&amp;gt;ISourceHook::AddHook&amp;lt;/tt&amp;gt; is a pointer to the ISHDelegate interface.&lt;br /&gt;
In C++, you construct ISHDelegates like this:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class MyDelegate : public SourceHook::ISHDelegate&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
    // vtable index 0&lt;br /&gt;
    virtual bool IsEqual(ISHDelegate *pOtherDeleg)&lt;br /&gt;
    {&lt;br /&gt;
        // pOtherDeleg is guaranteed to be from the same plugin.&lt;br /&gt;
        // This function is only used for compat with the old SH_REMOVE_HOOK method.&lt;br /&gt;
        // if you don't want to use that with your hooks, you can simply return false here.&lt;br /&gt;
        // if for some reason you need it, a good idea could be comparing the vtable pointer:&lt;br /&gt;
        return *reinterpret_cast&amp;lt;void**&amp;gt;(this) == *reinterpret_cast&amp;lt;void**&amp;gt;(pOtherDeleg);&lt;br /&gt;
&lt;br /&gt;
        // But in general I'd just return false!&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // vtable index 1&lt;br /&gt;
    virtual void DeleteThis()&lt;br /&gt;
    {&lt;br /&gt;
        delete this;   // Called from SourceHook when this instance is not needed&lt;br /&gt;
                       // and should be deleted.&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // vtable index 2&lt;br /&gt;
    virtual ret_type Call(params)&lt;br /&gt;
    {&lt;br /&gt;
        // your code.&lt;br /&gt;
        // SH_DECL_ macros pass execution to the actual user's handler through a FastDelegate&lt;br /&gt;
        // which is stored as a member variable of the delegate class.&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first parameter of the CProtoInfoBuilder constructor (see example code above) is the calling convention in an extended sense. At the moment it can be either CallConv_ThisCall or (CallConv_ThisCall | CallConv_HasVafmt). The second value means that the function has printf-like string formatting. Then, the finaly ''const char *, ...'' arguments will be added automatically, and the Deleagte::Call method should have one more parameter: ''const char *formattedString''.&lt;br /&gt;
&lt;br /&gt;
pNormalCtor/pCCtor/pODtor/pAssignOperator should be found using offsets / sigscanning. If you are a C++ plugin and know the type at compile time, you can also use the following class:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
// Address of constructor/destructor&lt;br /&gt;
// (using wrappers)&lt;br /&gt;
template &amp;lt;class T&amp;gt;&lt;br /&gt;
class Ctor_Thunk&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
	void NormalConstructor()&lt;br /&gt;
	{&lt;br /&gt;
		new(this) T;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	void CopyConstructor(const T &amp;amp;other)&lt;br /&gt;
	{&lt;br /&gt;
		new(this) T(other);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	void Destructor()&lt;br /&gt;
	{&lt;br /&gt;
		reinterpret_cast&amp;lt;T*&amp;gt;(this)-&amp;gt;~T();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	const T&amp;amp; AssignOp(const T &amp;amp;other)&lt;br /&gt;
	{&lt;br /&gt;
		return (*reinterpret_cast&amp;lt;T*&amp;gt;(this) = other);&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
template &amp;lt;class T&amp;gt;&lt;br /&gt;
void *FindFuncAddr(T mfp)&lt;br /&gt;
{&lt;br /&gt;
	union&lt;br /&gt;
	{&lt;br /&gt;
		T a;&lt;br /&gt;
		void *b;&lt;br /&gt;
	} u;&lt;br /&gt;
	u.a = mfp;&lt;br /&gt;
	return u.b;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Usage:&lt;br /&gt;
FindFuncAddr(&amp;amp;Ctor_Thunk&amp;lt;type&amp;gt;::NormalConstructor)&lt;br /&gt;
// (if the type is a reference type, use it without &amp;amp; here)&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Metamod:Source Development]]&lt;br /&gt;
[[Category:SourceHook]]&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=SourceHook_Standalone&amp;diff=11710</id>
		<title>SourceHook Standalone</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=SourceHook_Standalone&amp;diff=11710"/>
		<updated>2024-06-12T22:47:30Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Created page with &amp;quot;SourceHook can be embedded and run standalone of Metamod if you want to integrate it into another platform.  SourceHook independent of metamod is a lightweight and powerful in...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;SourceHook can be embedded and run standalone of Metamod if you want to integrate it into another platform. &lt;br /&gt;
SourceHook independent of metamod is a lightweight and powerful instrumentation library for polymorphic C++ classes, and comes with many features needed to implement your own C++ modding platform out-of-the-box.&lt;br /&gt;
&lt;br /&gt;
To make sure SourceHook's conflict resolution is able to run unimpeded, you need to make sure only one instance of SourceHook exists in the entire process!&lt;br /&gt;
Once the global SourceHook implementation has been created, you can pass the &amp;lt;tt&amp;gt;ISourceHook&amp;lt;/tt&amp;gt; pointer around to allow plugins to interface with SourceHook.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
Each hook has an associated &amp;lt;tt&amp;gt;g_PLID&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;PluginId&amp;lt;/tt&amp;gt; that groups hooks from the same plugin together. &lt;br /&gt;
The g_PLID doesn't need to be anything particularly; SourceHook doesn't care, it's just sugar that allows you to de-register, pause, and unpause entire plugins remotely.&lt;br /&gt;
&lt;br /&gt;
In all consuming plugins, g_PLID should be provided and tracked by whatever management code you have, and &amp;lt;tt&amp;gt;ISourceHook::UnloadPlugin&amp;lt;/tt&amp;gt; should be called with the corresponding PluginId when a plugin is being unloaded.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
To instantiate the SourceHook engine, you must create a &amp;lt;tt&amp;gt;CSourceHookImpl&amp;lt;/tt&amp;gt; instance.  Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
/* Normally, just &amp;lt;sourcehook.h&amp;gt; is included, but this is needed to instantiate the engine. */&lt;br /&gt;
#include &amp;lt;sourcehook/sourcehook_impl.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
SourceHook::Impl::CSourceHookImpl g_SourceHook;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To actually use SourceHook, it is necessary to have two global variables:&lt;br /&gt;
*&amp;lt;tt&amp;gt;g_PLID&amp;lt;/tt&amp;gt; - A unique integer that identifies the library using SourceHook.  This is used for removing all hooks a library is using.&lt;br /&gt;
*&amp;lt;tt&amp;gt;g_SHPtr&amp;lt;/tt&amp;gt; - A pointer to the &amp;lt;tt&amp;gt;SourceHook::ISourceHook&amp;lt;/tt&amp;gt; interface.&lt;br /&gt;
&lt;br /&gt;
Example header file:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;sourcehook/sourcehook.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern SourceHook::ISourceHook *g_SHPtr;&lt;br /&gt;
extern int g_PLID;&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example addition to the global code:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
SourceHook::ISourceHook *g_SHPtr = &amp;amp;g_SourceHook;&lt;br /&gt;
int g_PLID = 0;&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiple Libraries/Shared Hooks==&lt;br /&gt;
If SourceHook is going to be used across multiple libraries in the same process, it is essential that only one instance of SourceHook be present.  Of course, that is only logical, since otherwise the instances would be replacing each other's virtual patches.&lt;br /&gt;
&lt;br /&gt;
In order to support this, each separate library must be given the &amp;lt;tt&amp;gt;ISourceHook&amp;lt;/tt&amp;gt; pointer and a unique &amp;lt;tt&amp;gt;g_PLID&amp;lt;/tt&amp;gt; value.  &amp;lt;tt&amp;gt;CSourceHookImpl&amp;lt;/tt&amp;gt; provides a few useful functions for managing hooks on &amp;quot;child&amp;quot; libraries or otherwise linked code.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tt&amp;gt;PausePlugin()&amp;lt;/tt&amp;gt; - Silences any hooks from an ID, such that those hooks will not be called.&lt;br /&gt;
*&amp;lt;tt&amp;gt;UnpausePlugin()&amp;lt;/tt&amp;gt; - Un-silences any silenced hooks from an ID.&lt;br /&gt;
*&amp;lt;tt&amp;gt;UnloadPlugin()&amp;lt;/tt&amp;gt; - Clean-up any left-over hooks from an ID.&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceHook]]&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=SourceHook&amp;diff=11709</id>
		<title>SourceHook</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=SourceHook&amp;diff=11709"/>
		<updated>2024-06-12T22:38:44Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Expand!&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Stub}}&lt;br /&gt;
&lt;br /&gt;
SourceHook is a versatile library for hooking virtual functions. SourceHook was designed for declaring single hooks against a given virtual function and a specific &amp;lt;tt&amp;gt;&amp;lt;i&amp;gt;this&amp;lt;/i&amp;gt;&amp;lt;/tt&amp;gt; pointer.&lt;br /&gt;
&lt;br /&gt;
For more information about SourceHook's features and API, see [[SourceHook Development]].&lt;br /&gt;
&lt;br /&gt;
== Mechanism ==&lt;br /&gt;
&lt;br /&gt;
SourceHook replaces methods within a class's virtual table to redirect execution to SourceHook itself.&lt;br /&gt;
Virtual hooking is comparatively simple compared to detours; all a hooking library needs to do is ensure ABI compatibility with the method being swapped. Detours, on the other hand, require disassembling the first block of a subroutine to generate a trampoline that executes the original code!&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
Compatibility for arguments is fairly trivial--you just need to have the right type and pointer type (eg, lvalue ref, rvalue ref, pointer, pass-by-value...)&lt;br /&gt;
&lt;br /&gt;
For return types, it gets a bit tricky. For 64-bit support, you need to make sure that your return type exactly matches the type in the game, or else different code could be emitted by your compiler that is incompatible with the game.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
SourceHook is split into two parts: the '''implementation''' (within metamod itself) and the '''hook manager''' (within your plugin!)&lt;br /&gt;
The implementation keeps track of all plugins that are trying to hook a particular method, and the hook manager is responsible for calling each plugin's hook.&lt;br /&gt;
Your plugin's SourceHook macros or templates create a hook manager for the method being hooked, and this hook manager directly replaces the original implementation in the virtual table.&lt;br /&gt;
&lt;br /&gt;
Only one plugin's hook manager is used. When there are multiple, SourceHook picks the first one, prioritizing newer hook manager version numbers for compatibility.&lt;br /&gt;
Even if an old plugin that no longer supports the current SourceHook implementation is running on the system, as long as a newer hook manager exists SourceHook will use it instead, providing fairly remarkable compatibility. (The plugins themselves, on the other hand...)&lt;br /&gt;
&lt;br /&gt;
This also means if even one hook manager is out of date and no longer has ABI compatibility with the original, then crashes could occur.&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceHook]]&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Category:Metamod:Source_Development&amp;diff=11708</id>
		<title>Category:Metamod:Source Development</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Category:Metamod:Source_Development&amp;diff=11708"/>
		<updated>2024-06-12T22:26:11Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ForDevelopers|Metamod}}&lt;br /&gt;
&lt;br /&gt;
Need help?  Join #sourcemod or #metamod on irc.gamesurge.net, or post on the [http://forums.alliedmods.net/forumdisplay.php?f=75 forums].&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;b&amp;gt;Documentation&amp;lt;/b&amp;gt;&lt;br /&gt;
**[[Metamod:Source Environment|Setting up your Environment]]&lt;br /&gt;
**[[Metamod:Source Development|Overview of Writing Metamod:Source Plugins]]&lt;br /&gt;
**[[Sample Plugins (Metamod:Source)|Example Plugins]]&lt;br /&gt;
**[[SourceHook Development|SourceHook Overview]]&lt;br /&gt;
**[[Metamod:Source VDF Files]]&lt;br /&gt;
**[http://www.metamodsource.net/dox/ Metamod:Source 1.6.0 API]&lt;br /&gt;
**[http://www.metamodsource.net/dox-1.4.3/ Metamod:Source 1.4.3 API]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;b&amp;gt;Compatibility/Porting&amp;lt;/b&amp;gt;&lt;br /&gt;
**[[MM:S API Differences]] (Explains &amp;lt;tt&amp;gt;core&amp;lt;/tt&amp;gt; versus &amp;lt;tt&amp;gt;core-legacy&amp;lt;/tt&amp;gt;)&lt;br /&gt;
**[[Porting to Orange Box]]&lt;br /&gt;
**[[Porting to Left 4 Dead]]&lt;br /&gt;
**[[Porting to Swarm and CSGO]]&lt;br /&gt;
**[[Gameinfo Deprecation]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;b&amp;gt;Half-Life 2 Resources&amp;lt;/b&amp;gt;&lt;br /&gt;
**[[Virtual Offsets (Source Mods)]]&lt;br /&gt;
**[[Game Events (Source)]]&lt;br /&gt;
**[[Signature Scanning]]&lt;br /&gt;
**[[:Category:SourceMod Development]]&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Template:ForDevelopers&amp;diff=11707</id>
		<title>Template:ForDevelopers</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Template:ForDevelopers&amp;diff=11707"/>
		<updated>2024-06-12T22:25:41Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Created page with &amp;quot;&amp;lt;div style=&amp;quot;padding: 0.75em 1.5em; border-width: 2px; border-color: LightSeaGreen; border-style:solid; background-color: Azure; max-width: 60rem;&amp;quot;&amp;gt; File:Silly goose.png|fram...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;padding: 0.75em 1.5em; border-width: 2px; border-color: LightSeaGreen; border-style:solid; background-color: Azure; max-width: 60rem;&amp;quot;&amp;gt;&lt;br /&gt;
[[File:Silly goose.png|frameless|64px|left|link=|alt=]]&lt;br /&gt;
&amp;lt;b style=&amp;quot;font-size: 20px&amp;quot;&amp;gt;&lt;br /&gt;
For Developers &amp;amp; Modders&lt;br /&gt;
&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
This page is geared towards helping developers learn how to create and modify {{{1|SourceMod}}} plugins.&lt;br /&gt;
To learn how to install and manage {{{1|SourceMod}}} itself, check out the '''documentation''' categories for system-administrator geared articles.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Category:Metamod:Source_Documentation&amp;diff=11706</id>
		<title>Category:Metamod:Source Documentation</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Category:Metamod:Source_Documentation&amp;diff=11706"/>
		<updated>2024-06-12T22:22:13Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Add &amp;quot;for sysadmins&amp;quot; banner&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ForSysadmins|Metamod}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;b&amp;gt;Installation and Setup&amp;lt;/b&amp;gt;&lt;br /&gt;
**[[Installing Metamod:Source]]&lt;br /&gt;
**[[Configuring Metamod:Source]]&lt;br /&gt;
*&amp;lt;b&amp;gt;Usage&amp;lt;/b&amp;gt;&lt;br /&gt;
**[[Console Commands (Metamod:Source)|Console Commands]]&lt;br /&gt;
**[[:Category:Metamod:Source Development|Development]]&lt;br /&gt;
*&amp;lt;b&amp;gt;Information&amp;lt;/b&amp;gt;&lt;br /&gt;
**[[Gameinfo Deprecation]]&lt;br /&gt;
**[[Metamod:Source VDF Files]]&lt;br /&gt;
**[[Supported Games (Metamod:Source)|Supported Games]]&lt;br /&gt;
**[[Frequently Asked Questions (Metamod:Source)|FAQ]]&lt;br /&gt;
**[[Open Source Plugins for Metamod:Source|Open Source Plugins]]&lt;br /&gt;
*&amp;lt;b&amp;gt;Development&amp;lt;/b&amp;gt;&lt;br /&gt;
**[[:Category:Metamod:Source Development|Metamod:Source Development]]&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Template:ForSysadmins&amp;diff=11705</id>
		<title>Template:ForSysadmins</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Template:ForSysadmins&amp;diff=11705"/>
		<updated>2024-06-12T22:21:15Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Created page with &amp;quot;&amp;lt;div style=&amp;quot;padding: 0.75em 1.5em; border-width: 2px; border-color: LightPink; border-style:solid; background-color: MistyRose; max-width: 60rem;&amp;quot;&amp;gt; File:FlorkSunglasses.png|...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;padding: 0.75em 1.5em; border-width: 2px; border-color: LightPink; border-style:solid; background-color: MistyRose; max-width: 60rem;&amp;quot;&amp;gt;&lt;br /&gt;
[[File:FlorkSunglasses.png|frameless|64px|left|link=|alt=]]&lt;br /&gt;
&amp;lt;b style=&amp;quot;font-size: 20px&amp;quot;&amp;gt;&lt;br /&gt;
For System Administrators&lt;br /&gt;
&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
This page is geared towards helping a sysadmin install, manage, and maintain a {{{1|SourceMod}}} installation.&lt;br /&gt;
If you're looking to create, develop, or modify {{{1|SourceMod}}} plugins, check out the '''development''' pages for relevant documentation.&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=File:FlorkSunglasses.png&amp;diff=11704</id>
		<title>File:FlorkSunglasses.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=File:FlorkSunglasses.png&amp;diff=11704"/>
		<updated>2024-06-12T22:13:41Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Flork wearing some sunglasses. This is used to spice up templates and add some flair

'''This image is licensed under the Emotes.gg Basic License: https://emoji.gg/licenses'''&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
Flork wearing some sunglasses. This is used to spice up templates and add some flair&lt;br /&gt;
&lt;br /&gt;
'''This image is licensed under the Emotes.gg Basic License: https://emoji.gg/licenses'''&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=SourceHook_Development&amp;diff=11703</id>
		<title>SourceHook Development</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=SourceHook_Development&amp;diff=11703"/>
		<updated>2024-06-12T22:10:26Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Recategorize&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;SourceHook is a powerful API (Application Programming Interface) for detouring (hooking) virtual functions.  Unlike static detours, SourceHook needs only to swap addresses in and out of an object's virtual table.  This makes it fast and generally very platform-safe.&lt;br /&gt;
&lt;br /&gt;
SourceHook is coupled with Don Clugston's [http://www.codeproject.com/cpp/FastDelegate.asp FastDelegate] headers.  Virtual hooks can be detoured to any static function of the same prototype, or any member function (of any class) as long as the prototype matches.&lt;br /&gt;
&lt;br /&gt;
All code in SourceHook is part of the SourceHook namespace.  Thus, it may be prudent to declare this before using SourceHook structures or types:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;using namespace SourceHook;&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Simple Hooks=&lt;br /&gt;
SourceHook has the following steps of operation:&lt;br /&gt;
&lt;br /&gt;
* Declare the prototype of the function you are going to hook. This generates compile-time code that is able to pinpoint exactly how to go about hooking the function.&lt;br /&gt;
* Hook the function - as a member function of another class or a regular static function.&lt;br /&gt;
* Before the hooked function is called, all of the &amp;quot;pre&amp;quot; hook handlers attached to it are called. Each hook can set a special flag, the highest of which is chosen as a final operation. This flag specifies whether the original function should be called or not.&lt;br /&gt;
* Once all the hooks have been called, SourceHook decides whether to call the original function. Another set of hooks are called directly after, called &amp;quot;post&amp;quot; hook handlers. You can specify whether each hook is a post or pre hook - it simply changes whether it's called before or after the original call is made.&lt;br /&gt;
* After you are done using a hook, you must safely remove it before the object is destroyed (otherwise, memory will be leaked).&lt;br /&gt;
&lt;br /&gt;
==Declaration==&lt;br /&gt;
As an example, take the following class prototype:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class IVEngineServer&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   /*...*/&lt;br /&gt;
   virtual void LogPrint( const char *msg ) = 0;&lt;br /&gt;
   virtual bool IsDedicated() = 0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
extern IVEngineServer *engine;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The first step is to figure out how to declare its prototype to SourceHook. This function is void, and has one parameter. The declaration macro follows these formats:&lt;br /&gt;
&lt;br /&gt;
*{{bcode|SH_DECL_HOOK}}n - n is the number of parameters&lt;br /&gt;
**The parameters are: Class name, member function name, attributes, overloaded?, the return type, and a list of the parameter types.&lt;br /&gt;
*{{bcode|SH_DECL_HOOKn_void}} - n is the number of parameters&lt;br /&gt;
**_void specifies that the function does not return a value. The format is the same as above except the &amp;quot;return type&amp;quot; parameter is missing.&lt;br /&gt;
*'''Note:''' Not covered here are the SH_DECL_HOOKn[_void]_vafmt hooks. These can hook string-formattable variable argument lists. You do not pass the string format or ellipses parameter. SourceHook will automatically format the string for your hook.&lt;br /&gt;
&lt;br /&gt;
Our macro will look like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SH_DECL_HOOK1_void(IVEngineServer, LogPrint, SH_NOATTRIB, 0, const char *);&lt;br /&gt;
SH_DECL_HOOK0(IVEngineServer, IsDedicated, SH_NOATTRIB, 0, bool);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Broken down for the first line:&lt;br /&gt;
*There is 1 parameter.&lt;br /&gt;
*The function has no return value.&lt;br /&gt;
*&amp;lt;tt&amp;gt;IVEngineServer&amp;lt;/tt&amp;gt; is the class containing the function.&lt;br /&gt;
*&amp;lt;tt&amp;gt;LogPrint&amp;lt;/tt&amp;gt; is the function being hooked.&lt;br /&gt;
*The function as no attributes (for example, it is not const).&lt;br /&gt;
*The function is not overloaded.&lt;br /&gt;
*The first (and only) argument is a &amp;lt;tt&amp;gt;const char *&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second line is similar, except the parameter immediately after the overload parameter specifies the return type.  There are no further parameters since it was declared with 0.&lt;br /&gt;
&lt;br /&gt;
==Getting an Interface Instance==&lt;br /&gt;
&lt;br /&gt;
Before you can use an interface, you need to retrieve an instance of it.  This is done with either the &amp;lt;tt&amp;gt;GET_V_IFACE_ANY&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;GET_V_IFACE_CURRENT&amp;lt;/tt&amp;gt; macros.  Both take the same arguments.  &amp;lt;tt&amp;gt;GET_V_IFACE_CURRENT&amp;lt;/tt&amp;gt; is recommended if it works.  &amp;lt;tt&amp;gt;GET_V_IFACE_ANY&amp;lt;/tt&amp;gt; should also work, but may be missing newer functionality.&lt;br /&gt;
&lt;br /&gt;
Normally this initialization needs to be done when your MM:S plugin or SourceMod Extension starts.&lt;br /&gt;
&lt;br /&gt;
You also need to know which factory produces the interface you need.  There are only 4 factories: &amp;lt;tt&amp;gt;GetEngineFactory&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;GetServerFactory&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;GetPhysicsFactory&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;GetFilesystemFactory&amp;lt;/tt&amp;gt;.  Normally you'll want Engine or Server.&lt;br /&gt;
&lt;br /&gt;
You'll also need to know the constant that the game uses for that particular class.  This is usually found in the hl2sdk for your game.  In the case of &amp;lt;tt&amp;gt;IVEngineServer&amp;lt;/tt&amp;gt;, this is &amp;lt;tt&amp;gt;INTERFACEVERSION_VENGINESERVER&amp;lt;/tt&amp;gt; located in public/eiface.h.&lt;br /&gt;
&lt;br /&gt;
So, to retrieve the Interface so you can do something with it, it'd look something like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
IVEngineServer *engine;&lt;br /&gt;
&lt;br /&gt;
// For SourceMod, use the first signature&lt;br /&gt;
//bool MyExtension::OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)&lt;br /&gt;
bool MyPlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late)&lt;br /&gt;
{&lt;br /&gt;
    GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The error and maxlen arguments '''must''' be named error and maxlen respectively, or else certain macros will fail.&lt;br /&gt;
&lt;br /&gt;
Note that MyPlugin should be replaced with your plugin's class.&lt;br /&gt;
&lt;br /&gt;
==Hook Functions==&lt;br /&gt;
Hooks can be declared either ''pre'' or ''post''.  A ''pre'' hook will intercept the original function before it is called.  Pre-hooks can return one of four ''hook actions'':&lt;br /&gt;
*&amp;lt;tt&amp;gt;MRES_IGNORED&amp;lt;/tt&amp;gt; - The original function will be called.&lt;br /&gt;
*&amp;lt;tt&amp;gt;MRES_HANDLED&amp;lt;/tt&amp;gt; - Same as &amp;lt;tt&amp;gt;MRES_IGNORED&amp;lt;/tt&amp;gt;, except subsequent hooks can assume this means something important was changed.&lt;br /&gt;
*&amp;lt;tt&amp;gt;MRES_OVERRIDE&amp;lt;/tt&amp;gt; - The original function will be called, but the new return value will be used instead of the one from the original function.&lt;br /&gt;
*&amp;lt;tt&amp;gt;MRES_SUPERCEDE&amp;lt;/tt&amp;gt; - The original function will not be called.  The new return value (if any) will be used instead.&lt;br /&gt;
&lt;br /&gt;
These enum constants are defined in &amp;lt;tt&amp;gt;&amp;lt;sourcehook.h&amp;gt;&amp;lt;/tt&amp;gt;, and are made available to Metamod:Source plugin developers via &amp;lt;tt&amp;gt;&amp;lt;ISmmPlugin.h&amp;gt;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Once all pre-hooks have been processed, SourceHook takes an action based on the &amp;quot;highest&amp;quot; hook action returned (&amp;lt;tt&amp;gt;MRES_IGNORED&amp;lt;/tt&amp;gt; being lowest, &amp;lt;tt&amp;gt;MRES_SUPERCEDE&amp;lt;/tt&amp;gt; being highest).  Once the action has been processed, all ''post'' hooks are called.  That is to say, even if the original function is never called, post hooks are still processed.  Because a post hook as no chance at true interception, it is important to realize that depending on the information being detoured, the data may be modified or destroyed.  Similarly, a post hook's returned action and value is ignored.&lt;br /&gt;
&lt;br /&gt;
A hook's action is signalled via one of two macros:&lt;br /&gt;
*&amp;lt;tt&amp;gt;RETURN_META&amp;lt;/tt&amp;gt; - Only usable from &amp;lt;tt&amp;gt;void&amp;lt;/tt&amp;gt; functions.  Signals the action to take, then returns.&lt;br /&gt;
*&amp;lt;tt&amp;gt;RETURN_META_VALUE&amp;lt;/tt&amp;gt; - Only usable from non-&amp;lt;tt&amp;gt;void&amp;lt;/tt&amp;gt; functions.  Signals the action to take, then returns the supplied value.&lt;br /&gt;
&lt;br /&gt;
There are two methods of adding or removing hooks.  Hooks can be bound to '''static''' or '''member''' functions.  Both have a similar syntax.  Their macros are:&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_STATIC(Function)&amp;lt;/tt&amp;gt; - Hook to a static function.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_MEMBER(Instance, Function)&amp;lt;/tt&amp;gt; - Hook to a member function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;It is important to realize that a simple hook will only be invoked when used on the same instance.&amp;lt;/b&amp;gt;  That is to say, if there are 500 instances of object X, and a hook is added to function X::Y in instance #8, then the hook will only be invoked from instance #8.  &amp;lt;b&amp;gt;Multiple hooks can be declared on the same instance, and multiple instances can be bound to the same hook, but one hook will only be invoked for the instances it was hooked to.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To have hooks that work across all instances, and thus do not need to be delegated per-instance, see the &amp;quot;Global Hooks&amp;quot; section.  As of SourceHook v5, it is safe to remove hooks on a destroyed instance, as the instance is not actually dereferenced.  However, its virtual table must still be accessible.&lt;br /&gt;
&lt;br /&gt;
==Adding Hooks==&lt;br /&gt;
The macro to add hooks is &amp;lt;tt&amp;gt;SH_[ADD|REMOVE]_HOOK&amp;lt;/tt&amp;gt;.  The syntax is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_[ADD|REMOVE]_HOOK(Interface, Function, Instance, Hook, [post? true,false])&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example of adding a &amp;lt;tt&amp;gt;LogPrint&amp;lt;/tt&amp;gt; hook:&lt;br /&gt;
&amp;lt;cpp&amp;gt;void Hook_LogPrint(const char *msg)&lt;br /&gt;
{&lt;br /&gt;
   if (strcmp(msg, &amp;quot;If this string matches the function will be blocked&amp;quot;) == 0)&lt;br /&gt;
   {&lt;br /&gt;
      RETURN_META(MRES_SUPERCEDE);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /* Not needed, but good style */&lt;br /&gt;
   RETURN_META(MRES_IGNORED);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StartHooks()&lt;br /&gt;
{&lt;br /&gt;
   log_hook = SH_ADD_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(Hook_LogPrint), false);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StopHooks()&lt;br /&gt;
{&lt;br /&gt;
   SH_REMOVE_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(Hook_LogPrint), false);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax is similar for hooking to member functions.  Example equivalent to the above:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class MyHooks&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   void Hook_LogPrint(const char *msg)&lt;br /&gt;
   {&lt;br /&gt;
      if (strcmp(msg, &amp;quot;If this string matches the function will be blocked&amp;quot;) == 0)&lt;br /&gt;
      {&lt;br /&gt;
         RETURN_META(MRES_SUPERCEDE);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      /* Not needed, but good style */&lt;br /&gt;
      RETURN_META(MRES_IGNORED);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   void StartHooks()&lt;br /&gt;
   {&lt;br /&gt;
      SH_ADD_HOOK(IVEngineServer, LogPrint, engine, SH_MEMBER(this, &amp;amp;MyHooks::Hook_LogPrint), false);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   void StopHooks()&lt;br /&gt;
   {&lt;br /&gt;
      SH_REMOVE_HOOK(IVEngineServer, LogPrint, engine, SH_MEMBER(this, &amp;amp;MyHooks::Hook_LogPrint), false);&lt;br /&gt;
   }&lt;br /&gt;
};&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Manual Hooks=&lt;br /&gt;
In some cases, it may be necessary to support multiple, incompatible ABI branches of an interface.  For example, suppose you need to hook an application that may supply either version of these interfaces:&lt;br /&gt;
&lt;br /&gt;
Interface v1:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class Interface&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void Function1() =0;&lt;br /&gt;
   virtual bool Function2(int clam) =0;&lt;br /&gt;
};&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Interface v2:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class Interface&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual bool Function2(int clam) =0;&lt;br /&gt;
};&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Obviously, these two interfaces are backwards incompatible.  Manual hooks allow you to precisely define the structure of the virtual table, bypassing the compiler's rules.  These rules can be re-configured at runtime.&lt;br /&gt;
&lt;br /&gt;
==Declaration==&lt;br /&gt;
Declaring a manual hook is similar to declaring a normal/simple hook.  The syntax is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_DECL_MANUALHOOK&amp;lt;n&amp;gt;[_void](UniqueName, vtblIndex, vtblOffs, thisOffs, [return and param types])&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;UniqueName&amp;lt;/tt&amp;gt; is a unique identifier for the hook.  The &amp;lt;tt&amp;gt;vtblIndex&amp;lt;/tt&amp;gt; is the index into the virtual table at which the function lies.  In most compilers, this index starts from 0.  The &amp;lt;tt&amp;gt;vtblOffs&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;thisOffs&amp;lt;/tt&amp;gt; fields are used for multiple inheritance and are almost always 0 in modern compiler single inheritance.&lt;br /&gt;
&lt;br /&gt;
An example of hooking the two functions from the first interface version:&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_DECL_MANUALHOOK0_void(MHook_Function1, 0, 0, 0);&lt;br /&gt;
SH_DECL_MANUALHOOK1(MHook_Function2, 1, 0, 0, bool, int);&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Reconfiguring==&lt;br /&gt;
A manual hook can be ''reconfigured'', which will update its set offsets.  Reconfiguration automatically removes all hooks on the manual hook.  Let's say we want to reconfigure the &amp;lt;tt&amp;gt;Function2&amp;lt;/tt&amp;gt; hook in the case of the second version being detected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
void SwitchToNewerHooks()&lt;br /&gt;
{&lt;br /&gt;
   SH_MANUALHOOK_RECONFIGURE(MHook_Function2, 0, 0, 0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the hook was referenced by its unique identifier.&lt;br /&gt;
&lt;br /&gt;
==Adding Hooks==&lt;br /&gt;
Adding or removing hook binds is done via the following extra macros:&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_ADD_MANUALHOOK&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_REMOVE_MANUALHOOK&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These work similar to the original functions.  Example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;extern Interface *iface;&lt;br /&gt;
&lt;br /&gt;
bool Hook_Function2(int clam)&lt;br /&gt;
{&lt;br /&gt;
   RETURN_META_VALUE(MRES_IGNORED, false);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StartHooks()&lt;br /&gt;
{&lt;br /&gt;
   SH_ADD_MANUALHOOK(MHook_Function2, iface, SH_STATIC(Hook_Function2), false);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StopHooks()&lt;br /&gt;
{&lt;br /&gt;
   SH_REMOVE_MANUALHOOK(MHook_Function2, iface, SH_STATIC(Hook_Function2), false);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, a member function version would use &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt; instead.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Extended Removal Syntax=&lt;br /&gt;
The syntax described in the above sections is new as of SourceHook v4.5.  &amp;lt;tt&amp;gt;SH_REMOVE_HOOK&amp;lt;/tt&amp;gt; is, for all intents and purposes, optional.  There is another way to remove hooks.&lt;br /&gt;
&lt;br /&gt;
Each &amp;lt;tt&amp;gt;SH_ADD&amp;lt;/tt&amp;gt; macro returns a non-zero &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt; on success.  The same integer can be passed to the &amp;lt;tt&amp;gt;SH_REMOVE_HOOK_ID&amp;lt;/tt&amp;gt; macro, and the hook will be removed.  This alternate removal syntax can simplify code that uses multiple successive or dynamic hooks.&lt;br /&gt;
&lt;br /&gt;
Global hooks, described in a later section, require usage of &amp;lt;tt&amp;gt;SH_REMOVE_HOOK_ID&amp;lt;/tt&amp;gt; - that is, there is no helper macro to simplify removing a global hook.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Old Macros=&lt;br /&gt;
SourceHook v5.0 deprecates older macros that were used in earlier versions.  The macros are:&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_ADD_HOOK_STATICFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_ADD_HOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_STATIC&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_REMOVE_HOOK_STATICFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_REMOVE_HOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_STATIC&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_ADD_HOOK_MEMFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_ADD_HOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_REMOVE_HOOK_MEMFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_REMOVE_HOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_ADD_MANUALHOOK_STATICFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_ADD_MANUALHOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_STATIC&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_REMOVE_MANUALHOOK_STATICFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_REMOVE_MANUALHOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_STATIC&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_ADD_MANUALHOOK_MEMFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_ADD_MANUALHOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_REMOVE_MANUALHOOK_MEMFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_REMOVE_MANUALHOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
These macros are fairly self explanatory.  The parameter where the &amp;lt;tt&amp;gt;SH_STATIC&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt; macro would normally go is instead filled with the parameters to that macro.  &lt;br /&gt;
&lt;br /&gt;
This syntax is considered deprecated, but it is still supported.  Code written with these macros will continue to compile against older SourceHook versions.  If you are writing a plugin which must work against Metamod:Source 1.4 and 1.6, you will want to use the older macros for simplicity.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Global Hooks=&lt;br /&gt;
&amp;lt;b&amp;gt;Note:&amp;lt;/b&amp;gt; Global Hooks are only available in SourceHook v4.5 or later.&lt;br /&gt;
&lt;br /&gt;
Global hooks are unlike normal hooks in that the hook is invoked for ALL instances, rather than solely the given the instance the hook was bound to.  It is important to realize that this feature can be deceiving.  Consider the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class CBaseEntity&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void SetHealth(int health) =0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class CBaseCat : public CBaseEntity&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void SetHealth();&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class CBaseKitten : public CBaseCat&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void SetHealth();&lt;br /&gt;
};&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, &amp;lt;tt&amp;gt;CBaseCat&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;CBaseKitten&amp;lt;/tt&amp;gt; instances have ''separate virtual tables''.  Although they both derive from &amp;lt;tt&amp;gt;CBaseEntity&amp;lt;/tt&amp;gt;, they are separate virtual objects.  &amp;lt;b&amp;gt;Therefore, a global hook on &amp;lt;tt&amp;gt;CBaseEntity&amp;lt;/tt&amp;gt; will receive no invocations, and a hook on &amp;lt;tt&amp;gt;CBaseCat&amp;lt;/tt&amp;gt; will receive only &amp;lt;tt&amp;gt;CBaseCat&amp;lt;/tt&amp;gt; instances, as long as the instance is not a class derived from &amp;lt;tt&amp;gt;CBaseCat&amp;lt;/tt&amp;gt;&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
With this understanding in place, there are two separate syntaxes - one for simple hooks and one for manual hooks.  Additionally, there are two ways of declaring the virtual interface to use:&lt;br /&gt;
*An instance of the class can be passed.&lt;br /&gt;
*The direct address to the virtual table can be passed.&lt;br /&gt;
&lt;br /&gt;
They are essentially equivalent, although one may be more advantageous than the other (for example, if no instances are known, but the vtable address can be extracted via pattern searching).&lt;br /&gt;
&lt;br /&gt;
It is also important to note that global hooks are just a different method of &amp;quot;filtering.&amp;quot;  They fall into either the &amp;quot;simple&amp;quot; or &amp;quot;manual&amp;quot; category, and are otherwise exactly the same to those hooks.  Thus there are no separate return/declaration macros for global hooks.&lt;br /&gt;
&lt;br /&gt;
The macro &amp;lt;tt&amp;gt;META_IFACEPTR&amp;lt;/tt&amp;gt; is especially useful for global hooks.  See [[SourceHook_Development#Interface_Pointers_from_Hooks|Interface Pointers from Hooks]] near the end.&lt;br /&gt;
&lt;br /&gt;
Lastly, global hooks exclusively use the extended hooking syntax.  That means there exists only &amp;lt;tt&amp;gt;SH_ADD&amp;lt;/tt&amp;gt; macros.  &amp;lt;tt&amp;gt;SH_HOOK_REMOVE_ID&amp;lt;/tt&amp;gt; must be used and the hook ID generated via &amp;lt;tt&amp;gt;SH_ADD&amp;lt;/tt&amp;gt; must be cached.&lt;br /&gt;
&lt;br /&gt;
All examples will use the following code as a basis:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class Player&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void TakeDamage(int damage) =0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
void Hook_TakeDamage(int damage);&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Simple Hooks==&lt;br /&gt;
Two extra macros exist for adding a global hook:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
SH_ADD_VPHOOK(Interface, Function, Instance, Handler, Post)&lt;br /&gt;
SH_ADD_DVPHOOK(Interface, Function, VirtualTable, Handler, Post)&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
extern void *player_vtable;&lt;br /&gt;
HookId takedamage_hook = 0;&lt;br /&gt;
&lt;br /&gt;
void StartHooks()&lt;br /&gt;
{&lt;br /&gt;
   takedamage_hook = SH_ADD_DVPHOOK(Player, TakeDamage, player_vtable, SH_STATIC(Hook_TakeDamage), false);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StopHooks()&lt;br /&gt;
{&lt;br /&gt;
   if (takedamage_hook)&lt;br /&gt;
   {&lt;br /&gt;
      SH_REMOVE_HOOK_ID(takedamage_hook);&lt;br /&gt;
   }&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Manual Hooks==&lt;br /&gt;
Similarly, manual hooks are straightforward:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
SH_DECL_MANUALHOOK1_void(MHook_TakeDamage, 0, 0, 0, int);&lt;br /&gt;
&lt;br /&gt;
extern void *player_vtable;&lt;br /&gt;
int takedamage_hook = 0;&lt;br /&gt;
&lt;br /&gt;
void StartHooks()&lt;br /&gt;
{&lt;br /&gt;
   takedamage_hook = SH_ADD_MANUALDVPHOOK(MHook_TakeDamage, player_vtable, SH_STATIC(Hook_TakeDamage), false);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StopHooks()&lt;br /&gt;
{&lt;br /&gt;
   if (takedamage_hook)&lt;br /&gt;
   {&lt;br /&gt;
      SH_REMOVE_HOOK_ID(takedamage_hook);&lt;br /&gt;
   }&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Modifying Parameters=&lt;br /&gt;
Consider another variation of the hooking process.  There is a hook on function X, which has one parameter.  The hook wants to change the value of this parameter transparently.  For example:&lt;br /&gt;
*Caller passes 5 into X.&lt;br /&gt;
*Hook changes the 5 to a 6.&lt;br /&gt;
*Hooked function receives a 6 and continues normally.&lt;br /&gt;
&lt;br /&gt;
SourceHook has a method for achieving this.  As an added bonus, the new parameters are passed to subsequent hooks.  That means the replacement process is as transparent as possible.  For this example, we'll use the following code, with an assumed hook on &amp;lt;tt&amp;gt;Player::TakeDamage&amp;lt;/tt&amp;gt; to the &amp;lt;tt&amp;gt;Hook_TakeDamage&amp;lt;/tt&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class Player&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void TakeDamage(int damage);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
void Hook_TakeDamage(int damage);&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our objective is to multiply the damage by 2.&lt;br /&gt;
&lt;br /&gt;
==Simple Hooks==&lt;br /&gt;
For simple hooks, changing parameters looks similar to an &amp;lt;tt&amp;gt;SH_CALL&amp;lt;/tt&amp;gt;.  The macros are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;RETURN_META_NEWPARAMS(Action, HookFunction, ([params]))&lt;br /&gt;
RETURN_META_VALUE_NEWPARAMS(Action, Value, HookFunction, ([params]))&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
void Hook_TakeDamage(int damage)&lt;br /&gt;
{&lt;br /&gt;
   RETURN_META_NEWPARAMS(MRES_IGNORED, &amp;amp;Player::TakeDamage, (damage * 2));&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the parenthesis enclosing the parameters are required.&lt;br /&gt;
&lt;br /&gt;
==Manual Hooks==&lt;br /&gt;
Manual hooks require slightly different macros.  They are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;RETURN_META_MNEWPARAMS(Action, UniqueName, ([params]));&lt;br /&gt;
RETURN_META_VALUE_MNEWPARAMS(Action, Value, UniqueName, ([params]));&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
SH_DECL_MANUALHOOK1_void(MHook_Player_TakeDamage, 0, 0, 0, int);&lt;br /&gt;
&lt;br /&gt;
void Hook_TakeDamage(int damage)&lt;br /&gt;
{&lt;br /&gt;
   RETURN_META_MNEWPARAMS(MRES_IGNORED, MHook_Player_TakeDamage, (damage *2));&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the parenthesis enclosing the parameters are required.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Bypassing Hooks=&lt;br /&gt;
Often, either to avoid certain functionality or to avoid infinite recursion, it is necessary to bypass all hooks on a hooked function, such that only the original function is called.  For instance, a previous blocked certain messages sent through &amp;lt;tt&amp;gt;LogPrint&amp;lt;/tt&amp;gt;.  In order to send that message, the hook needs to be bypassed.&lt;br /&gt;
&lt;br /&gt;
To way to do this is to use the &amp;lt;tt&amp;gt;SH_CALL&amp;lt;/tt&amp;gt; macro:&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_CALL(Instance, HookFunction)(params)&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_CALL(engine, &amp;amp;IVEngineServer::LogPrint)(&amp;quot;Secret Message&amp;quot;);&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, manual hooks have &amp;lt;tt&amp;gt;SH_MCALL&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_DECL_MANUALHOOK1(MHook_Function2, 1, 0, 0, bool, int);&lt;br /&gt;
&lt;br /&gt;
bool Function2_Bypass(int clam)&lt;br /&gt;
{&lt;br /&gt;
   return SH_MCALL(iface, MHook_Function2)(clam);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Deprecated Syntax==&lt;br /&gt;
The syntax described above is used in SourceHook v5.0 and v4.5.  An older syntax, using a &amp;quot;CallClass&amp;quot; data type, was used in SourceHook v4.4 and lower.  This syntax was deprecated in v4.5 and completely removed in v5.0.  Upgrading from SourceHook v4.4 means that code referencing &amp;lt;tt&amp;gt;SH_GET_CALLCLASS&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SH_REMOVE_CALLCLASS&amp;lt;/tt&amp;gt; must be removed, and &amp;lt;tt&amp;gt;SH_CALL&amp;lt;/tt&amp;gt; simply needs an instance pointer instead.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Other Macros=&lt;br /&gt;
SourceHook contains a large variety of extra macros.  This section is a grab bag of the more commonly used ones.&lt;br /&gt;
&lt;br /&gt;
==Interface Pointers from Hooks==&lt;br /&gt;
Let's say you have the following hook:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;class Player&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void TakeDamage(int damage);&lt;br /&gt;
   float GetDamageModifier();&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
void Hook_TakeDamage(int damage);&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
How can you get the &amp;lt;tt&amp;gt;Player&amp;lt;/tt&amp;gt; instance while in the hook?  This can be achieved via the &amp;lt;tt&amp;gt;META_IFACEPTR&amp;lt;/tt&amp;gt; macro.  Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;void Hook_TakeDamage(int damage)&lt;br /&gt;
{&lt;br /&gt;
   Player *pPlayer = META_IFACEPTR(Player);&lt;br /&gt;
&lt;br /&gt;
   int new_damage = (int)((pPlayer-&amp;gt;GetDamageModifier() + 0.3) * (float)damage);&lt;br /&gt;
&lt;br /&gt;
   RETURN_META_NEWPARAMS(MRES_IGNORED, &amp;amp;Player::TakeDamage, (new_damage));&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the class name should be passed to &amp;lt;tt&amp;gt;META_IFACEPTR&amp;lt;/tt&amp;gt;, not the pointer type.&lt;br /&gt;
&lt;br /&gt;
==Ignoring Reference Returns==&lt;br /&gt;
There is a special macro, &amp;lt;tt&amp;gt;RETURN_META_NOREF&amp;lt;/tt&amp;gt;, for ignoring a return value for reference-returning functions.  Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class ISomething&lt;br /&gt;
{&lt;br /&gt;
public:  &lt;br /&gt;
   virtual int &amp;amp; GetSomething() =0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int &amp;amp; Hook_GetSomething()&lt;br /&gt;
{&lt;br /&gt;
   RETURN_META_NOREF(MRES_IGNORED, int &amp;amp;);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Automatic hookmanager generation=&lt;br /&gt;
Normally, the SH_DECL_ macros generate a so-called &amp;quot;hook manager&amp;quot;, a function which is invoked instead of the original function and then calls the hooks and processes their return and &amp;lt;tt&amp;gt;META_RES&amp;lt;/tt&amp;gt; values.&lt;br /&gt;
&lt;br /&gt;
It is also possible to let SourceHook auto-generate the hook manager. This is neccessary if the function prototype is unknown at compile time (for example if hooks can be defined from third-party plugins of your plugin).&lt;br /&gt;
&lt;br /&gt;
Example Usage from a Metamod:Source plugin:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;quot;sourcehook_pibuilder.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// We want to hook a void (int, float) function&lt;br /&gt;
&lt;br /&gt;
// Request IHookManagerAutoGen interface&lt;br /&gt;
SourceHook::IHookManagerAutoGen *hmag =&lt;br /&gt;
    static_cast&amp;lt;SourceHook::IHookManagerAutoGen *&amp;gt;(ismm-&amp;gt;MetaFactory(MMIFACE_SH_HOOKMANAUTOGEN, NULL, NULL));&lt;br /&gt;
&lt;br /&gt;
// (check for hmag == NULL)&lt;br /&gt;
&lt;br /&gt;
// Build prototype information (using CProtoInfoBuilder helper class).&lt;br /&gt;
SourceHook::CProtoInfoBuilder protoInfo(SourceHook::ProtoInfo::CallConv_ThisCall);&lt;br /&gt;
protoInfo.AddParam(sizeof(int), SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal,&lt;br /&gt;
    NULL, NULL, NULL, NULL);&lt;br /&gt;
protoInfo.AddParam(sizeof(float), SourceHook::PassInfo::PassType_Float, SourceHook::PassInfo::PassFlag_ByVal,&lt;br /&gt;
    NULL, NULL, NULL, NULL);&lt;br /&gt;
&lt;br /&gt;
// Generate the hook manager&lt;br /&gt;
HookManagerPubFunc generatedHookMan = hmag-&amp;gt;MakeHookMan(protoInfo, 0 /* vtable offset */, 0 /* vtable index */);&lt;br /&gt;
&lt;br /&gt;
// Add the hook&lt;br /&gt;
int hookid = g_SHPtr-&amp;gt;AddHook(g_PLID, SourceHook::ISourceHook::Hook_Normal/Hook_VP/Hook_DVP, iface_ptr, thisptr_offs,&lt;br /&gt;
    generatedHookMan, handler, post);&lt;br /&gt;
&lt;br /&gt;
// ... (use the hook)&lt;br /&gt;
&lt;br /&gt;
// After you're done using the hook (cleanup)&lt;br /&gt;
// Remove the hook&lt;br /&gt;
g_SHPtr-&amp;gt;RemoveHookByID(hookid);&lt;br /&gt;
&lt;br /&gt;
// Release hook manager&lt;br /&gt;
hmag-&amp;gt;ReleaseHookMan(generatedHookMan);&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;CProtoInfoBuilder::AddParam&amp;lt;/tt&amp;gt; has 7 parameters:&lt;br /&gt;
* size: size of the type. This is sizeof(type) even if it is passed by reference!&lt;br /&gt;
* passtype: this can be PassType_Basic for integer types (char/short/int/...), PassType_Float for floating-point types (float/double) and PassType_Object for unions, structs and classes.&lt;br /&gt;
* passflags: flags. Has to contain either PassFlag_ByVal or PassFlag_ByRef.&lt;br /&gt;
* pNormalCtor: for PassType_Object, set this to the pointer to the user-defined default constructor of the object, if it has one.&lt;br /&gt;
* pCCtor: for PassType_Object, set this to the pointer to the user-defined copy constructor of the object, if it has one.&lt;br /&gt;
* pODtor: for PassType_Object, set this to the pointer to the user-defined destructor of the object, if it has one.&lt;br /&gt;
* pAssignOperator: for PassType_Object, set this to the pointer to the user-defined assignment operator of the object, if it has one.&lt;br /&gt;
&lt;br /&gt;
If you are hooking a non-void function, also call &amp;lt;tt&amp;gt;CProtoInfoBuilder::SetReturnType&amp;lt;/tt&amp;gt;. It has the same arguments as &amp;lt;tt&amp;gt;AddParam&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;handler&amp;lt;/tt&amp;gt; parameter of &amp;lt;tt&amp;gt;ISourceHook::AddHook&amp;lt;/tt&amp;gt; is a pointer to the ISHDelegate interface.&lt;br /&gt;
In C++, you construct ISHDelegates like this:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class MyDelegate : public SourceHook::ISHDelegate&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
    // vtable index 0&lt;br /&gt;
    virtual bool IsEqual(ISHDelegate *pOtherDeleg)&lt;br /&gt;
    {&lt;br /&gt;
        // pOtherDeleg is guaranteed to be from the same plugin.&lt;br /&gt;
        // This function is only used for compat with the old SH_REMOVE_HOOK method.&lt;br /&gt;
        // if you don't want to use that with your hooks, you can simply return false here.&lt;br /&gt;
        // if for some reason you need it, a good idea could be comparing the vtable pointer:&lt;br /&gt;
        return *reinterpret_cast&amp;lt;void**&amp;gt;(this) == *reinterpret_cast&amp;lt;void**&amp;gt;(pOtherDeleg);&lt;br /&gt;
&lt;br /&gt;
        // But in general I'd just return false!&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // vtable index 1&lt;br /&gt;
    virtual void DeleteThis()&lt;br /&gt;
    {&lt;br /&gt;
        delete this;   // Called from SourceHook when this instance is not needed&lt;br /&gt;
                       // and should be deleted.&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // vtable index 2&lt;br /&gt;
    virtual ret_type Call(params)&lt;br /&gt;
    {&lt;br /&gt;
        // your code.&lt;br /&gt;
        // SH_DECL_ macros pass execution to the actual user's handler through a FastDelegate&lt;br /&gt;
        // which is stored as a member variable of the delegate class.&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first parameter of the CProtoInfoBuilder constructor (see example code above) is the calling convention in an extended sense. At the moment it can be either CallConv_ThisCall or (CallConv_ThisCall | CallConv_HasVafmt). The second value means that the function has printf-like string formatting. Then, the finaly ''const char *, ...'' arguments will be added automatically, and the Deleagte::Call method should have one more parameter: ''const char *formattedString''.&lt;br /&gt;
&lt;br /&gt;
pNormalCtor/pCCtor/pODtor/pAssignOperator should be found using offsets / sigscanning. If you are a C++ plugin and know the type at compile time, you can also use the following class:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
// Address of constructor/destructor&lt;br /&gt;
// (using wrappers)&lt;br /&gt;
template &amp;lt;class T&amp;gt;&lt;br /&gt;
class Ctor_Thunk&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
	void NormalConstructor()&lt;br /&gt;
	{&lt;br /&gt;
		new(this) T;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	void CopyConstructor(const T &amp;amp;other)&lt;br /&gt;
	{&lt;br /&gt;
		new(this) T(other);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	void Destructor()&lt;br /&gt;
	{&lt;br /&gt;
		reinterpret_cast&amp;lt;T*&amp;gt;(this)-&amp;gt;~T();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	const T&amp;amp; AssignOp(const T &amp;amp;other)&lt;br /&gt;
	{&lt;br /&gt;
		return (*reinterpret_cast&amp;lt;T*&amp;gt;(this) = other);&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
template &amp;lt;class T&amp;gt;&lt;br /&gt;
void *FindFuncAddr(T mfp)&lt;br /&gt;
{&lt;br /&gt;
	union&lt;br /&gt;
	{&lt;br /&gt;
		T a;&lt;br /&gt;
		void *b;&lt;br /&gt;
	} u;&lt;br /&gt;
	u.a = mfp;&lt;br /&gt;
	return u.b;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Usage:&lt;br /&gt;
FindFuncAddr(&amp;amp;Ctor_Thunk&amp;lt;type&amp;gt;::NormalConstructor)&lt;br /&gt;
// (if the type is a reference type, use it without &amp;amp; here)&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Embedding=&lt;br /&gt;
Embedding SourceHook in your own application or library is very easy.  The &amp;lt;tt&amp;gt;sourcehook.cpp&amp;lt;/tt&amp;gt; file must be compiled or linked into your project.  To instantiate the SourceHook engine, you must create a &amp;lt;tt&amp;gt;CSourceHookImpl&amp;lt;/tt&amp;gt; instance.  Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
/* Normally, just &amp;lt;sourcehook.h&amp;gt; is included, but this is needed to instantiate the engine. */&lt;br /&gt;
#include &amp;lt;sourcehook/sourcehook_impl.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
SourceHook::Impl::CSourceHookImpl g_SourceHook;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To actually use SourceHook, it is necessary to have two global variables:&lt;br /&gt;
*&amp;lt;tt&amp;gt;g_PLID&amp;lt;/tt&amp;gt; - A unique integer that identifies the library using SourceHook.  This is used for removing all hooks a library is using.&lt;br /&gt;
*&amp;lt;tt&amp;gt;g_SHPtr&amp;lt;/tt&amp;gt; - A pointer to the &amp;lt;tt&amp;gt;SourceHook::ISourceHook&amp;lt;/tt&amp;gt; interface.&lt;br /&gt;
&lt;br /&gt;
Example header file:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;sourcehook/sourcehook.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern SourceHook::ISourceHook *g_SHPtr;&lt;br /&gt;
extern int g_PLID;&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example addition to the global code:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
SourceHook::ISourceHook *g_SHPtr = &amp;amp;g_SourceHook;&lt;br /&gt;
int g_PLID = 0;&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiple Libraries/Shared Hooks==&lt;br /&gt;
If SourceHook is going to be used across multiple libraries in the same process, it is essential that only one instance of SourceHook be present.  Of course, that is only logical, since otherwise the instances would be replacing each other's virtual patches.&lt;br /&gt;
&lt;br /&gt;
In order to support this, each separate library must be given the &amp;lt;tt&amp;gt;ISourceHook&amp;lt;/tt&amp;gt; pointer and a unique &amp;lt;tt&amp;gt;g_PLID&amp;lt;/tt&amp;gt; value.  &amp;lt;tt&amp;gt;CSourceHookImpl&amp;lt;/tt&amp;gt; provides a few useful functions for managing hooks on &amp;quot;child&amp;quot; libraries or otherwise linked code.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tt&amp;gt;PausePlugin()&amp;lt;/tt&amp;gt; - Silences any hooks from an ID, such that those hooks will not be called.&lt;br /&gt;
*&amp;lt;tt&amp;gt;UnpausePlugin()&amp;lt;/tt&amp;gt; - Un-silences any silenced hooks from an ID.&lt;br /&gt;
*&amp;lt;tt&amp;gt;UnloadPlugin()&amp;lt;/tt&amp;gt; - Clean-up any left-over hooks from an ID.&lt;br /&gt;
&lt;br /&gt;
[[Category:Metamod:Source Development]]&lt;br /&gt;
[[Category:SourceHook]]&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Category:SourceHook&amp;diff=11702</id>
		<title>Category:SourceHook</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Category:SourceHook&amp;diff=11702"/>
		<updated>2024-06-12T22:09:12Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Recategorize&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;SourceHook is Metamod's built in virtual hooking and conflict mediation library. SourceHook is used by plugins to instrument and modify game code without causing compatibility issues for other plugins.&lt;br /&gt;
&lt;br /&gt;
[[Category:Metamod:Source Development]]&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Installing_Metamod:Source&amp;diff=11700</id>
		<title>Installing Metamod:Source</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Installing_Metamod:Source&amp;diff=11700"/>
		<updated>2024-06-09T16:30:20Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: /* Source 2 */ add some notes to the instructions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This article will guide you through a [[Metamod:Source]] installation.&lt;br /&gt;
&lt;br /&gt;
=Normal Installation=&lt;br /&gt;
&lt;br /&gt;
''Not applicable for Source 2. See GameInfo section below''&lt;br /&gt;
&lt;br /&gt;
Valve sometimes makes changes in their games that break Metamod:Source between releases.  When this happens, you may need to install a snapshot versions of Metamod:Source.  You can see if this is required on the [[Required Versions (SourceMod)|Required Versions]] page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[http://www.metamodsource.net/ Download] Metamod:Source.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Extract the package to your game folder.  For example, for Counter-Strike:Source, you would have &amp;lt;code&amp;gt;cstrike/addons/metamod&amp;lt;/code&amp;gt; after extracting.  If you are uploading to FTP, extract the files locally before transferring to your server's game folder.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Restart your server.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Type &amp;quot;meta version&amp;quot; in your server console (or RCon).  You should see a line like: &amp;quot;Loaded As: Valve Server Plugin.&amp;quot;  If the command is not recognized, see the sections below.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When using a Linux server, you may see the following messages:&lt;br /&gt;
&lt;br /&gt;
* An error indicating that it could not be loaded due to &amp;quot;wrong ELF class: ELFCLASS64&amp;quot;.  If you are using a 32-bit dedicated server installation, this is normal behavior; as long as &amp;lt;code&amp;gt;meta version&amp;lt;/code&amp;gt; is recognized, Metamod:Source is installed.&lt;br /&gt;
* An error indicating that it could not be loaded because &amp;quot;/path/to/server_install/bin/libgcc_s.so.1: version `GCC_7.0.0` not found (required by /some_system_path_to/libstdc++.so.6&amp;quot;.  This is because Valve ships their own copies of those libraries.  As modern systems will have newer versions, you can safely delete the listed file from the server install.  Do not delete the file in the system path (usually &amp;lt;code&amp;gt;lib&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;lib32&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If you are running a 64-bit operating system yourself, you may need to install the system's 32-bit libraries.&lt;br /&gt;
** On Debian / Ubuntu, you can do this with &amp;lt;code&amp;gt;apt install gcc-multilib&amp;lt;/code&amp;gt;.&lt;br /&gt;
* You may find more information about any load failures under a &amp;lt;code&amp;gt;metamod-fatal.log&amp;lt;/code&amp;gt; in metamod's &amp;lt;code&amp;gt;bin&amp;lt;/code&amp;gt; folder.&lt;br /&gt;
&lt;br /&gt;
==Custom VDF File==&lt;br /&gt;
'''Note: This is normally not needed - Metamod:Source 1.10.0 and later include a &amp;lt;code&amp;gt;metamod.vdf&amp;lt;/code&amp;gt; file for easier installation on most games.'''&lt;br /&gt;
&lt;br /&gt;
If you have trouble getting it to load, [http://www.metamodsource.net/?go=vdf go here] to generate a VDF file specific to your game. This file should be placed into your server's &amp;lt;code&amp;gt;addons&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
Known setups that require this step:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Left 4 Dead 1&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;3rd party mods using the Source SDK Base.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Listen servers (created with the in-game &amp;quot;Create Server&amp;quot; option) for non-english game clients.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Adjust gameinfo file=&lt;br /&gt;
&lt;br /&gt;
'''Adjusting gameinfo for Source 1 is normally not needed. If you do not understand what this is, do NOT do this unless instructed to. The above instructions are sufficient to install Metamod:Source for 99% of servers. For Source 2, this is, however, the only supported loading method. See [[#Source_2|Source 2]] for more info.'''&lt;br /&gt;
&lt;br /&gt;
==Source 1==&lt;br /&gt;
Metamod:Source 1.4.2 and lower used an older method for loading itself.  The advantage of this method was that Metamod:Source could be loaded before the actual game mod, which gave it a small amount of extra functionality.  This functionality was never used by plugin developers, and Steam updates kept overwriting &amp;lt;code&amp;gt;gameinfo&amp;lt;/code&amp;gt; files, so we switched to a different loading mechanism.&lt;br /&gt;
&lt;br /&gt;
However this loading mechanism may still be desirable if you run into backwards compatibility issues, or you have a plugin which takes advantage of the early-loading mechanism.  If this is your case, here are the &amp;lt;code&amp;gt;gameinfo&amp;lt;/code&amp;gt; directions below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Open the file in the mod folder called &amp;lt;code&amp;gt;gameinfo.txt&amp;lt;/code&amp;gt;. You will see a few lines at the bottom like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SearchPaths&lt;br /&gt;
{&lt;br /&gt;
	Game				|gameinfo_path|. &lt;br /&gt;
	Game				cstrike&lt;br /&gt;
	Game				hl2&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Add a line after the &amp;lt;code&amp;gt;{&amp;lt;/code&amp;gt; sign but before all of the &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; entries that looks like this:&amp;lt;pre&amp;gt;GameBin				|gameinfo_path|addons/metamod/bin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If you're using Windows, you may need to use a backwards slash (\) instead.&lt;br /&gt;
&amp;lt;li&amp;gt;You're done! To test whether it worked, restart your game server and type &amp;lt;code&amp;gt;meta version&amp;lt;/code&amp;gt; in the server console.  You should see a line that says &amp;lt;code&amp;gt;Loaded as: GameDLL (gameinfo.txt)&amp;lt;/code&amp;gt;.&lt;br /&gt;
If it doesn't recognize the command, the installation probably failed.  If the &amp;lt;code&amp;gt;Loaded as:&amp;lt;/code&amp;gt; line says something else, &amp;lt;code&amp;gt;gameinfo&amp;lt;/code&amp;gt; was probably not modified correctly.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;For more information or documentation, see [[:Category:Metamod:Source Documentation]]&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Source 2==&lt;br /&gt;
Source 2 does not have server plugins, so you will need to load Metamod the old-fashioned way: replacing the server library with Metamod's stub loader.&lt;br /&gt;
&lt;br /&gt;
{{Sad|You will need to redo these changes every time a developer pushes a change that modifies gameinfo.gi}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Open the file in the mod folder called &amp;lt;code&amp;gt;gameinfo.gi&amp;lt;/code&amp;gt;. In CS2 this is &amp;lt;code&amp;gt;csgo/gameinfo.gi&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;li&amp;gt;Note that even though it says &amp;lt;code&amp;gt;DO NOT EDIT THIS FILE DIRECTLY&amp;lt;/code&amp;gt; and advises to edit &amp;lt;code&amp;gt;csgo_core/gameinfo.gi&amp;lt;/code&amp;gt;, editing that file does not correctly load Metamod.&lt;br /&gt;
&amp;lt;li&amp;gt;Look for the &amp;lt;code&amp;gt;SearchPaths&amp;lt;/code&amp;gt; section of code.&lt;br /&gt;
&amp;lt;li&amp;gt;Add a line after the &amp;lt;code&amp;gt;{&amp;lt;/code&amp;gt; sign but before all of the &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; entries that looks like this, replacing &amp;lt;code&amp;gt;csgo&amp;lt;/code&amp;gt; (for CS2) with your game name found in lines beneath it:&lt;br /&gt;
&amp;lt;pre&amp;gt;Game csgo/addons/metamod&amp;lt;/pre&amp;gt;&lt;br /&gt;
{{CommonMistake|Make sure the Metamod entry is the '''first''' in the searchpaths list! This list is ordered and placing it anywhere else will prevent Metamod from loading}}&lt;br /&gt;
&amp;lt;li&amp;gt;Using &amp;lt;code&amp;gt;GameBin&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; does not work.&lt;br /&gt;
&amp;lt;li&amp;gt;In Windows, the backslash is no longer required for paths.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You're done! To test whether it worked, restart your game server and type &amp;lt;code&amp;gt;meta version&amp;lt;/code&amp;gt; in the server console. You should see a line that says &amp;lt;code&amp;gt;Metamod:Source version 2.x.x&amp;lt;/code&amp;gt;.&lt;br /&gt;
If it doesn't recognize the command, the installation probably failed. Try updating your game to the latest version and using the latest version of Source 2.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;For more information or documentation, see [[:Category:Metamod:Source Documentation]]&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Metamod:Source Documentation]]&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Events_(SourceMod_Scripting)&amp;diff=11699</id>
		<title>Events (SourceMod Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Events_(SourceMod_Scripting)&amp;diff=11699"/>
		<updated>2024-05-19T19:57:08Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;:''To view all the events, click [[Game Events (Source)|here]].''&lt;br /&gt;
&lt;br /&gt;
Events are short, named messages sent by the server.  Although they are used for internal message passing, they are also networked to clients.&lt;br /&gt;
&lt;br /&gt;
Events are used for internal messages (such as when the server starts) and game events (such as when players take damage or spawn). Events are a simple way to hook events that SourceMod does not have dedicated support for, such as player spawns.&lt;br /&gt;
However, game events are '''mod-defined''', so you will need to ensure your behavior is correct for every mod you support, or you will have compatibility issues.&lt;br /&gt;
&lt;br /&gt;
All event natives are found in &amp;lt;tt&amp;gt;scripting/include/events.inc&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
Events are documented in &amp;lt;tt&amp;gt;.res&amp;lt;/tt&amp;gt; files under a mod's &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; folder.  The &amp;quot;default&amp;quot; events are located in &amp;lt;tt&amp;gt;hl2/resource/gameevents.res&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;hl2/resource/serverevents.res&amp;lt;/tt&amp;gt;.  Mods can extend these events with their own.  &lt;br /&gt;
&lt;br /&gt;
For example, let's look at &amp;lt;tt&amp;gt;player_death&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;hl2/resource/gameevents.res&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;quot;player_death&amp;quot;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;userid&amp;quot;    &amp;quot;short&amp;quot;     // user ID who died             &lt;br /&gt;
    &amp;quot;attacker&amp;quot;  &amp;quot;short&amp;quot;     // user ID who killed&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Counter-Strike:Source extends this definition in &amp;lt;tt&amp;gt;cstrike/resource/modevents.res&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;quot;player_death&amp;quot;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;userid&amp;quot;    &amp;quot;short&amp;quot;     // user ID who died             &lt;br /&gt;
    &amp;quot;attacker&amp;quot;  &amp;quot;short&amp;quot;     // user ID who killed&lt;br /&gt;
    &amp;quot;weapon&amp;quot;    &amp;quot;string&amp;quot;    // weapon name killer used &lt;br /&gt;
    &amp;quot;headshot&amp;quot;  &amp;quot;bool&amp;quot;      // signals a headshot&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the event is structured in the following format:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;quot;name&amp;quot;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;key1&amp;quot;  &amp;quot;valueType1&amp;quot;&lt;br /&gt;
    &amp;quot;key2&amp;quot;  &amp;quot;valueType2&amp;quot;&lt;br /&gt;
    ...&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Sending Events=&lt;br /&gt;
Events are very easy to send.  For example, let's say we want to send a death message using the &amp;lt;tt&amp;gt;player_death&amp;lt;/tt&amp;gt; event from above.  For Counter-Strike:Source, this would look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;void SendDeathMessage(int attacker, int victim, const char[] weapon, bool headshot)&lt;br /&gt;
{&lt;br /&gt;
    Event event = CreateEvent(&amp;quot;player_death&amp;quot;);&lt;br /&gt;
    if (event == null)&lt;br /&gt;
    {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    event.SetInt(&amp;quot;userid&amp;quot;, GetClientUserId(victim));&lt;br /&gt;
    event.SetInt(&amp;quot;attacker&amp;quot;, GetClientUserId(attacker));&lt;br /&gt;
    event.SetString(&amp;quot;weapon&amp;quot;, weapon);&lt;br /&gt;
    event.SetBool(&amp;quot;headshot&amp;quot;, headshot);&lt;br /&gt;
    event.Fire();&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
*You don't need to call &amp;lt;tt&amp;gt;CloseHandle()&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;FireEvent()&amp;lt;/tt&amp;gt; does this for us.&lt;br /&gt;
*Even though &amp;quot;userid&amp;quot; and &amp;quot;attacker&amp;quot; are shorts, we set them as ints.  The term &amp;quot;short&amp;quot; is only used to tell the engine how many bytes of the integer are needed to be networked.&lt;br /&gt;
*It is possible for event creation to fail; this can happen if the event does not exist, or nothing is hooking the event.  Thus, you should always make sure &amp;lt;tt&amp;gt;CreateEvent&amp;lt;/tt&amp;gt; calls return a valid Event handle.&lt;br /&gt;
*Most events use client userids instead of client indexes.&lt;br /&gt;
*By default, &amp;lt;tt&amp;gt;FireEvent()&amp;lt;/tt&amp;gt; broadcasts messages to clients.  This can be prevented by passing &amp;lt;tt&amp;gt;dontBroadcast&amp;lt;/tt&amp;gt; as true.&lt;br /&gt;
&lt;br /&gt;
=Hooking Events=&lt;br /&gt;
When hooking an event, there are three modes to choose from:&lt;br /&gt;
*&amp;lt;tt&amp;gt;Pre&amp;lt;/tt&amp;gt; - Hook the event before it is fired.&lt;br /&gt;
*&amp;lt;tt&amp;gt;Post&amp;lt;/tt&amp;gt; - Hook the event after it is fired.&lt;br /&gt;
*&amp;lt;tt&amp;gt;Post_NoCopy&amp;lt;/tt&amp;gt; - Hook the event, but do not save any of its information (special optimization).&lt;br /&gt;
&lt;br /&gt;
Hooking an event is usually done for one of the following goals.  To get an idea of which mode to use, see the list below each goal:&lt;br /&gt;
*Blocking the event (preventing it from being fired)&lt;br /&gt;
**'''Always &amp;lt;tt&amp;gt;Pre&amp;lt;/tt&amp;gt;'''&lt;br /&gt;
*Rewriting the event (changing its parameters)&lt;br /&gt;
**'''Always &amp;lt;tt&amp;gt;Pre&amp;lt;/tt&amp;gt;'''&lt;br /&gt;
*Acting upon the event (doing something once the event is completed)&lt;br /&gt;
**'''&amp;lt;tt&amp;gt;Pre&amp;lt;/tt&amp;gt;''' if your action must come before the mod's action.&lt;br /&gt;
**'''&amp;lt;tt&amp;gt;Post&amp;lt;/tt&amp;gt;''' if your action must come after the mod's action.&lt;br /&gt;
**'''&amp;lt;tt&amp;gt;PostNoCopy&amp;lt;/tt&amp;gt;''' if your action is &amp;lt;tt&amp;gt;Post&amp;lt;/tt&amp;gt; and only requires the event name.&lt;br /&gt;
&lt;br /&gt;
As always, you do not need to unhook events when your plugin unloads.  They are automatically removed.&lt;br /&gt;
&lt;br /&gt;
==Blocking Events==&lt;br /&gt;
Blocking events is the easiest thing to do.  Let's say we want to block death events that are headshots:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
    HookEvent(&amp;quot;player_death&amp;quot;, Event_PlayerDeath, EventHookMode_Pre);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast)&lt;br /&gt;
{&lt;br /&gt;
    if (event.GetBool(&amp;quot;headshot&amp;quot;))&lt;br /&gt;
    {&lt;br /&gt;
        return Plugin_Handled;&lt;br /&gt;
    }&lt;br /&gt;
    return Plugin_Continue;&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{CommonMistake|Blocking an event only blocks other parts of the game from receiving the event; the source of the event may still take action (such as by damaging players)!}}&lt;br /&gt;
&lt;br /&gt;
==Rewriting Events==&lt;br /&gt;
Rewriting events is just as easy -- events can be modified in pre hooks.  For example, say we want to remove headshots from all events:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
    HookEvent(&amp;quot;player_death&amp;quot;, Event_PlayerDeath, EventHookMode_Pre);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast)&lt;br /&gt;
{&lt;br /&gt;
    event.SetBool(&amp;quot;headshot&amp;quot;, false);&lt;br /&gt;
    return Plugin_Continue;&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Post Hooks==&lt;br /&gt;
{{CommonMistake|Post hooks run after the game has handled the event, but the event source may still take action after the event has finished!&lt;br /&gt;
This is a potentially sneaky source of recursion and stack overflow crashes, so watch out!&lt;br /&gt;
}}&lt;br /&gt;
Post hooks are default, and will usually be the most common usage.  For example, say we want to print a message to every client that dies:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
    HookEvent(&amp;quot;player_death&amp;quot;, Event_PlayerDeath);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast)&lt;br /&gt;
{&lt;br /&gt;
    char weapon[64];&lt;br /&gt;
    int victimId = event.GetInt(&amp;quot;userid&amp;quot;);&lt;br /&gt;
    int attackerId = event.GetInt(&amp;quot;attacker&amp;quot;);&lt;br /&gt;
    bool headshot = event.GetBool(&amp;quot;headshot&amp;quot;);&lt;br /&gt;
    event.GetString(&amp;quot;weapon&amp;quot;, weapon, sizeof(weapon));&lt;br /&gt;
&lt;br /&gt;
    char name[64];&lt;br /&gt;
    int victim = GetClientOfUserId(victimId);&lt;br /&gt;
    int attacker = GetClientOfUserId(attackerId);&lt;br /&gt;
    GetClientName(attacker, name, sizeof(name));&lt;br /&gt;
&lt;br /&gt;
    PrintToConsole(victim,&lt;br /&gt;
        &amp;quot;You were killed by \&amp;quot;%s\&amp;quot; (weapon \&amp;quot;%s\&amp;quot;) (headshot \&amp;quot;%d\&amp;quot;)&amp;quot;,&lt;br /&gt;
        name,&lt;br /&gt;
        weapon,&lt;br /&gt;
        headshot);&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will print a message to a player's console telling them who killed them, with what weapon, and whether it was a headshot or not.&lt;br /&gt;
&lt;br /&gt;
Note that the return value for post hooks is ignored, so the &amp;lt;tt&amp;gt;Action&amp;lt;/tt&amp;gt; tag is not needed.&lt;br /&gt;
&lt;br /&gt;
==PostNoCopy Hooks==&lt;br /&gt;
Lastly, there are some hooks where the only piece of information needed is the name of the event.  &amp;lt;tt&amp;gt;PostNoCopy&amp;lt;/tt&amp;gt; is a special optimization for this case.  When transitioning from &amp;lt;tt&amp;gt;Pre&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;Post&amp;lt;/tt&amp;gt;, SourceMod must duplicate the event and all of its key/value pairs.  &amp;lt;tt&amp;gt;PostNoCopy&amp;lt;/tt&amp;gt; prevents that sequence from happening.&lt;br /&gt;
&lt;br /&gt;
For example, let's say we want to find when a certain sequence of events is called.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
    HookEvent(&amp;quot;game_newmap&amp;quot;, GameEvents, EventHookMode_PostNoCopy);&lt;br /&gt;
    HookEvent(&amp;quot;game_start&amp;quot;, GameEvents, EventHookMode_PostNoCopy);&lt;br /&gt;
    HookEvent(&amp;quot;game_end&amp;quot;, GameEvents, EventHookMode_PostNoCopy);&lt;br /&gt;
    HookEvent(&amp;quot;game_message&amp;quot;, GameEvents, EventHookMode_PostNoCopy);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void GameEvents(Event event, const char[] name, bool dontBroadcast)&lt;br /&gt;
{&lt;br /&gt;
    PrintToServer(&amp;quot;Event has been fired (event \&amp;quot;%s\&amp;quot;) (nobcast \&amp;quot;%d\&amp;quot;)&amp;quot;, name, dontBroadcast);&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that like normal &amp;lt;tt&amp;gt;Post&amp;lt;/tt&amp;gt; hooks, there is no return value needed.  However, the &amp;lt;tt&amp;gt;event&amp;lt;/tt&amp;gt; parameter for &amp;lt;tt&amp;gt;PostNoCopy&amp;lt;/tt&amp;gt; will '''always''' be equal to &amp;lt;tt&amp;gt;null&amp;lt;/tt&amp;gt;.  Thus, the &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; parameter must be used instead of &amp;lt;tt&amp;gt;event.GetName&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Scripting]]&lt;br /&gt;
&lt;br /&gt;
{{LanguageSwitch}}&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Template:Sad&amp;diff=11698</id>
		<title>Template:Sad</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Template:Sad&amp;diff=11698"/>
		<updated>2024-05-19T19:44:42Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Created page with &amp;quot;&amp;lt;div style=&amp;quot;padding: 0.75em 1.5em; border-width: 2px; border-color: grey; border-style:solid;&amp;quot;&amp;gt; alt= &amp;lt;span style=&amp;quot;display:table-...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;padding: 0.75em 1.5em; border-width: 2px; border-color: grey; border-style:solid;&amp;quot;&amp;gt;&lt;br /&gt;
[[File:sadness.png|frameless|32px|left|link=|alt=]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;display:table-cell&amp;quot;&amp;gt;&lt;br /&gt;
{{{1}}}&lt;br /&gt;
&amp;lt;/span&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=File:Sadness.png&amp;diff=11697</id>
		<title>File:Sadness.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=File:Sadness.png&amp;diff=11697"/>
		<updated>2024-05-19T19:44:25Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: A sad little flork.

This image will be used in templates when features have been removed or when other sad things occur that require extra work from developers.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
A sad little flork.&lt;br /&gt;
&lt;br /&gt;
This image will be used in templates when features have been removed or when other sad things occur that require extra work from developers.&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Vectors_Explained_(Scripting)&amp;diff=11696</id>
		<title>Vectors Explained (Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Vectors_Explained_(Scripting)&amp;diff=11696"/>
		<updated>2024-05-19T19:41:30Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
Vectors in general tend to be rather confusing until they are explained. There are three different types you will see. Position Vectors, Velocity Vectors, and Angle Vectors. While in most basic cases you will probably only use one of these at a time, it doesn't hurt to know what the other two parameters are there for. Here is an example of the native 'TeleportEntity' to show you what it looks like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
native int TeleportEntity(int entity, const float origin[3], const float angles[3], const float velocity[3]);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Positions ===&lt;br /&gt;
'''Position Vector''': The first Vector in this native, declared as origin[3], is the Position Vector. This simply tells us the entities absolute position in the world. The position vector could look something like {15.0, 30.0, 15.0} and this would mean the entity is 15 units along the X axis, 30 units along the Y axis, and 15 units along the Z axis.&lt;br /&gt;
&lt;br /&gt;
=== Angles ===&lt;br /&gt;
'''Angles''' specify the ''angles'' of the rotation, not the actual vector of the rotation! (Essentially, it's an arctangent of each direction component.) &lt;br /&gt;
Angles are specified as &amp;lt;code&amp;gt;{pitch/up, yaw/left, roll/spin}}&amp;lt;/code&amp;gt;. Angles are specified as a `float[3]` array. &lt;br /&gt;
Angles can be turned into a vector (and back into an angle!) using the angle natives: &amp;lt;code&amp;gt;GetAngleVectors&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;GetVectorAngles&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Most angles are sanitized between -180 and 180 within the source engine (for up/down on players this is -89/89!), however some weird physics shenanigans and cheating clients can exceed these values so always ensure your angles are well formed before using them.&lt;br /&gt;
&lt;br /&gt;
{{CommonMistake|Make sure to use &amp;lt;code&amp;gt;GetAngleVectors&amp;lt;/code&amp;gt; before using the angles value to transform world space!}}&lt;br /&gt;
&lt;br /&gt;
=== Velocity ===&lt;br /&gt;
'''Velocity''', or a '''Vector''', is a true vector in the sense that it is ''only a direction and magnitude''. The velocity represents motion, usually the amount of motion that will occur in one tick. The position of an object on the next tick will be the sum of the current position and the object's velocity.&lt;br /&gt;
&lt;br /&gt;
==Velocity Vectors==&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
float vecOrigin[3], vecVelocity[3], vecResult[3];&lt;br /&gt;
&lt;br /&gt;
AddVectors(vecOrigin, vecVelocity, vecResult);&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Template:CommonMistake&amp;diff=11695</id>
		<title>Template:CommonMistake</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Template:CommonMistake&amp;diff=11695"/>
		<updated>2024-05-19T19:36:33Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Remove documentation :(&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;padding: 0.75em 1.5em; border-width: 2px; border-color: grey; border-style:solid;&amp;quot;&amp;gt;&lt;br /&gt;
[[File:silly_goose.png|frameless|32px|left|link=|alt=]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;display:table-cell&amp;quot;&amp;gt;&lt;br /&gt;
{{{1}}}&lt;br /&gt;
&amp;lt;/span&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Template:CommonMistake&amp;diff=11694</id>
		<title>Template:CommonMistake</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Template:CommonMistake&amp;diff=11694"/>
		<updated>2024-05-19T19:29:05Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Add {{CommonMistake}}&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;padding: 0.75em 1.5em; border-width: 2px; border-color: grey; border-style:solid;&amp;quot;&amp;gt;&lt;br /&gt;
[[File:silly_goose.png|frameless|32px|left|link=|alt=]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;display:table-cell&amp;quot;&amp;gt;&lt;br /&gt;
{{{1}}}&lt;br /&gt;
&amp;lt;/span&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{documentation|content=&lt;br /&gt;
If you see people making a mistake a lot, document it with a common mistake!&lt;br /&gt;
&lt;br /&gt;
{{CommonMistake| Did you make sure to put the key in the ignition first?}}&lt;br /&gt;
{{CommonMistake| Don't touch that dial! We'll be right back after this message from our sponsors}}&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=File:Silly_goose.png&amp;diff=11693</id>
		<title>File:Silly goose.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=File:Silly_goose.png&amp;diff=11693"/>
		<updated>2024-05-19T19:22:29Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Are you a silly little goose? 

This image will be used in templates to explain common mistakes. It's just a little charm :)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
Are you a silly little goose? &lt;br /&gt;
&lt;br /&gt;
This image will be used in templates to explain common mistakes. It's just a little charm :)&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=SDKHooks&amp;diff=11692</id>
		<title>SDKHooks</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=SDKHooks&amp;diff=11692"/>
		<updated>2024-05-10T05:37:54Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Add sourcemod scripting category&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
SDKHooks was previously an external extension to Sourcemod. It was rolled in [https://wiki.alliedmods.net/Sourcemod_1.5.0_API_Changes#SDKHooks Sourcemod 1.5] and it does not need to be manually installed anymore.&lt;br /&gt;
&lt;br /&gt;
==Hooks==&lt;br /&gt;
Some information on various hooks below.&lt;br /&gt;
&lt;br /&gt;
===SDKHook_OnTakeDamage===&lt;br /&gt;
inflictor (3rd argument) is the entity that inflicts the damage. If a player directly damages another, inflictor should be equal to the attacking player id. An example of an indirect damage would be a grenade.&lt;br /&gt;
&lt;br /&gt;
===SDKHook_OnTakeDamageAlive===&lt;br /&gt;
This hook works in a similar way to SDKHook_OnTakeDamage but it gives the [https://bugs.alliedmods.net/show_bug.cgi?id=6249#c7 actual, calculated damage amount done to the player. The pre-hook will fire after an OnTakeDamage pre-hook, and the post-hook will fire before an OnTakeDamage post-hook. The health is subtracted in between pre and post unless the hook is blocked.] {{pr|149}}&lt;br /&gt;
&lt;br /&gt;
[https://forums.alliedmods.net/showthread.php?p=2309798#post2309798 OnTakeDamageAlive is also only called for players.]&lt;br /&gt;
&lt;br /&gt;
==Under CSS==&lt;br /&gt;
===Non-regular cases for SDKHook_OnTakeDamage===&lt;br /&gt;
In the scenario where a player throw a grenade to another player then quickly disconnect, the attacker (2nd argument) will become the inflictor (3rd argument). &lt;br /&gt;
&lt;br /&gt;
In the scenario where a player fall; the attacker, which is also the inflictor, will be 0 (the world).&lt;br /&gt;
&lt;br /&gt;
In the scenario where a terrorist plants the bomb, when the bomb explodes, the attacker (2nd argument) will be the same as the inflictor (3rd argument) which will have the Classname &amp;quot;planted_c4&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Some damage types===&lt;br /&gt;
A normal HEGrenade and the C4 inflict damage of type DMG_BLAST.&lt;br /&gt;
&lt;br /&gt;
A fall inflicts damage of type DMG_FALL.&lt;br /&gt;
&lt;br /&gt;
A grenade impact (for instance a flash hitting a teammate) will inflict damage of type DMG_CLUB.&lt;br /&gt;
&lt;br /&gt;
A normal gun bullet and the knife will inflict damage of type (DMG_BULLET | DMG_NEVERGIB) (non-headshot) or (DMG_BULLET | DMG_NEVERGIB | (1 &amp;lt;&amp;lt; 30) ) (headshot).&lt;br /&gt;
&lt;br /&gt;
A single attack can trigger many SDKHook_OnTakeDamage; when a gun throws pullets for instance (shotgun and glock in burst-mode notably).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(Regarding SM/Admin damaged; maybe place this is another section if someone can be sure that this would occur on all mods)&lt;br /&gt;
&lt;br /&gt;
sm_slap does not trigger SDKHook_OnTakeDamage.&lt;br /&gt;
&lt;br /&gt;
sm_burn will trigger two different callback : an entity with the classname &amp;quot;entityflame&amp;quot; will deal once 0 damage of type DMG_BURN and once 1 damage of type (DMG_BURN | DMG_DIRECT) every tick.&lt;br /&gt;
&lt;br /&gt;
===Regarding SDKHook_OnTakeDamage and SDKHook_OnTakeDamageAlive===&lt;br /&gt;
&lt;br /&gt;
SDKHook_OnTakeDamage/Post is triggered when hitting a teammate with mp_friendlyfire 0 (except in TF2), but not SDKHook_OnTakeDamageAlive.&lt;br /&gt;
&lt;br /&gt;
==Under TF2==&lt;br /&gt;
Under TF2, the SDKHook_OnTakeDamage hook isn't 100% accurate, it's damage parameter is the weapon's base damage. the DMG_CRIT flag is for both crits and minicrits. Weapon spread and minicrit/crit damage is calculated after this call (in SDKHook_OnTakeDamageAlive/Post).&lt;br /&gt;
&lt;br /&gt;
===Some damage types===&lt;br /&gt;
Shotgun = DMG_BUCKSHOT | DMG_SLOWBURN&lt;br /&gt;
&lt;br /&gt;
Rocket Launcher = DMG_SLOWBURN | DMG_RADIATION | DMG_BLAST&lt;br /&gt;
&lt;br /&gt;
If a crit, |= DMG_CRIT&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Scripting]]&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=SourceHook_Development&amp;diff=11691</id>
		<title>SourceHook Development</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=SourceHook_Development&amp;diff=11691"/>
		<updated>2024-05-10T05:36:13Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Add metamod-dev category&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;SourceHook is a powerful API (Application Programming Interface) for detouring (hooking) virtual functions.  Unlike static detours, SourceHook needs only to swap addresses in and out of an object's virtual table.  This makes it fast and generally very platform-safe.&lt;br /&gt;
&lt;br /&gt;
SourceHook is coupled with Don Clugston's [http://www.codeproject.com/cpp/FastDelegate.asp FastDelegate] headers.  Virtual hooks can be detoured to any static function of the same prototype, or any member function (of any class) as long as the prototype matches.&lt;br /&gt;
&lt;br /&gt;
All code in SourceHook is part of the SourceHook namespace.  Thus, it may be prudent to declare this before using SourceHook structures or types:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;using namespace SourceHook;&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Simple Hooks=&lt;br /&gt;
SourceHook has the following steps of operation:&lt;br /&gt;
&lt;br /&gt;
* Declare the prototype of the function you are going to hook. This generates compile-time code that is able to pinpoint exactly how to go about hooking the function.&lt;br /&gt;
* Hook the function - as a member function of another class or a regular static function.&lt;br /&gt;
* Before the hooked function is called, all of the &amp;quot;pre&amp;quot; hook handlers attached to it are called. Each hook can set a special flag, the highest of which is chosen as a final operation. This flag specifies whether the original function should be called or not.&lt;br /&gt;
* Once all the hooks have been called, SourceHook decides whether to call the original function. Another set of hooks are called directly after, called &amp;quot;post&amp;quot; hook handlers. You can specify whether each hook is a post or pre hook - it simply changes whether it's called before or after the original call is made.&lt;br /&gt;
* After you are done using a hook, you must safely remove it before the object is destroyed (otherwise, memory will be leaked).&lt;br /&gt;
&lt;br /&gt;
==Declaration==&lt;br /&gt;
As an example, take the following class prototype:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class IVEngineServer&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   /*...*/&lt;br /&gt;
   virtual void LogPrint( const char *msg ) = 0;&lt;br /&gt;
   virtual bool IsDedicated() = 0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
extern IVEngineServer *engine;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The first step is to figure out how to declare its prototype to SourceHook. This function is void, and has one parameter. The declaration macro follows these formats:&lt;br /&gt;
&lt;br /&gt;
*{{bcode|SH_DECL_HOOK}}n - n is the number of parameters&lt;br /&gt;
**The parameters are: Class name, member function name, attributes, overloaded?, the return type, and a list of the parameter types.&lt;br /&gt;
*{{bcode|SH_DECL_HOOKn_void}} - n is the number of parameters&lt;br /&gt;
**_void specifies that the function does not return a value. The format is the same as above except the &amp;quot;return type&amp;quot; parameter is missing.&lt;br /&gt;
*'''Note:''' Not covered here are the SH_DECL_HOOKn[_void]_vafmt hooks. These can hook string-formattable variable argument lists. You do not pass the string format or ellipses parameter. SourceHook will automatically format the string for your hook.&lt;br /&gt;
&lt;br /&gt;
Our macro will look like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SH_DECL_HOOK1_void(IVEngineServer, LogPrint, SH_NOATTRIB, 0, const char *);&lt;br /&gt;
SH_DECL_HOOK0(IVEngineServer, IsDedicated, SH_NOATTRIB, 0, bool);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Broken down for the first line:&lt;br /&gt;
*There is 1 parameter.&lt;br /&gt;
*The function has no return value.&lt;br /&gt;
*&amp;lt;tt&amp;gt;IVEngineServer&amp;lt;/tt&amp;gt; is the class containing the function.&lt;br /&gt;
*&amp;lt;tt&amp;gt;LogPrint&amp;lt;/tt&amp;gt; is the function being hooked.&lt;br /&gt;
*The function as no attributes (for example, it is not const).&lt;br /&gt;
*The function is not overloaded.&lt;br /&gt;
*The first (and only) argument is a &amp;lt;tt&amp;gt;const char *&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second line is similar, except the parameter immediately after the overload parameter specifies the return type.  There are no further parameters since it was declared with 0.&lt;br /&gt;
&lt;br /&gt;
==Getting an Interface Instance==&lt;br /&gt;
&lt;br /&gt;
Before you can use an interface, you need to retrieve an instance of it.  This is done with either the &amp;lt;tt&amp;gt;GET_V_IFACE_ANY&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;GET_V_IFACE_CURRENT&amp;lt;/tt&amp;gt; macros.  Both take the same arguments.  &amp;lt;tt&amp;gt;GET_V_IFACE_CURRENT&amp;lt;/tt&amp;gt; is recommended if it works.  &amp;lt;tt&amp;gt;GET_V_IFACE_ANY&amp;lt;/tt&amp;gt; should also work, but may be missing newer functionality.&lt;br /&gt;
&lt;br /&gt;
Normally this initialization needs to be done when your MM:S plugin or SourceMod Extension starts.&lt;br /&gt;
&lt;br /&gt;
You also need to know which factory produces the interface you need.  There are only 4 factories: &amp;lt;tt&amp;gt;GetEngineFactory&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;GetServerFactory&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;GetPhysicsFactory&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;GetFilesystemFactory&amp;lt;/tt&amp;gt;.  Normally you'll want Engine or Server.&lt;br /&gt;
&lt;br /&gt;
You'll also need to know the constant that the game uses for that particular class.  This is usually found in the hl2sdk for your game.  In the case of &amp;lt;tt&amp;gt;IVEngineServer&amp;lt;/tt&amp;gt;, this is &amp;lt;tt&amp;gt;INTERFACEVERSION_VENGINESERVER&amp;lt;/tt&amp;gt; located in public/eiface.h.&lt;br /&gt;
&lt;br /&gt;
So, to retrieve the Interface so you can do something with it, it'd look something like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
IVEngineServer *engine;&lt;br /&gt;
&lt;br /&gt;
// For SourceMod, use the first signature&lt;br /&gt;
//bool MyExtension::OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)&lt;br /&gt;
bool MyPlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late)&lt;br /&gt;
{&lt;br /&gt;
    GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The error and maxlen arguments '''must''' be named error and maxlen respectively, or else certain macros will fail.&lt;br /&gt;
&lt;br /&gt;
Note that MyPlugin should be replaced with your plugin's class.&lt;br /&gt;
&lt;br /&gt;
==Hook Functions==&lt;br /&gt;
Hooks can be declared either ''pre'' or ''post''.  A ''pre'' hook will intercept the original function before it is called.  Pre-hooks can return one of four ''hook actions'':&lt;br /&gt;
*&amp;lt;tt&amp;gt;MRES_IGNORED&amp;lt;/tt&amp;gt; - The original function will be called.&lt;br /&gt;
*&amp;lt;tt&amp;gt;MRES_HANDLED&amp;lt;/tt&amp;gt; - Same as &amp;lt;tt&amp;gt;MRES_IGNORED&amp;lt;/tt&amp;gt;, except subsequent hooks can assume this means something important was changed.&lt;br /&gt;
*&amp;lt;tt&amp;gt;MRES_OVERRIDE&amp;lt;/tt&amp;gt; - The original function will be called, but the new return value will be used instead of the one from the original function.&lt;br /&gt;
*&amp;lt;tt&amp;gt;MRES_SUPERCEDE&amp;lt;/tt&amp;gt; - The original function will not be called.  The new return value (if any) will be used instead.&lt;br /&gt;
&lt;br /&gt;
These enum constants are defined in &amp;lt;tt&amp;gt;&amp;lt;sourcehook.h&amp;gt;&amp;lt;/tt&amp;gt;, and are made available to Metamod:Source plugin developers via &amp;lt;tt&amp;gt;&amp;lt;ISmmPlugin.h&amp;gt;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Once all pre-hooks have been processed, SourceHook takes an action based on the &amp;quot;highest&amp;quot; hook action returned (&amp;lt;tt&amp;gt;MRES_IGNORED&amp;lt;/tt&amp;gt; being lowest, &amp;lt;tt&amp;gt;MRES_SUPERCEDE&amp;lt;/tt&amp;gt; being highest).  Once the action has been processed, all ''post'' hooks are called.  That is to say, even if the original function is never called, post hooks are still processed.  Because a post hook as no chance at true interception, it is important to realize that depending on the information being detoured, the data may be modified or destroyed.  Similarly, a post hook's returned action and value is ignored.&lt;br /&gt;
&lt;br /&gt;
A hook's action is signalled via one of two macros:&lt;br /&gt;
*&amp;lt;tt&amp;gt;RETURN_META&amp;lt;/tt&amp;gt; - Only usable from &amp;lt;tt&amp;gt;void&amp;lt;/tt&amp;gt; functions.  Signals the action to take, then returns.&lt;br /&gt;
*&amp;lt;tt&amp;gt;RETURN_META_VALUE&amp;lt;/tt&amp;gt; - Only usable from non-&amp;lt;tt&amp;gt;void&amp;lt;/tt&amp;gt; functions.  Signals the action to take, then returns the supplied value.&lt;br /&gt;
&lt;br /&gt;
There are two methods of adding or removing hooks.  Hooks can be bound to '''static''' or '''member''' functions.  Both have a similar syntax.  Their macros are:&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_STATIC(Function)&amp;lt;/tt&amp;gt; - Hook to a static function.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_MEMBER(Instance, Function)&amp;lt;/tt&amp;gt; - Hook to a member function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;It is important to realize that a simple hook will only be invoked when used on the same instance.&amp;lt;/b&amp;gt;  That is to say, if there are 500 instances of object X, and a hook is added to function X::Y in instance #8, then the hook will only be invoked from instance #8.  &amp;lt;b&amp;gt;Multiple hooks can be declared on the same instance, and multiple instances can be bound to the same hook, but one hook will only be invoked for the instances it was hooked to.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To have hooks that work across all instances, and thus do not need to be delegated per-instance, see the &amp;quot;Global Hooks&amp;quot; section.  As of SourceHook v5, it is safe to remove hooks on a destroyed instance, as the instance is not actually dereferenced.  However, its virtual table must still be accessible.&lt;br /&gt;
&lt;br /&gt;
==Adding Hooks==&lt;br /&gt;
The macro to add hooks is &amp;lt;tt&amp;gt;SH_[ADD|REMOVE]_HOOK&amp;lt;/tt&amp;gt;.  The syntax is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_[ADD|REMOVE]_HOOK(Interface, Function, Instance, Hook, [post? true,false])&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example of adding a &amp;lt;tt&amp;gt;LogPrint&amp;lt;/tt&amp;gt; hook:&lt;br /&gt;
&amp;lt;cpp&amp;gt;void Hook_LogPrint(const char *msg)&lt;br /&gt;
{&lt;br /&gt;
   if (strcmp(msg, &amp;quot;If this string matches the function will be blocked&amp;quot;) == 0)&lt;br /&gt;
   {&lt;br /&gt;
      RETURN_META(MRES_SUPERCEDE);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /* Not needed, but good style */&lt;br /&gt;
   RETURN_META(MRES_IGNORED);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StartHooks()&lt;br /&gt;
{&lt;br /&gt;
   log_hook = SH_ADD_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(Hook_LogPrint), false);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StopHooks()&lt;br /&gt;
{&lt;br /&gt;
   SH_REMOVE_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(Hook_LogPrint), false);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax is similar for hooking to member functions.  Example equivalent to the above:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class MyHooks&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   void Hook_LogPrint(const char *msg)&lt;br /&gt;
   {&lt;br /&gt;
      if (strcmp(msg, &amp;quot;If this string matches the function will be blocked&amp;quot;) == 0)&lt;br /&gt;
      {&lt;br /&gt;
         RETURN_META(MRES_SUPERCEDE);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      /* Not needed, but good style */&lt;br /&gt;
      RETURN_META(MRES_IGNORED);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   void StartHooks()&lt;br /&gt;
   {&lt;br /&gt;
      SH_ADD_HOOK(IVEngineServer, LogPrint, engine, SH_MEMBER(this, &amp;amp;MyHooks::Hook_LogPrint), false);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   void StopHooks()&lt;br /&gt;
   {&lt;br /&gt;
      SH_REMOVE_HOOK(IVEngineServer, LogPrint, engine, SH_MEMBER(this, &amp;amp;MyHooks::Hook_LogPrint), false);&lt;br /&gt;
   }&lt;br /&gt;
};&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Manual Hooks=&lt;br /&gt;
In some cases, it may be necessary to support multiple, incompatible ABI branches of an interface.  For example, suppose you need to hook an application that may supply either version of these interfaces:&lt;br /&gt;
&lt;br /&gt;
Interface v1:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class Interface&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void Function1() =0;&lt;br /&gt;
   virtual bool Function2(int clam) =0;&lt;br /&gt;
};&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Interface v2:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class Interface&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual bool Function2(int clam) =0;&lt;br /&gt;
};&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Obviously, these two interfaces are backwards incompatible.  Manual hooks allow you to precisely define the structure of the virtual table, bypassing the compiler's rules.  These rules can be re-configured at runtime.&lt;br /&gt;
&lt;br /&gt;
==Declaration==&lt;br /&gt;
Declaring a manual hook is similar to declaring a normal/simple hook.  The syntax is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_DECL_MANUALHOOK&amp;lt;n&amp;gt;[_void](UniqueName, vtblIndex, vtblOffs, thisOffs, [return and param types])&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;UniqueName&amp;lt;/tt&amp;gt; is a unique identifier for the hook.  The &amp;lt;tt&amp;gt;vtblIndex&amp;lt;/tt&amp;gt; is the index into the virtual table at which the function lies.  In most compilers, this index starts from 0.  The &amp;lt;tt&amp;gt;vtblOffs&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;thisOffs&amp;lt;/tt&amp;gt; fields are used for multiple inheritance and are almost always 0 in modern compiler single inheritance.&lt;br /&gt;
&lt;br /&gt;
An example of hooking the two functions from the first interface version:&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_DECL_MANUALHOOK0_void(MHook_Function1, 0, 0, 0);&lt;br /&gt;
SH_DECL_MANUALHOOK1(MHook_Function2, 1, 0, 0, bool, int);&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Reconfiguring==&lt;br /&gt;
A manual hook can be ''reconfigured'', which will update its set offsets.  Reconfiguration automatically removes all hooks on the manual hook.  Let's say we want to reconfigure the &amp;lt;tt&amp;gt;Function2&amp;lt;/tt&amp;gt; hook in the case of the second version being detected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
void SwitchToNewerHooks()&lt;br /&gt;
{&lt;br /&gt;
   SH_MANUALHOOK_RECONFIGURE(MHook_Function2, 0, 0, 0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the hook was referenced by its unique identifier.&lt;br /&gt;
&lt;br /&gt;
==Adding Hooks==&lt;br /&gt;
Adding or removing hook binds is done via the following extra macros:&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_ADD_MANUALHOOK&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_REMOVE_MANUALHOOK&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These work similar to the original functions.  Example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;extern Interface *iface;&lt;br /&gt;
&lt;br /&gt;
bool Hook_Function2(int clam)&lt;br /&gt;
{&lt;br /&gt;
   RETURN_META_VALUE(MRES_IGNORED, false);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StartHooks()&lt;br /&gt;
{&lt;br /&gt;
   SH_ADD_MANUALHOOK(MHook_Function2, iface, SH_STATIC(Hook_Function2), false);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StopHooks()&lt;br /&gt;
{&lt;br /&gt;
   SH_REMOVE_MANUALHOOK(MHook_Function2, iface, SH_STATIC(Hook_Function2), false);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, a member function version would use &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt; instead.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Extended Removal Syntax=&lt;br /&gt;
The syntax described in the above sections is new as of SourceHook v4.5.  &amp;lt;tt&amp;gt;SH_REMOVE_HOOK&amp;lt;/tt&amp;gt; is, for all intents and purposes, optional.  There is another way to remove hooks.&lt;br /&gt;
&lt;br /&gt;
Each &amp;lt;tt&amp;gt;SH_ADD&amp;lt;/tt&amp;gt; macro returns a non-zero &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt; on success.  The same integer can be passed to the &amp;lt;tt&amp;gt;SH_REMOVE_HOOK_ID&amp;lt;/tt&amp;gt; macro, and the hook will be removed.  This alternate removal syntax can simplify code that uses multiple successive or dynamic hooks.&lt;br /&gt;
&lt;br /&gt;
Global hooks, described in a later section, require usage of &amp;lt;tt&amp;gt;SH_REMOVE_HOOK_ID&amp;lt;/tt&amp;gt; - that is, there is no helper macro to simplify removing a global hook.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Old Macros=&lt;br /&gt;
SourceHook v5.0 deprecates older macros that were used in earlier versions.  The macros are:&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_ADD_HOOK_STATICFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_ADD_HOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_STATIC&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_REMOVE_HOOK_STATICFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_REMOVE_HOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_STATIC&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_ADD_HOOK_MEMFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_ADD_HOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_REMOVE_HOOK_MEMFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_REMOVE_HOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_ADD_MANUALHOOK_STATICFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_ADD_MANUALHOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_STATIC&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_REMOVE_MANUALHOOK_STATICFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_REMOVE_MANUALHOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_STATIC&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_ADD_MANUALHOOK_MEMFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_ADD_MANUALHOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SH_REMOVE_MANUALHOOK_MEMFUNC&amp;lt;/tt&amp;gt; - Wrapper for &amp;lt;tt&amp;gt;SH_REMOVE_MANUALHOOK&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
These macros are fairly self explanatory.  The parameter where the &amp;lt;tt&amp;gt;SH_STATIC&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SH_MEMBER&amp;lt;/tt&amp;gt; macro would normally go is instead filled with the parameters to that macro.  &lt;br /&gt;
&lt;br /&gt;
This syntax is considered deprecated, but it is still supported.  Code written with these macros will continue to compile against older SourceHook versions.  If you are writing a plugin which must work against Metamod:Source 1.4 and 1.6, you will want to use the older macros for simplicity.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Global Hooks=&lt;br /&gt;
&amp;lt;b&amp;gt;Note:&amp;lt;/b&amp;gt; Global Hooks are only available in SourceHook v4.5 or later.&lt;br /&gt;
&lt;br /&gt;
Global hooks are unlike normal hooks in that the hook is invoked for ALL instances, rather than solely the given the instance the hook was bound to.  It is important to realize that this feature can be deceiving.  Consider the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class CBaseEntity&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void SetHealth(int health) =0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class CBaseCat : public CBaseEntity&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void SetHealth();&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class CBaseKitten : public CBaseCat&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void SetHealth();&lt;br /&gt;
};&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, &amp;lt;tt&amp;gt;CBaseCat&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;CBaseKitten&amp;lt;/tt&amp;gt; instances have ''separate virtual tables''.  Although they both derive from &amp;lt;tt&amp;gt;CBaseEntity&amp;lt;/tt&amp;gt;, they are separate virtual objects.  &amp;lt;b&amp;gt;Therefore, a global hook on &amp;lt;tt&amp;gt;CBaseEntity&amp;lt;/tt&amp;gt; will receive no invocations, and a hook on &amp;lt;tt&amp;gt;CBaseCat&amp;lt;/tt&amp;gt; will receive only &amp;lt;tt&amp;gt;CBaseCat&amp;lt;/tt&amp;gt; instances, as long as the instance is not a class derived from &amp;lt;tt&amp;gt;CBaseCat&amp;lt;/tt&amp;gt;&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
With this understanding in place, there are two separate syntaxes - one for simple hooks and one for manual hooks.  Additionally, there are two ways of declaring the virtual interface to use:&lt;br /&gt;
*An instance of the class can be passed.&lt;br /&gt;
*The direct address to the virtual table can be passed.&lt;br /&gt;
&lt;br /&gt;
They are essentially equivalent, although one may be more advantageous than the other (for example, if no instances are known, but the vtable address can be extracted via pattern searching).&lt;br /&gt;
&lt;br /&gt;
It is also important to note that global hooks are just a different method of &amp;quot;filtering.&amp;quot;  They fall into either the &amp;quot;simple&amp;quot; or &amp;quot;manual&amp;quot; category, and are otherwise exactly the same to those hooks.  Thus there are no separate return/declaration macros for global hooks.&lt;br /&gt;
&lt;br /&gt;
The macro &amp;lt;tt&amp;gt;META_IFACEPTR&amp;lt;/tt&amp;gt; is especially useful for global hooks.  See [[SourceHook_Development#Interface_Pointers_from_Hooks|Interface Pointers from Hooks]] near the end.&lt;br /&gt;
&lt;br /&gt;
Lastly, global hooks exclusively use the extended hooking syntax.  That means there exists only &amp;lt;tt&amp;gt;SH_ADD&amp;lt;/tt&amp;gt; macros.  &amp;lt;tt&amp;gt;SH_HOOK_REMOVE_ID&amp;lt;/tt&amp;gt; must be used and the hook ID generated via &amp;lt;tt&amp;gt;SH_ADD&amp;lt;/tt&amp;gt; must be cached.&lt;br /&gt;
&lt;br /&gt;
All examples will use the following code as a basis:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class Player&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void TakeDamage(int damage) =0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
void Hook_TakeDamage(int damage);&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Simple Hooks==&lt;br /&gt;
Two extra macros exist for adding a global hook:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
SH_ADD_VPHOOK(Interface, Function, Instance, Handler, Post)&lt;br /&gt;
SH_ADD_DVPHOOK(Interface, Function, VirtualTable, Handler, Post)&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
extern void *player_vtable;&lt;br /&gt;
HookId takedamage_hook = 0;&lt;br /&gt;
&lt;br /&gt;
void StartHooks()&lt;br /&gt;
{&lt;br /&gt;
   takedamage_hook = SH_ADD_DVPHOOK(Player, TakeDamage, player_vtable, SH_STATIC(Hook_TakeDamage), false);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StopHooks()&lt;br /&gt;
{&lt;br /&gt;
   if (takedamage_hook)&lt;br /&gt;
   {&lt;br /&gt;
      SH_REMOVE_HOOK_ID(takedamage_hook);&lt;br /&gt;
   }&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Manual Hooks==&lt;br /&gt;
Similarly, manual hooks are straightforward:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
SH_DECL_MANUALHOOK1_void(MHook_TakeDamage, 0, 0, 0, int);&lt;br /&gt;
&lt;br /&gt;
extern void *player_vtable;&lt;br /&gt;
int takedamage_hook = 0;&lt;br /&gt;
&lt;br /&gt;
void StartHooks()&lt;br /&gt;
{&lt;br /&gt;
   takedamage_hook = SH_ADD_MANUALDVPHOOK(MHook_TakeDamage, player_vtable, SH_STATIC(Hook_TakeDamage), false);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void StopHooks()&lt;br /&gt;
{&lt;br /&gt;
   if (takedamage_hook)&lt;br /&gt;
   {&lt;br /&gt;
      SH_REMOVE_HOOK_ID(takedamage_hook);&lt;br /&gt;
   }&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Modifying Parameters=&lt;br /&gt;
Consider another variation of the hooking process.  There is a hook on function X, which has one parameter.  The hook wants to change the value of this parameter transparently.  For example:&lt;br /&gt;
*Caller passes 5 into X.&lt;br /&gt;
*Hook changes the 5 to a 6.&lt;br /&gt;
*Hooked function receives a 6 and continues normally.&lt;br /&gt;
&lt;br /&gt;
SourceHook has a method for achieving this.  As an added bonus, the new parameters are passed to subsequent hooks.  That means the replacement process is as transparent as possible.  For this example, we'll use the following code, with an assumed hook on &amp;lt;tt&amp;gt;Player::TakeDamage&amp;lt;/tt&amp;gt; to the &amp;lt;tt&amp;gt;Hook_TakeDamage&amp;lt;/tt&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class Player&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void TakeDamage(int damage);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
void Hook_TakeDamage(int damage);&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our objective is to multiply the damage by 2.&lt;br /&gt;
&lt;br /&gt;
==Simple Hooks==&lt;br /&gt;
For simple hooks, changing parameters looks similar to an &amp;lt;tt&amp;gt;SH_CALL&amp;lt;/tt&amp;gt;.  The macros are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;RETURN_META_NEWPARAMS(Action, HookFunction, ([params]))&lt;br /&gt;
RETURN_META_VALUE_NEWPARAMS(Action, Value, HookFunction, ([params]))&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
void Hook_TakeDamage(int damage)&lt;br /&gt;
{&lt;br /&gt;
   RETURN_META_NEWPARAMS(MRES_IGNORED, &amp;amp;Player::TakeDamage, (damage * 2));&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the parenthesis enclosing the parameters are required.&lt;br /&gt;
&lt;br /&gt;
==Manual Hooks==&lt;br /&gt;
Manual hooks require slightly different macros.  They are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;RETURN_META_MNEWPARAMS(Action, UniqueName, ([params]));&lt;br /&gt;
RETURN_META_VALUE_MNEWPARAMS(Action, Value, UniqueName, ([params]));&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
SH_DECL_MANUALHOOK1_void(MHook_Player_TakeDamage, 0, 0, 0, int);&lt;br /&gt;
&lt;br /&gt;
void Hook_TakeDamage(int damage)&lt;br /&gt;
{&lt;br /&gt;
   RETURN_META_MNEWPARAMS(MRES_IGNORED, MHook_Player_TakeDamage, (damage *2));&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the parenthesis enclosing the parameters are required.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Bypassing Hooks=&lt;br /&gt;
Often, either to avoid certain functionality or to avoid infinite recursion, it is necessary to bypass all hooks on a hooked function, such that only the original function is called.  For instance, a previous blocked certain messages sent through &amp;lt;tt&amp;gt;LogPrint&amp;lt;/tt&amp;gt;.  In order to send that message, the hook needs to be bypassed.&lt;br /&gt;
&lt;br /&gt;
To way to do this is to use the &amp;lt;tt&amp;gt;SH_CALL&amp;lt;/tt&amp;gt; macro:&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_CALL(Instance, HookFunction)(params)&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_CALL(engine, &amp;amp;IVEngineServer::LogPrint)(&amp;quot;Secret Message&amp;quot;);&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, manual hooks have &amp;lt;tt&amp;gt;SH_MCALL&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;SH_DECL_MANUALHOOK1(MHook_Function2, 1, 0, 0, bool, int);&lt;br /&gt;
&lt;br /&gt;
bool Function2_Bypass(int clam)&lt;br /&gt;
{&lt;br /&gt;
   return SH_MCALL(iface, MHook_Function2)(clam);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Deprecated Syntax==&lt;br /&gt;
The syntax described above is used in SourceHook v5.0 and v4.5.  An older syntax, using a &amp;quot;CallClass&amp;quot; data type, was used in SourceHook v4.4 and lower.  This syntax was deprecated in v4.5 and completely removed in v5.0.  Upgrading from SourceHook v4.4 means that code referencing &amp;lt;tt&amp;gt;SH_GET_CALLCLASS&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SH_REMOVE_CALLCLASS&amp;lt;/tt&amp;gt; must be removed, and &amp;lt;tt&amp;gt;SH_CALL&amp;lt;/tt&amp;gt; simply needs an instance pointer instead.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Other Macros=&lt;br /&gt;
SourceHook contains a large variety of extra macros.  This section is a grab bag of the more commonly used ones.&lt;br /&gt;
&lt;br /&gt;
==Interface Pointers from Hooks==&lt;br /&gt;
Let's say you have the following hook:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;class Player&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
   virtual void TakeDamage(int damage);&lt;br /&gt;
   float GetDamageModifier();&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
void Hook_TakeDamage(int damage);&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
How can you get the &amp;lt;tt&amp;gt;Player&amp;lt;/tt&amp;gt; instance while in the hook?  This can be achieved via the &amp;lt;tt&amp;gt;META_IFACEPTR&amp;lt;/tt&amp;gt; macro.  Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;void Hook_TakeDamage(int damage)&lt;br /&gt;
{&lt;br /&gt;
   Player *pPlayer = META_IFACEPTR(Player);&lt;br /&gt;
&lt;br /&gt;
   int new_damage = (int)((pPlayer-&amp;gt;GetDamageModifier() + 0.3) * (float)damage);&lt;br /&gt;
&lt;br /&gt;
   RETURN_META_NEWPARAMS(MRES_IGNORED, &amp;amp;Player::TakeDamage, (new_damage));&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the class name should be passed to &amp;lt;tt&amp;gt;META_IFACEPTR&amp;lt;/tt&amp;gt;, not the pointer type.&lt;br /&gt;
&lt;br /&gt;
==Ignoring Reference Returns==&lt;br /&gt;
There is a special macro, &amp;lt;tt&amp;gt;RETURN_META_NOREF&amp;lt;/tt&amp;gt;, for ignoring a return value for reference-returning functions.  Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class ISomething&lt;br /&gt;
{&lt;br /&gt;
public:  &lt;br /&gt;
   virtual int &amp;amp; GetSomething() =0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int &amp;amp; Hook_GetSomething()&lt;br /&gt;
{&lt;br /&gt;
   RETURN_META_NOREF(MRES_IGNORED, int &amp;amp;);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Automatic hookmanager generation=&lt;br /&gt;
Normally, the SH_DECL_ macros generate a so-called &amp;quot;hook manager&amp;quot;, a function which is invoked instead of the original function and then calls the hooks and processes their return and &amp;lt;tt&amp;gt;META_RES&amp;lt;/tt&amp;gt; values.&lt;br /&gt;
&lt;br /&gt;
It is also possible to let SourceHook auto-generate the hook manager. This is neccessary if the function prototype is unknown at compile time (for example if hooks can be defined from third-party plugins of your plugin).&lt;br /&gt;
&lt;br /&gt;
Example Usage from a Metamod:Source plugin:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;quot;sourcehook_pibuilder.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// We want to hook a void (int, float) function&lt;br /&gt;
&lt;br /&gt;
// Request IHookManagerAutoGen interface&lt;br /&gt;
SourceHook::IHookManagerAutoGen *hmag =&lt;br /&gt;
    static_cast&amp;lt;SourceHook::IHookManagerAutoGen *&amp;gt;(ismm-&amp;gt;MetaFactory(MMIFACE_SH_HOOKMANAUTOGEN, NULL, NULL));&lt;br /&gt;
&lt;br /&gt;
// (check for hmag == NULL)&lt;br /&gt;
&lt;br /&gt;
// Build prototype information (using CProtoInfoBuilder helper class).&lt;br /&gt;
SourceHook::CProtoInfoBuilder protoInfo(SourceHook::ProtoInfo::CallConv_ThisCall);&lt;br /&gt;
protoInfo.AddParam(sizeof(int), SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal,&lt;br /&gt;
    NULL, NULL, NULL, NULL);&lt;br /&gt;
protoInfo.AddParam(sizeof(float), SourceHook::PassInfo::PassType_Float, SourceHook::PassInfo::PassFlag_ByVal,&lt;br /&gt;
    NULL, NULL, NULL, NULL);&lt;br /&gt;
&lt;br /&gt;
// Generate the hook manager&lt;br /&gt;
HookManagerPubFunc generatedHookMan = hmag-&amp;gt;MakeHookMan(protoInfo, 0 /* vtable offset */, 0 /* vtable index */);&lt;br /&gt;
&lt;br /&gt;
// Add the hook&lt;br /&gt;
int hookid = g_SHPtr-&amp;gt;AddHook(g_PLID, SourceHook::ISourceHook::Hook_Normal/Hook_VP/Hook_DVP, iface_ptr, thisptr_offs,&lt;br /&gt;
    generatedHookMan, handler, post);&lt;br /&gt;
&lt;br /&gt;
// ... (use the hook)&lt;br /&gt;
&lt;br /&gt;
// After you're done using the hook (cleanup)&lt;br /&gt;
// Remove the hook&lt;br /&gt;
g_SHPtr-&amp;gt;RemoveHookByID(hookid);&lt;br /&gt;
&lt;br /&gt;
// Release hook manager&lt;br /&gt;
hmag-&amp;gt;ReleaseHookMan(generatedHookMan);&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;CProtoInfoBuilder::AddParam&amp;lt;/tt&amp;gt; has 7 parameters:&lt;br /&gt;
* size: size of the type. This is sizeof(type) even if it is passed by reference!&lt;br /&gt;
* passtype: this can be PassType_Basic for integer types (char/short/int/...), PassType_Float for floating-point types (float/double) and PassType_Object for unions, structs and classes.&lt;br /&gt;
* passflags: flags. Has to contain either PassFlag_ByVal or PassFlag_ByRef.&lt;br /&gt;
* pNormalCtor: for PassType_Object, set this to the pointer to the user-defined default constructor of the object, if it has one.&lt;br /&gt;
* pCCtor: for PassType_Object, set this to the pointer to the user-defined copy constructor of the object, if it has one.&lt;br /&gt;
* pODtor: for PassType_Object, set this to the pointer to the user-defined destructor of the object, if it has one.&lt;br /&gt;
* pAssignOperator: for PassType_Object, set this to the pointer to the user-defined assignment operator of the object, if it has one.&lt;br /&gt;
&lt;br /&gt;
If you are hooking a non-void function, also call &amp;lt;tt&amp;gt;CProtoInfoBuilder::SetReturnType&amp;lt;/tt&amp;gt;. It has the same arguments as &amp;lt;tt&amp;gt;AddParam&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;handler&amp;lt;/tt&amp;gt; parameter of &amp;lt;tt&amp;gt;ISourceHook::AddHook&amp;lt;/tt&amp;gt; is a pointer to the ISHDelegate interface.&lt;br /&gt;
In C++, you construct ISHDelegates like this:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
class MyDelegate : public SourceHook::ISHDelegate&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
    // vtable index 0&lt;br /&gt;
    virtual bool IsEqual(ISHDelegate *pOtherDeleg)&lt;br /&gt;
    {&lt;br /&gt;
        // pOtherDeleg is guaranteed to be from the same plugin.&lt;br /&gt;
        // This function is only used for compat with the old SH_REMOVE_HOOK method.&lt;br /&gt;
        // if you don't want to use that with your hooks, you can simply return false here.&lt;br /&gt;
        // if for some reason you need it, a good idea could be comparing the vtable pointer:&lt;br /&gt;
        return *reinterpret_cast&amp;lt;void**&amp;gt;(this) == *reinterpret_cast&amp;lt;void**&amp;gt;(pOtherDeleg);&lt;br /&gt;
&lt;br /&gt;
        // But in general I'd just return false!&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // vtable index 1&lt;br /&gt;
    virtual void DeleteThis()&lt;br /&gt;
    {&lt;br /&gt;
        delete this;   // Called from SourceHook when this instance is not needed&lt;br /&gt;
                       // and should be deleted.&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // vtable index 2&lt;br /&gt;
    virtual ret_type Call(params)&lt;br /&gt;
    {&lt;br /&gt;
        // your code.&lt;br /&gt;
        // SH_DECL_ macros pass execution to the actual user's handler through a FastDelegate&lt;br /&gt;
        // which is stored as a member variable of the delegate class.&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first parameter of the CProtoInfoBuilder constructor (see example code above) is the calling convention in an extended sense. At the moment it can be either CallConv_ThisCall or (CallConv_ThisCall | CallConv_HasVafmt). The second value means that the function has printf-like string formatting. Then, the finaly ''const char *, ...'' arguments will be added automatically, and the Deleagte::Call method should have one more parameter: ''const char *formattedString''.&lt;br /&gt;
&lt;br /&gt;
pNormalCtor/pCCtor/pODtor/pAssignOperator should be found using offsets / sigscanning. If you are a C++ plugin and know the type at compile time, you can also use the following class:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
// Address of constructor/destructor&lt;br /&gt;
// (using wrappers)&lt;br /&gt;
template &amp;lt;class T&amp;gt;&lt;br /&gt;
class Ctor_Thunk&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
	void NormalConstructor()&lt;br /&gt;
	{&lt;br /&gt;
		new(this) T;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	void CopyConstructor(const T &amp;amp;other)&lt;br /&gt;
	{&lt;br /&gt;
		new(this) T(other);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	void Destructor()&lt;br /&gt;
	{&lt;br /&gt;
		reinterpret_cast&amp;lt;T*&amp;gt;(this)-&amp;gt;~T();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	const T&amp;amp; AssignOp(const T &amp;amp;other)&lt;br /&gt;
	{&lt;br /&gt;
		return (*reinterpret_cast&amp;lt;T*&amp;gt;(this) = other);&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
template &amp;lt;class T&amp;gt;&lt;br /&gt;
void *FindFuncAddr(T mfp)&lt;br /&gt;
{&lt;br /&gt;
	union&lt;br /&gt;
	{&lt;br /&gt;
		T a;&lt;br /&gt;
		void *b;&lt;br /&gt;
	} u;&lt;br /&gt;
	u.a = mfp;&lt;br /&gt;
	return u.b;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Usage:&lt;br /&gt;
FindFuncAddr(&amp;amp;Ctor_Thunk&amp;lt;type&amp;gt;::NormalConstructor)&lt;br /&gt;
// (if the type is a reference type, use it without &amp;amp; here)&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Embedding=&lt;br /&gt;
Embedding SourceHook in your own application or library is very easy.  The &amp;lt;tt&amp;gt;sourcehook.cpp&amp;lt;/tt&amp;gt; file must be compiled or linked into your project.  To instantiate the SourceHook engine, you must create a &amp;lt;tt&amp;gt;CSourceHookImpl&amp;lt;/tt&amp;gt; instance.  Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
/* Normally, just &amp;lt;sourcehook.h&amp;gt; is included, but this is needed to instantiate the engine. */&lt;br /&gt;
#include &amp;lt;sourcehook/sourcehook_impl.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
SourceHook::Impl::CSourceHookImpl g_SourceHook;&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To actually use SourceHook, it is necessary to have two global variables:&lt;br /&gt;
*&amp;lt;tt&amp;gt;g_PLID&amp;lt;/tt&amp;gt; - A unique integer that identifies the library using SourceHook.  This is used for removing all hooks a library is using.&lt;br /&gt;
*&amp;lt;tt&amp;gt;g_SHPtr&amp;lt;/tt&amp;gt; - A pointer to the &amp;lt;tt&amp;gt;SourceHook::ISourceHook&amp;lt;/tt&amp;gt; interface.&lt;br /&gt;
&lt;br /&gt;
Example header file:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
#include &amp;lt;sourcehook/sourcehook.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern SourceHook::ISourceHook *g_SHPtr;&lt;br /&gt;
extern int g_PLID;&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example addition to the global code:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
SourceHook::ISourceHook *g_SHPtr = &amp;amp;g_SourceHook;&lt;br /&gt;
int g_PLID = 0;&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Multiple Libraries/Shared Hooks==&lt;br /&gt;
If SourceHook is going to be used across multiple libraries in the same process, it is essential that only one instance of SourceHook be present.  Of course, that is only logical, since otherwise the instances would be replacing each other's virtual patches.&lt;br /&gt;
&lt;br /&gt;
In order to support this, each separate library must be given the &amp;lt;tt&amp;gt;ISourceHook&amp;lt;/tt&amp;gt; pointer and a unique &amp;lt;tt&amp;gt;g_PLID&amp;lt;/tt&amp;gt; value.  &amp;lt;tt&amp;gt;CSourceHookImpl&amp;lt;/tt&amp;gt; provides a few useful functions for managing hooks on &amp;quot;child&amp;quot; libraries or otherwise linked code.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;tt&amp;gt;PausePlugin()&amp;lt;/tt&amp;gt; - Silences any hooks from an ID, such that those hooks will not be called.&lt;br /&gt;
*&amp;lt;tt&amp;gt;UnpausePlugin()&amp;lt;/tt&amp;gt; - Un-silences any silenced hooks from an ID.&lt;br /&gt;
*&amp;lt;tt&amp;gt;UnloadPlugin()&amp;lt;/tt&amp;gt; - Clean-up any left-over hooks from an ID.&lt;br /&gt;
&lt;br /&gt;
[[Category:Metamod:Source Documentation]]&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Porting_to_x64&amp;diff=11689</id>
		<title>Porting to x64</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Porting_to_x64&amp;diff=11689"/>
		<updated>2024-05-08T23:04:26Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Add ABI shenanigans&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Many plugins are already compatible with the x64 architecture, but many that manipulate game memory (such as with hooks or patches) will require extensive revisions to run under the new 64-bit servers.&lt;br /&gt;
Overall, if your plugin:&lt;br /&gt;
* Uses the address natives or the Address type,&lt;br /&gt;
* Uses dhooks&lt;br /&gt;
* Uses sdkcalls or sdktools (''not sdkhooks'')&lt;br /&gt;
&lt;br /&gt;
...you will need to update your plugin for 64 bits.&lt;br /&gt;
&lt;br /&gt;
Extensions may be good to go with just a recompile for 64-bits, but some may need more extensives changes.&lt;br /&gt;
&lt;br /&gt;
== I'm having an issue! ==&lt;br /&gt;
&lt;br /&gt;
In general, '''prototypes need to be exactly correct''' (including class statics like copy/destruct/constructors) as there are now significantly more quirks that will cause ABIs to be laid out differently.&lt;br /&gt;
&lt;br /&gt;
Here are some things to check for that may be tripping you up:&lt;br /&gt;
&lt;br /&gt;
* The type you thought was an ''int'' was actually a ''size_t''!&lt;br /&gt;
* The type you put down as an int or pointer was actually a ''float''!&lt;br /&gt;
* Handling pointers as ''int''s when they should be ''void*'' or ''size_t'' (why would you do this??)&lt;br /&gt;
* '''The calling convention has changed.''' Make sure to account for this in detours and patches. Make sure your prototypes are exactly correct!&lt;br /&gt;
* '''In patches:''' Did you forget the 64-bit opcode prefix when assembling your patch? EAX and RAX are accessed using different opcode prefixes!&lt;br /&gt;
&lt;br /&gt;
=== Linux Calling Convention Quirks ===&lt;br /&gt;
&lt;br /&gt;
Linux uses the System-V x64 ABI. There are many great sources of documentation all over the internet: [https://wiki.osdev.org/System_V_ABI OSDev Wiki] [https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions Wikipedia]&lt;br /&gt;
* All calling conventions are now an up to 8-register fastcall depending on the types (!!)&lt;br /&gt;
* RCX can be a thisptr, first argument, or stack return pointer depending on the context&lt;br /&gt;
* '''Integer arguments and float arguments are passed in different registers!''' (generic for ints, SIMD registers for floats)&lt;br /&gt;
* Varargs are now more complex to call when floats are included in the vararg&lt;br /&gt;
&lt;br /&gt;
The exact value of return types with C++ shenanigans (destructors, etc) still needs to be figured out by someone. However, in general.&lt;br /&gt;
* The return argument is always passed in RCX, and will bump the thisptr to RDX (todo: confirm this)&lt;br /&gt;
* Some return types that are 128-bits will be returned in both RAX and RDX??&lt;br /&gt;
&lt;br /&gt;
=== MSVC Calling Convention Quirks ===&lt;br /&gt;
Microsoft has some excellent official documentation [https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170 in their MSVC docs].&lt;br /&gt;
&lt;br /&gt;
* All calling conventions are now a four-register fastcall&lt;br /&gt;
* RCX can be a thisptr OR the first arg! It is not always a thisptr now. RCX can also be the return value (see below), bumping the thisptr to RDX.&lt;br /&gt;
* '''Integer arguments and float arguments are passed in different registers!''' (generic for ints, SIMD registers for floats)&lt;br /&gt;
* All objects larger than 8 bytes are now passed exclusively by reference (even on the stack??)&lt;br /&gt;
* Float arguments passed to varargs need to be put in both the generic and SIMD register for the appropiate argument index. Varargs are still fastcalls... somehow...&lt;br /&gt;
* '''setjmp has new behavior''' and destroys objects as if the scope has been exited. (if you ''are'' using setjmp, good luck)&lt;br /&gt;
&lt;br /&gt;
Return types also have their usual obscure shenanigans. More specifically,&lt;br /&gt;
* The return argument is always passed in RCX, and will bump the thisptr to RDX (todo: confirm this)&lt;br /&gt;
* Returns with all types larger than 8 bytes occur on the stack&lt;br /&gt;
* Returns with any type that has a user-defined base classes, virtual methods, constructor, destructor, or copy operation happens on the stack (''regardless of size'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Porting Plugins ==&lt;br /&gt;
&lt;br /&gt;
=== Gamedata ===&lt;br /&gt;
&lt;br /&gt;
All signatures will need to be updated, and likely many offsets. &amp;quot;linux&amp;quot; is for 32-bit linux and &amp;quot;linux64&amp;quot; is for 64-bit linux.&lt;br /&gt;
&lt;br /&gt;
Todo: What is the equivalent for windows?&lt;br /&gt;
&lt;br /&gt;
=== Address Natives ===&lt;br /&gt;
&lt;br /&gt;
New address natives that support 64-bits are still under development&lt;br /&gt;
&lt;br /&gt;
=== DHooks ===&lt;br /&gt;
&lt;br /&gt;
DHooks does not support 64-bits at all for the time being. It will need heavy revisions to work under the new architecture, starting with better SourceHook support for the 64-bit architecture (see: hookmangen)&lt;br /&gt;
&lt;br /&gt;
=== SDKCalls ===&lt;br /&gt;
&lt;br /&gt;
SDKCalls will need to be updated to learn how to accept a thisptr. However, all non-raw calls (eg, those to entities or gamerules that does not require a thisptr) should be fine as long as none of the arguments are 64-bits (including 64-bit ints!)&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Documentation]]&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Porting_to_x64&amp;diff=11688</id>
		<title>Porting to x64</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Porting_to_x64&amp;diff=11688"/>
		<updated>2024-05-08T22:38:21Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Fix category naming???&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Many plugins are already compatible with the x64 architecture, but many that manipulate game memory (such as with hooks or patches) will require extensive revisions to run under the new 64-bit servers.&lt;br /&gt;
Overall, if your plugin:&lt;br /&gt;
* Uses the address natives or the Address type,&lt;br /&gt;
* Uses dhooks&lt;br /&gt;
* Uses sdkcalls or sdktools (''not sdkhooks'')&lt;br /&gt;
&lt;br /&gt;
...you will need to update your plugin for 64 bits.&lt;br /&gt;
&lt;br /&gt;
Extensions may be good to go with just a recompile for 64-bits, but some may need more extensives changes.&lt;br /&gt;
&lt;br /&gt;
== I'm having an issue! ==&lt;br /&gt;
Here are some things to check for that may be tripping you up:&lt;br /&gt;
&lt;br /&gt;
* The type you thought was an ''int'' was actually a ''size_t''!&lt;br /&gt;
* Passing pointers as ''int''s when they should be ''void*'' (why would you do this??)&lt;br /&gt;
* '''The calling convention has changed.''' Make sure to account for this in detours and patches. Make sure your prototypes are exactly correct!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Porting Plugins ==&lt;br /&gt;
&lt;br /&gt;
=== Gamedata ===&lt;br /&gt;
&lt;br /&gt;
All signatures will need to be updated, and likely many offsets. &amp;quot;linux&amp;quot; is for 32-bit linux and &amp;quot;linux64&amp;quot; is for 64-bit linux.&lt;br /&gt;
&lt;br /&gt;
Todo: What is the equivalent for windows?&lt;br /&gt;
&lt;br /&gt;
=== Address Natives ===&lt;br /&gt;
&lt;br /&gt;
New address natives that support 64-bits are still under development&lt;br /&gt;
&lt;br /&gt;
=== DHooks ===&lt;br /&gt;
&lt;br /&gt;
DHooks does not support 64-bits at all for the time being. It will need heavy revisions to work under the new architecture, starting with better SourceHook support for the 64-bit architecture (see: hookmangen)&lt;br /&gt;
&lt;br /&gt;
=== SDKCalls ===&lt;br /&gt;
&lt;br /&gt;
SDKCalls will need to be updated to learn how to accept a thisptr. However, all non-raw calls (eg, those to entities or gamerules that does not require a thisptr) should be fine as long as none of the arguments are 64-bits (including 64-bit ints!)&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Documentation]]&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Porting_to_x64&amp;diff=11687</id>
		<title>Porting to x64</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Porting_to_x64&amp;diff=11687"/>
		<updated>2024-05-08T22:35:28Z</updated>

		<summary type="html">&lt;p&gt;Mooshua: Initial draft of porting page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Many plugins are already compatible with the x64 architecture, but many that manipulate game memory (such as with hooks or patches) will require extensive revisions to run under the new 64-bit servers.&lt;br /&gt;
Overall, if your plugin:&lt;br /&gt;
* Uses the address natives or the Address type,&lt;br /&gt;
* Uses dhooks&lt;br /&gt;
* Uses sdkcalls or sdktools (''not sdkhooks'')&lt;br /&gt;
&lt;br /&gt;
...you will need to update your plugin for 64 bits.&lt;br /&gt;
&lt;br /&gt;
Extensions may be good to go with just a recompile for 64-bits, but some may need more extensives changes.&lt;br /&gt;
&lt;br /&gt;
== I'm having an issue! ==&lt;br /&gt;
Here are some things to check for that may be tripping you up:&lt;br /&gt;
&lt;br /&gt;
* The type you thought was an ''int'' was actually a ''size_t''!&lt;br /&gt;
* Passing pointers as ''int''s when they should be ''void*'' (why would you do this??)&lt;br /&gt;
* '''The calling convention has changed.''' Make sure to account for this in detours and patches. Make sure your prototypes are exactly correct!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Porting Plugins ==&lt;br /&gt;
&lt;br /&gt;
=== Gamedata ===&lt;br /&gt;
&lt;br /&gt;
All signatures will need to be updated, and likely many offsets. &amp;quot;linux&amp;quot; is for 32-bit linux and &amp;quot;linux64&amp;quot; is for 64-bit linux.&lt;br /&gt;
&lt;br /&gt;
Todo: What is the equivalent for windows?&lt;br /&gt;
&lt;br /&gt;
=== Address Natives ===&lt;br /&gt;
&lt;br /&gt;
New address natives that support 64-bits are still under development&lt;br /&gt;
&lt;br /&gt;
=== DHooks ===&lt;br /&gt;
&lt;br /&gt;
DHooks does not support 64-bits at all for the time being. It will need heavy revisions to work under the new architecture, starting with better SourceHook support for the 64-bit architecture (see: hookmangen)&lt;br /&gt;
&lt;br /&gt;
=== SDKCalls ===&lt;br /&gt;
&lt;br /&gt;
SDKCalls will need to be updated to learn how to accept a thisptr. However, all non-raw calls (eg, those to entities or gamerules that does not require a thisptr) should be fine as long as none of the arguments are 64-bits (including 64-bit ints!)&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Documentation|Categories]]&lt;/div&gt;</summary>
		<author><name>Mooshua</name></author>
		
	</entry>
</feed>