<?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=Sawce</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=Sawce"/>
	<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/Special:Contributions/Sawce"/>
	<updated>2026-04-16T17:50:42Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.6</generator>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=CCSGameRules_Offset_List_(Counter-Strike:_Source)&amp;diff=6233</id>
		<title>CCSGameRules Offset List (Counter-Strike: Source)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=CCSGameRules_Offset_List_(Counter-Strike:_Source)&amp;diff=6233"/>
		<updated>2008-09-21T01:06:21Z</updated>

		<summary type="html">&lt;p&gt;Sawce: Undo revision 6230 by Matt29addai (Talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;For use when using [[Virtual Offsets (Source Mods)|virtual offsets]].&lt;br /&gt;
&lt;br /&gt;
This is the list of offsets I've been using. These are the &amp;lt;b&amp;gt;Linux&amp;lt;/b&amp;gt; offsets. &amp;lt;b&amp;gt;Windows offsets are 1 less.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The List ==&lt;br /&gt;
This comes from the symbol tables, so you'll have to look in the SDK for return types...or guess for the CSS specific functions near the end.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Last Updated 28 April 2008&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Auto reconstructed from vtable block @ 0x00B446E0&lt;br /&gt;
// from &amp;quot;server_i486.so&amp;quot;, by ida_vtables.idc&lt;br /&gt;
0	CGameRules::Name(void)&lt;br /&gt;
1	CBaseGameSystemPerFrame::Init(void)&lt;br /&gt;
2	CBaseGameSystemPerFrame::Shutdown(void)&lt;br /&gt;
3	CCSGameRules::LevelInitPreEntity(void)&lt;br /&gt;
4	CCSGameRules::LevelInitPostEntity(void)&lt;br /&gt;
5	CBaseGameSystemPerFrame::LevelShutdownPreEntity(void)&lt;br /&gt;
6	CBaseGameSystemPerFrame::LevelShutdownPostEntity(void)&lt;br /&gt;
7	CBaseGameSystemPerFrame::OnSave(void)&lt;br /&gt;
8	CBaseGameSystemPerFrame::OnRestore(void)&lt;br /&gt;
9	CBaseGameSystemPerFrame::SafeRemoveIfDesired(void)&lt;br /&gt;
10	CBaseGameSystemPerFrame::IsPerFrame(void)&lt;br /&gt;
11	CCSGameRules::~CCSGameRules()&lt;br /&gt;
12	CCSGameRules::~CCSGameRules()&lt;br /&gt;
13	CBaseGameSystemPerFrame::FrameUpdatePrePlayerRunCommand(void)&lt;br /&gt;
14	CBaseGameSystemPerFrame::FrameUpdatePreEntityThink(void)&lt;br /&gt;
15	CGameRules::FrameUpdatePostEntityThink(void)&lt;br /&gt;
16	CBaseGameSystemPerFrame::PreClientUpdate(void)&lt;br /&gt;
17	CCSGameRules::_GetClassName(void)&lt;br /&gt;
18	CMultiplayRules::SwitchToNextBestWeapon(CBaseCombatCharacter *,CBaseCombatWeapon *)&lt;br /&gt;
19	CCSGameRules::GetNextBestWeapon(CBaseCombatCharacter *,CBaseCombatWeapon *)&lt;br /&gt;
20	CCSGameRules::ShouldCollide(int,int)&lt;br /&gt;
21	CCSGameRules::DefaultFOV(void)&lt;br /&gt;
22	CCSGameRules::GetViewVectors(void)const&lt;br /&gt;
23	CGameRules::GetAmmoDamage(CBaseEntity *,CBaseEntity *,int)&lt;br /&gt;
24	CGameRules::GetDamageMultiplier(void)&lt;br /&gt;
25	CMultiplayRules::IsMultiplayer(void)&lt;br /&gt;
26	CCSGameRules::GetEncryptionKey(void)&lt;br /&gt;
27	CCSGameRules::LevelShutdown(void)&lt;br /&gt;
28	CTeamplayRules::Precache(void)&lt;br /&gt;
29	CMultiplayRules::RefreshSkillData(bool)&lt;br /&gt;
30	CCSGameRules::Think(void)&lt;br /&gt;
31	CMultiplayRules::IsAllowedToSpawn(CBaseEntity *)&lt;br /&gt;
32	CCSGameRules::EndGameFrame(void)&lt;br /&gt;
33	CGameRules::IsSkillLevel(int)&lt;br /&gt;
34	CGameRules::GetSkillLevel(void)&lt;br /&gt;
35	CGameRules::OnSkillLevelChanged(int)&lt;br /&gt;
36	CGameRules::SetSkillLevel(int)&lt;br /&gt;
37	CMultiplayRules::FAllowFlashlight(void)&lt;br /&gt;
38	CCSGameRules::FShouldSwitchWeapon(CBasePlayer *,CBaseCombatWeapon *)&lt;br /&gt;
39	CMultiplayRules::IsDeathmatch(void)&lt;br /&gt;
40	CTeamplayRules::IsTeamplay(void)&lt;br /&gt;
41	CMultiplayRules::IsCoOp(void)&lt;br /&gt;
42	CCSGameRules::GetGameDescription(void)&lt;br /&gt;
43	CMultiplayRules::ClientConnected(edict_t *,char  const*,char  const*,char *,int)&lt;br /&gt;
44	CTeamplayRules::InitHUD(CBasePlayer *)&lt;br /&gt;
45	CCSGameRules::ClientDisconnected(edict_t *)&lt;br /&gt;
46	CCSGameRules::FlPlayerFallDamage(CBasePlayer *)&lt;br /&gt;
47	CTeamplayRules::FPlayerCanTakeDamage(CBasePlayer *,CBaseEntity *)&lt;br /&gt;
48	CTeamplayRules::ShouldAutoAim(CBasePlayer *,edict_t *)&lt;br /&gt;
49	CGameRules::GetAutoAimScale(CBasePlayer *)&lt;br /&gt;
50	CGameRules::ShouldUseRobustRadiusDamage(CBaseEntity *)&lt;br /&gt;
51	CCSGameRules::RadiusDamage(CTakeDamageInfo  const&amp;amp;,Vector  const&amp;amp;,float,int,CBaseEntity *)&lt;br /&gt;
52	CCSGameRules::FlPlayerFallDeathDoesScreenFade(CBasePlayer *)&lt;br /&gt;
53	CMultiplayRules::AllowDamage(CBaseEntity *,CTakeDamageInfo  const&amp;amp;)&lt;br /&gt;
54	CCSGameRules::PlayerSpawn(CBasePlayer *)&lt;br /&gt;
55	CMultiplayRules::PlayerThink(CBasePlayer *)&lt;br /&gt;
56	CCSGameRules::FPlayerCanRespawn(CBasePlayer *)&lt;br /&gt;
57	CMultiplayRules::FlPlayerSpawnTime(CBasePlayer *)&lt;br /&gt;
58	CCSGameRules::GetPlayerSpawnSpot(CBasePlayer *)&lt;br /&gt;
59	CCSGameRules::IsSpawnPointValid(CBaseEntity *,CBasePlayer *)&lt;br /&gt;
60	CMultiplayRules::AllowAutoTargetCrosshair(void)&lt;br /&gt;
61	CCSGameRules::ClientCommand(char  const*,CBaseEntity *)&lt;br /&gt;
62	CCSGameRules::ClientSettingsChanged(CBasePlayer *)&lt;br /&gt;
63	CTeamplayRules::IPointsForKill(CBasePlayer *,CBasePlayer *)&lt;br /&gt;
64	CCSGameRules::PlayerKilled(CBasePlayer *,CTakeDamageInfo  const&amp;amp;)&lt;br /&gt;
65	CCSGameRules::DeathNotice(CBasePlayer *,CTakeDamageInfo  const&amp;amp;)&lt;br /&gt;
66	CGameRules::GetCustomKillString(CTakeDamageInfo  const&amp;amp;)&lt;br /&gt;
67	CGameRules::AdjustPlayerDamageInflicted(float)&lt;br /&gt;
68	CGameRules::AdjustPlayerDamageTaken(CTakeDamageInfo *)&lt;br /&gt;
69	CMultiplayRules::CanHavePlayerItem(CBasePlayer *,CBaseCombatWeapon *)&lt;br /&gt;
70	CMultiplayRules::WeaponShouldRespawn(CBaseCombatWeapon *)&lt;br /&gt;
71	CMultiplayRules::FlWeaponRespawnTime(CBaseCombatWeapon *)&lt;br /&gt;
72	CMultiplayRules::FlWeaponTryRespawn(CBaseCombatWeapon *)&lt;br /&gt;
73	CMultiplayRules::VecWeaponRespawnSpot(CBaseCombatWeapon *)&lt;br /&gt;
74	CMultiplayRules::CanHaveItem(CBasePlayer *,CItem *)&lt;br /&gt;
75	CMultiplayRules::PlayerGotItem(CBasePlayer *,CItem *)&lt;br /&gt;
76	CMultiplayRules::ItemShouldRespawn(CItem *)&lt;br /&gt;
77	CMultiplayRules::FlItemRespawnTime(CItem *)&lt;br /&gt;
78	CMultiplayRules::VecItemRespawnSpot(CItem *)&lt;br /&gt;
79	CMultiplayRules::VecItemRespawnAngles(CItem *)&lt;br /&gt;
80	CGameRules::CanHaveAmmo(CBaseCombatCharacter *,int)&lt;br /&gt;
81	CGameRules::CanHaveAmmo(CBaseCombatCharacter *,char  const*)&lt;br /&gt;
82	CMultiplayRules::PlayerGotAmmo(CBaseCombatCharacter *,char *,int)&lt;br /&gt;
83	CGameRules::GetAmmoQuantityScale(int)&lt;br /&gt;
84	CCSGameRules::InitDefaultAIRelationships(void)&lt;br /&gt;
85	CCSGameRules::AIClassText(int)&lt;br /&gt;
86	CMultiplayRules::FlHealthChargerRechargeTime(void)&lt;br /&gt;
87	CMultiplayRules::FlHEVChargerRechargeTime(void)&lt;br /&gt;
88	CMultiplayRules::DeadPlayerWeapons(CBasePlayer *)&lt;br /&gt;
89	CMultiplayRules::DeadPlayerAmmo(CBasePlayer *)&lt;br /&gt;
90	CTeamplayRules::GetTeamID(CBaseEntity *)&lt;br /&gt;
91	CTeamplayRules::PlayerRelationship(CBaseEntity *,CBaseEntity *)&lt;br /&gt;
92	CTeamplayRules::PlayerCanHearChat(CBasePlayer *,CBasePlayer *)&lt;br /&gt;
93	CTeamplayRules::GetTeamIndex(char  const*)&lt;br /&gt;
94	CTeamplayRules::GetIndexedTeamName(int)&lt;br /&gt;
95	CTeamplayRules::IsValidTeam(char  const*)&lt;br /&gt;
96	CTeamplayRules::ChangePlayerTeam(CBasePlayer *,char  const*,bool,bool)&lt;br /&gt;
97	CCSGameRules::SetDefaultPlayerTeam(CBasePlayer *)&lt;br /&gt;
98	CCSGameRules::UpdateClientData(CBasePlayer *)&lt;br /&gt;
99	CCSGameRules::PlayTextureSounds(void)&lt;br /&gt;
100	CMultiplayRules::PlayFootstepSounds(CBasePlayer *)&lt;br /&gt;
101	CCSGameRules::FAllowNPCs(void)&lt;br /&gt;
102	CMultiplayRules::EndMultiplayerGame(void)&lt;br /&gt;
103	CGameRules::WeaponTraceEntity(CBaseEntity *,Vector  const&amp;amp;,Vector  const&amp;amp;,unsigned int,CGameTrace *)&lt;br /&gt;
104	CCSGameRules::CreateStandardEntities(void)&lt;br /&gt;
105	CCSGameRules::GetChatPrefix(bool,CBasePlayer *)&lt;br /&gt;
106	CCSGameRules::GetChatLocation(bool,CBasePlayer *)&lt;br /&gt;
107	CCSGameRules::GetChatFormat(bool,CBasePlayer *)&lt;br /&gt;
108	CGameRules::ShouldBurningPropsEmitLight(void)&lt;br /&gt;
109	CGameRules::InRoundRestart(void)&lt;br /&gt;
110	CGameRules::CanEntityBeUsePushed(CBaseEntity *)&lt;br /&gt;
111	CCSGameRules::CreateCustomNetworkStringTables(void)&lt;br /&gt;
112	CMultiplayRules::GetNextLevelName(char *,int)&lt;br /&gt;
113	CMultiplayRules::ChangeLevel(void)&lt;br /&gt;
114	CCSGameRules::GoToIntermission(void)&lt;br /&gt;
115	CCSGameRules::SetAllowWeaponSwitch(bool)&lt;br /&gt;
116	CCSGameRules::GetAllowWeaponSwitch(void)&lt;br /&gt;
117	std::bad_cast::~bad_cast()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Iroh_Migration&amp;diff=5932</id>
		<title>Iroh Migration</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Iroh_Migration&amp;diff=5932"/>
		<updated>2008-06-08T05:49:10Z</updated>

		<summary type="html">&lt;p&gt;Sawce: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__FORCETOC__&lt;br /&gt;
sente to iroh migration plans&lt;br /&gt;
&lt;br /&gt;
=TODO List=&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;strike&amp;gt;Shutdown all Sente servers except e-mail.&amp;lt;/strike&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;strike&amp;gt;Move CVS/SVN to Iroh.&amp;lt;/strike&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Move any &amp;quot;root&amp;quot; stuff to Iroh (such as scripts).&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;strike&amp;gt;Open a port on Iroh so Sente can use its MySQL.&amp;lt;/strike&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;strike&amp;gt;Move MySQL.&amp;lt;/strike&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;&amp;lt;strike&amp;gt;Start a MySQL proxy from Sente to Iroh.&amp;lt;/strike&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Move all owned and movable sites from Sente to Iroh.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Change IP addresses on owned domains.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Bring Iroh web services &amp;lt;strike&amp;gt;and MySQL&amp;lt;/strike&amp;gt; online.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Move all cronjobs for moved sites.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Create web proxies from Sente to Iroh for all moved sites.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Bring remaining Sente web services back online.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Repeat processes as hostees can be contacted for IP changes.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Create new e-mail services on iroh, verify that they work.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Move e-mail boxes from Sente to Iroh.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Change e-mail IP address.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Movable Owned Sites=&lt;br /&gt;
*ampaste.net&lt;br /&gt;
*&amp;lt;strike&amp;gt;metamodsource.net&amp;lt;/strike&amp;gt;&lt;br /&gt;
*&amp;lt;strike&amp;gt;cvs.alliedmods.net&amp;lt;/strike&amp;gt;&lt;br /&gt;
*&amp;lt;strike&amp;gt;svn.alliedmods.net&amp;lt;/strike&amp;gt;&lt;br /&gt;
*&amp;lt;strike&amp;gt;users.svn.alliedmods.net&amp;lt;/strike&amp;gt;&lt;br /&gt;
*&amp;lt;strike&amp;gt;amxmodx.org&amp;lt;/strike&amp;gt;&lt;br /&gt;
*tcwonline.org&lt;br /&gt;
*&amp;lt;strike&amp;gt;forums.alliedmods.net&amp;lt;/strike&amp;gt;&lt;br /&gt;
*www.alliedmods.net&lt;br /&gt;
*&amp;lt;strike&amp;gt;bugs.alliedmods.net&amp;lt;/strike&amp;gt;&lt;br /&gt;
*docs.sourcemod.net&lt;br /&gt;
*&amp;lt;strike&amp;gt;www.sourcemod.net&amp;lt;/strike&amp;gt;&lt;br /&gt;
**bring symbol archive back up&lt;br /&gt;
*&amp;lt;strike&amp;gt;wiki.alliedmods.net&amp;lt;/strike&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Movable Hosted Sites=&lt;br /&gt;
*&amp;lt;strike&amp;gt;urahara.amxmodx.org&amp;lt;/strike&amp;gt; (HAG)&lt;br /&gt;
*jaguar.alliedmods.net&lt;br /&gt;
*shero.alliedmods.net&lt;br /&gt;
*uaio.amxmodx.org&lt;br /&gt;
*jghg.amxmodx.org&lt;br /&gt;
*electricmole.alliedmods.net&lt;br /&gt;
*&amp;lt;strike&amp;gt;bailopan.net&amp;lt;/strike&amp;gt;&lt;br /&gt;
*&amp;lt;strike&amp;gt;dav.bailopan.net&amp;lt;/strike&amp;gt; (REMOVED)&lt;br /&gt;
*whitewolf.sourcemod.net&lt;br /&gt;
&lt;br /&gt;
=Odds and Ends=&lt;br /&gt;
*Turn DS's alliedmods e-mail address into a real account instead of an alias&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMX_Mod_X_1.8.0_Changes&amp;diff=5012</id>
		<title>AMX Mod X 1.8.0 Changes</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMX_Mod_X_1.8.0_Changes&amp;diff=5012"/>
		<updated>2007-08-08T02:35:32Z</updated>

		<summary type="html">&lt;p&gt;Sawce: /* Plugin Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;AMX Mod X 1.8 is a large feature release with many changes, both to the development API and user-mode features.&lt;br /&gt;
&lt;br /&gt;
=Changelog=&lt;br /&gt;
==Overall Changes==&lt;br /&gt;
*Added a new module, Ham Sandwich, for hooking virtual CBaseEntity functions in mods.&lt;br /&gt;
*Command flags are now initially dumped to disk and can be edited via &amp;lt;tt&amp;gt;configs/cmdaccess.ini&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*Added {{AMBug|48738}}: Romanian translation from X-5173.&lt;br /&gt;
*Added {{AMBug|50741}} and {{AMBug|43830}}: per-map plugins files can now be prefixed based.&lt;br /&gt;
*Added {{amb|17}}: New menu rendering is now more consistent; non-consistent controls are deprecated.&lt;br /&gt;
*Added {{amb|32}}: The server console commands &amp;quot;amxx cvars&amp;quot; and &amp;quot;amxx cmds&amp;quot; can now filter by plugin.&lt;br /&gt;
*Added {{amb|122}}: Log file names now include a four-digit year.&lt;br /&gt;
*Fixed {{amb|18}}: New menus are now properly destroyed if overridden.&lt;br /&gt;
*Fixed {{amb|46}}: &amp;lt;tt&amp;gt;is_user_bot&amp;lt;/tt&amp;gt; had some false positives.&lt;br /&gt;
*Fixed {{amb|69}}: Fixed Metamod trying to reload AMX Mod X against a poorly configured clock.&lt;br /&gt;
*Fixed {{amb|207}}: New menus now display &amp;quot;0&amp;quot; instead of &amp;quot;10.&amp;quot;&lt;br /&gt;
*Fixed {{amb|208}}: New menus did not reset callback results after each call.&lt;br /&gt;
*Fixed {{amb|200}}: Dynamic/fake natives were not re-entrant.&lt;br /&gt;
*Fixed {{amb|244}}: Run-time errors blocked forwards.&lt;br /&gt;
*Fixed {{amb|305}}: Core crashed on mods that removed the standard &amp;lt;tt&amp;gt;mp_timelimit&amp;lt;/tt&amp;gt; cvar.&lt;br /&gt;
*Fixed many various internal new menu rendering and item selection bugs.&lt;br /&gt;
==Scripting Changes==&lt;br /&gt;
*Added natives for dynamic global arrays.&lt;br /&gt;
*Added a new, magic &amp;lt;tt&amp;gt;any&amp;lt;/tt&amp;gt; tag from [[SourceMod]].&lt;br /&gt;
*Added a &amp;lt;tt&amp;gt;charsmax&amp;lt;/tt&amp;gt; operator for safe sizeof(string)-1 usage.&lt;br /&gt;
*Added &amp;lt;tt&amp;gt;set_pcvar_string&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added &amp;lt;tt&amp;gt;LookupLangKey&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added &amp;lt;tt&amp;gt;SQL_QuoteString&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added &amp;lt;tt&amp;gt;[g|s]et_pdata_cbase[_safe]&amp;lt;/tt&amp;gt;() to the Ham Sandwich module.&lt;br /&gt;
*Added &amp;lt;tt&amp;gt;geoip_code[2|3]_ex&amp;lt;/tt&amp;gt;(), which address a serious issue in the now deprecated &amp;lt;tt&amp;gt;geoip_code[2|3]&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added &amp;lt;tt&amp;gt;lookup_sequence&amp;lt;/tt&amp;gt;(), &amp;lt;tt&amp;gt;set_controller&amp;lt;/tt&amp;gt;(), &amp;lt;tt&amp;gt;set_pev_string&amp;lt;/tt&amp;gt;(), and &amp;lt;tt&amp;gt;pev_serial&amp;lt;/tt&amp;gt;() to Fakemeta.&lt;br /&gt;
*Added &amp;lt;tt&amp;gt;ns_get_user_team&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*Added a menu property to change the numbering color.&lt;br /&gt;
*Added {{amb|27}}: &amp;lt;tt&amp;gt;SQL_Rewind&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|37}}: &amp;lt;tt&amp;gt;cs_[g|s]et_user_submodel&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|38}}: &amp;lt;tt&amp;gt;cs_[g|s]et_user_lastactivity&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|39}}: &amp;lt;tt&amp;gt;cs_[g|s]et_hostage_lastuse&amp;lt;/tt&amp;gt;() and &amp;lt;tt&amp;gt;cs_[g|s]et_hostage_nextuser&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|63}}: &amp;lt;tt&amp;gt;floatmin&amp;lt;/tt&amp;gt;(), &amp;lt;tt&amp;gt;floatmax&amp;lt;/tt&amp;gt;(), and &amp;lt;tt&amp;gt;floatclamp()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*Added {{amb|76}}: Formatting functions can now use %x or %X for hexadecimal numbers.&lt;br /&gt;
*Added {{amb|92}}: &amp;lt;tt&amp;gt;create_tr2&amp;lt;/tt&amp;gt;() and &amp;lt;tt&amp;gt;free_tr2&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|205}}: &amp;lt;tt&amp;gt;cs_[g|s]et_c4_explode_time&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|216}}: &amp;lt;tt&amp;gt;SQL_MakeStdTuple&amp;lt;/tt&amp;gt;() now has a timeout parameter.&lt;br /&gt;
*Added {{amb|237}}: Fakemeta can now call &amp;quot;ServerPrint.&amp;quot;&lt;br /&gt;
*Added {{amb|242}}: &amp;lt;tt&amp;gt;cs_[g|s]et_user_hostagekills&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|245}}: &amp;lt;tt&amp;gt;precache_sound&amp;lt;/tt&amp;gt; now returns a precache index.&lt;br /&gt;
*Added {{amb|261}}: &amp;lt;tt&amp;gt;has_flag&amp;lt;/tt&amp;gt;() and &amp;lt;tt&amp;gt;has_all_flags&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|291}}: &amp;lt;tt&amp;gt;cs_[g|s]et_c4_defusing&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|673}}: &amp;lt;tt&amp;gt;regex_compile&amp;lt;/tt&amp;gt;() and &amp;lt;tt&amp;gt;regex_match_c&amp;lt;/tt&amp;gt; for pre-compiling expressions.&lt;br /&gt;
*Added {{AMBug|46213}}: &amp;lt;tt&amp;gt;player_menu_info&amp;lt;/tt&amp;gt;() now returns a page number.&lt;br /&gt;
*Added {{AMBug|51064}}: Some parameters to &amp;lt;tt&amp;gt;get_plugin&amp;lt;/tt&amp;gt; are now optional.&lt;br /&gt;
*Added {{AMBug|50610}}: Some parameters to &amp;lt;tt&amp;gt;get_user_weapon&amp;lt;/tt&amp;gt; are now optional.&lt;br /&gt;
*Added {{AMBug|48841}}: &amp;lt;tt&amp;gt;tfc_is_user_feigning&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{AMBug|45664}}: &amp;lt;tt&amp;gt;tfc_is_team_ally&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Fixed {{AMBug|49337}}: &amp;lt;tt&amp;gt;get_pcvar_float&amp;lt;/tt&amp;gt;() malfunctioned on high numbers.&lt;br /&gt;
*Fixed {{amb|78}}: &amp;lt;tt&amp;gt;get_concmdsnum&amp;lt;/tt&amp;gt; could return an incorrect result.&lt;br /&gt;
*Fixed {{amb|85}}: Tag mismatches on &amp;lt;tt&amp;gt;ShowSyncHudMsg&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Fixed {{amb|90}}: &amp;lt;tt&amp;gt;set_native_filter&amp;lt;/tt&amp;gt;() did not work in rare cases.&lt;br /&gt;
*Fixed {{amb|107}}: &amp;lt;tt&amp;gt;socket_open&amp;lt;/tt&amp;gt;() didn't return an error by reference.&lt;br /&gt;
*Fixed {{amb|110}}: &amp;lt;tt&amp;gt;socket_change&amp;lt;/tt&amp;gt;() could return 1 on certain failures.&lt;br /&gt;
*Fixed {{amb|116}}: &amp;lt;tt&amp;gt;DispatchKeyValue&amp;lt;/tt&amp;gt;() did not work on worldspawn (entity 0).&lt;br /&gt;
*Fixed {{amb|149}}: &amp;lt;tt&amp;gt;register_event&amp;lt;/tt&amp;gt; with the &amp;quot;e&amp;quot; flag could catch incorrect players.&lt;br /&gt;
*Fixed {{amb|230}}: &amp;lt;tt&amp;gt;radius_damage&amp;lt;/tt&amp;gt;() didn't kill players on all mods.&lt;br /&gt;
*Fixed {{amb|257}}: &amp;lt;tt&amp;gt;get_user_origin&amp;lt;/tt&amp;gt;() mode 4 had false positives.&lt;br /&gt;
*Fixed {{amb|343}}: &amp;lt;tt&amp;gt;TFC_ClearModel&amp;lt;/tt&amp;gt;() did not function as documented.&lt;br /&gt;
*Fixed {{amb|421}}: &amp;lt;tt&amp;gt;get_user_weapons&amp;lt;/tt&amp;gt;() could omit a weapon on Day of Defeat.&lt;br /&gt;
*Fixed {{amb|437}}: &amp;lt;tt&amp;gt;dod_set_user_kills&amp;lt;/tt&amp;gt;() and &amp;lt;tt&amp;gt;dod_set_user_score&amp;lt;/tt&amp;gt;() could mess up the scoreboard.&lt;br /&gt;
*Fixed {{amb|519}}: &amp;lt;tt&amp;gt;geoip_code[2|3]&amp;lt;/tt&amp;gt;() buffer overflowed on error.&lt;br /&gt;
*Fixed {{amb|736}}: &amp;lt;tt&amp;gt;find_entity&amp;lt;/tt&amp;gt;() was defined twice.&lt;br /&gt;
*Fixed a memory leak in &amp;lt;tt&amp;gt;SortCustom1D&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Fixed a crash bug in &amp;lt;tt&amp;gt;fwrite_blocks&amp;lt;/tt&amp;gt;().&lt;br /&gt;
&lt;br /&gt;
==Plugin Changes==&lt;br /&gt;
*There is no longer a hardcoded limit to the number of admins.&lt;br /&gt;
*There is no longer a hardcoded limit to the map list.&lt;br /&gt;
*There is no longer a hardcoded limit to the number of &amp;quot;imessages.&amp;quot;&lt;br /&gt;
*Added {{amb|34}}: There are now plugin command/cvar menus.&lt;br /&gt;
*Added {{AMBug|45044}}: amx_banmenu now prints the ban time length.&lt;br /&gt;
*Added {{AMBug|43757}}: amx_addadmin now writes a comment with the player's name.&lt;br /&gt;
*Added {{AMBug|29353}}: amx_plugins now prints paginated output.&lt;br /&gt;
*Added {{AMBug|50742}}: admin.sma now supports prefix based per-map configs.&lt;br /&gt;
*Added {{amb|28}}: statscfg.sma can now use translations.&lt;br /&gt;
*Added {{amb|30}}: &amp;lt;tt&amp;gt;csstats_rankbots&amp;lt;/tt&amp;gt; prevents bots from showing on &amp;lt;tt&amp;gt;/top15&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*Added {{amb|31}}: plmenu.sma ban and slap options are now configurable.&lt;br /&gt;
*Added {{amb|42}}: Added new values for &amp;lt;tt&amp;gt;amx_show_activity&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*Added {{amb|51}}: amx_vote can now take more than two options.&lt;br /&gt;
*Added {{amb|64}}: amx_voteban autodetects whether it should IP ban.&lt;br /&gt;
*Added {{amb|307}}: amx_addban now caches the last ten connections.&lt;br /&gt;
*Added {{amb|311}}: mapcycle file now ignores .bsp extensions.&lt;br /&gt;
*Added {{amb|340}}: amx_ban/amx_banip now display a reason in the activity.&lt;br /&gt;
*Added {{amb|427}}: Additional weapons to &amp;lt;tt&amp;gt;dod_[g|s]et_user_ammo&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Fixed {{amb|29}}: pausecfg.sma did not translate two phrases.&lt;br /&gt;
*Fixed {{amb|91}}: miscstats.sma truncated some language translations.&lt;br /&gt;
*Fixed {{amb|94}}: amx_psay sometimes sent truncated messages.&lt;br /&gt;
*Fixed {{amb|109}}: mapsmenu.sma now checks &amp;lt;tt&amp;gt;mapcyclefile&amp;lt;/tt&amp;gt; before reverting to &amp;lt;tt&amp;gt;mapcycle.txt&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*Fixed {{amb|118}}: amx_help would not list &amp;lt;tt&amp;gt;ADMIN_ADMIN&amp;lt;/tt&amp;gt; commands.&lt;br /&gt;
*Fixed {{amb|130}}: Various menus did not take &amp;lt;tt&amp;gt;ADMIN_ALL&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;ADMIN_ADMIN&amp;lt;/tt&amp;gt; into account.&lt;br /&gt;
*Fixed {{amb|183}}: plmenu.sma did not work on Natural Selection.&lt;br /&gt;
*Fixed {{amb|196}}: amx_modules did not handle invalid modules properly.&lt;br /&gt;
*Fixed {{amb|222}}: cl_rebuy could exploit CS weapon restrictions.  This also makes CZ bots obey restrictions.&lt;br /&gt;
*Fixed {{amb|228}}: amxmod_compat could cause &amp;lt;tt&amp;gt;set_user_hitzones&amp;lt;/tt&amp;gt;() to break.&lt;br /&gt;
*Fixed {{amb|350}}: &amp;lt;tt&amp;gt;traceline_set_float&amp;lt;/tt&amp;gt; from the AMX Mod Compat layer was broken.&lt;br /&gt;
*Fixed {{amb|467}}: &amp;lt;tt&amp;gt;conmotd.txt&amp;lt;/tt&amp;gt; is now removed.&lt;br /&gt;
*Fixed {{amb|633}}: Immune admins can now target themselves.&lt;br /&gt;
*Fixed a potential exploit in adminslots.sma.&lt;br /&gt;
*SQL cvars are now protected.&lt;br /&gt;
*Added {{amb|743}}: plmenu for cstrike has an option to move to spectator.&lt;br /&gt;
&lt;br /&gt;
==Module Changes==&lt;br /&gt;
*Fixed {{amb|108}}: IP-based stats no longer include a port when saving.&lt;br /&gt;
*Fixed {{amb|503}}: CSX did not set a META_RESULT when paused.&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=AMX_Mod_X_1.8.0_Changes&amp;diff=5009</id>
		<title>AMX Mod X 1.8.0 Changes</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=AMX_Mod_X_1.8.0_Changes&amp;diff=5009"/>
		<updated>2007-08-06T23:15:46Z</updated>

		<summary type="html">&lt;p&gt;Sawce: /* Scripting Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;AMX Mod X 1.8 is a large feature release with many changes, both to the development API and user-mode features.&lt;br /&gt;
&lt;br /&gt;
=Changelog=&lt;br /&gt;
==Overall Changes==&lt;br /&gt;
*Added a new module, Ham Sandwich, for hooking virtual CBaseEntity functions in mods.&lt;br /&gt;
*Command flags are now initially dumped to disk and can be edited via &amp;lt;tt&amp;gt;configs/cmdaccess.ini&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*Added {{AMBug|48738}}: Romanian translation from X-5173.&lt;br /&gt;
*Added {{AMBug|50741}} and {{AMBug|43830}}: per-map plugins files can now be prefixed based.&lt;br /&gt;
*Added {{amb|17}}: New menu rendering is now more consistent; non-consistent controls are deprecated.&lt;br /&gt;
*Added {{amb|32}}: The server console commands &amp;quot;amxx cvars&amp;quot; and &amp;quot;amxx cmds&amp;quot; can now filter by plugin.&lt;br /&gt;
*Added {{amb|122}}: Log file names now include a four-digit year.&lt;br /&gt;
*Fixed {{amb|18}}: New menus are now properly destroyed if overridden.&lt;br /&gt;
*Fixed {{amb|46}}: &amp;lt;tt&amp;gt;is_user_bot&amp;lt;/tt&amp;gt; had some false positives.&lt;br /&gt;
*Fixed {{amb|69}}: Fixed Metamod trying to reload AMX Mod X against a poorly configured clock.&lt;br /&gt;
*Fixed {{amb|207}}: New menus now display &amp;quot;0&amp;quot; instead of &amp;quot;10.&amp;quot;&lt;br /&gt;
*Fixed {{amb|208}}: New menus did not reset callback results after each call.&lt;br /&gt;
*Fixed {{amb|200}}: Dynamic/fake natives were not re-entrant.&lt;br /&gt;
*Fixed {{amb|244}}: Run-time errors blocked forwards.&lt;br /&gt;
*Fixed {{amb|305}}: Core crashed on mods that removed the standard &amp;lt;tt&amp;gt;mp_timelimit&amp;lt;/tt&amp;gt; cvar.&lt;br /&gt;
*Fixed many various internal new menu rendering and item selection bugs.&lt;br /&gt;
==Scripting Changes==&lt;br /&gt;
*Added natives for dynamic global arrays.&lt;br /&gt;
*Added a new, magic &amp;lt;tt&amp;gt;any&amp;lt;/tt&amp;gt; tag from [[SourceMod]].&lt;br /&gt;
*Added a &amp;lt;tt&amp;gt;charsmax&amp;lt;/tt&amp;gt; operator for safe sizeof(string)-1 usage.&lt;br /&gt;
*Added &amp;lt;tt&amp;gt;set_pcvar_string&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added &amp;lt;tt&amp;gt;LookupLangKey&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added &amp;lt;tt&amp;gt;SQL_QuoteString&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added &amp;lt;tt&amp;gt;[g|s]et_pdata_cbase[_safe]&amp;lt;/tt&amp;gt;() to the Ham Sandwich module.&lt;br /&gt;
*Added &amp;lt;tt&amp;gt;geoip_code[2|3]_ex&amp;lt;/tt&amp;gt;(), which address a serious issue in the now deprecated &amp;lt;tt&amp;gt;geoip_code[2|3]&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added &amp;lt;tt&amp;gt;lookup_sequence&amp;lt;/tt&amp;gt;(), &amp;lt;tt&amp;gt;set_controller&amp;lt;/tt&amp;gt;(), &amp;lt;tt&amp;gt;set_pev_string&amp;lt;/tt&amp;gt;(), and &amp;lt;tt&amp;gt;pev_serial&amp;lt;/tt&amp;gt;() to Fakemeta.&lt;br /&gt;
*Added &amp;lt;tt&amp;gt;ns_get_user_team&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*Added a menu property to change the numbering color.&lt;br /&gt;
*Added {{amb|27}}: &amp;lt;tt&amp;gt;SQL_Rewind&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|37}}: &amp;lt;tt&amp;gt;cs_[g|s]et_user_submodel&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|38}}: &amp;lt;tt&amp;gt;cs_[g|s]et_user_lastactivity&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|39}}: &amp;lt;tt&amp;gt;cs_[g|s]et_hostage_lastuse&amp;lt;/tt&amp;gt;() and &amp;lt;tt&amp;gt;cs_[g|s]et_hostage_nextuser&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|63}}: &amp;lt;tt&amp;gt;floatmin&amp;lt;/tt&amp;gt;(), &amp;lt;tt&amp;gt;floatmax&amp;lt;/tt&amp;gt;(), and &amp;lt;tt&amp;gt;floatclamp()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*Added {{amb|76}}: Formatting functions can now use %x or %X for hexadecimal numbers.&lt;br /&gt;
*Added {{amb|92}}: &amp;lt;tt&amp;gt;create_tr2&amp;lt;/tt&amp;gt;() and &amp;lt;tt&amp;gt;free_tr2&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|205}}: &amp;lt;tt&amp;gt;cs_[g|s]et_c4_explode_time&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|216}}: &amp;lt;tt&amp;gt;SQL_MakeStdTuple&amp;lt;/tt&amp;gt;() now has a timeout parameter.&lt;br /&gt;
*Added {{amb|237}}: Fakemeta can now call &amp;quot;ServerPrint.&amp;quot;&lt;br /&gt;
*Added {{amb|242}}: &amp;lt;tt&amp;gt;cs_[g|s]et_user_hostagekills&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|245}}: &amp;lt;tt&amp;gt;precache_sound&amp;lt;/tt&amp;gt; now returns a precache index.&lt;br /&gt;
*Added {{amb|261}}: &amp;lt;tt&amp;gt;has_flag&amp;lt;/tt&amp;gt;() and &amp;lt;tt&amp;gt;has_all_flags&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|291}}: &amp;lt;tt&amp;gt;cs_[g|s]et_c4_defusing&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{amb|673}}: &amp;lt;tt&amp;gt;regex_compile&amp;lt;/tt&amp;gt;() and &amp;lt;tt&amp;gt;regex_match_c&amp;lt;/tt&amp;gt; for pre-compiling expressions.&lt;br /&gt;
*Added {{AMBug|46213}}: &amp;lt;tt&amp;gt;player_menu_info&amp;lt;/tt&amp;gt;() now returns a page number.&lt;br /&gt;
*Added {{AMBug|51064}}: Some parameters to &amp;lt;tt&amp;gt;get_plugin&amp;lt;/tt&amp;gt; are now optional.&lt;br /&gt;
*Added {{AMBug|50610}}: Some parameters to &amp;lt;tt&amp;gt;get_user_weapon&amp;lt;/tt&amp;gt; are now optional.&lt;br /&gt;
*Added {{AMBug|48841}}: &amp;lt;tt&amp;gt;tfc_is_user_feigning&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Added {{AMBug|45664}}: &amp;lt;tt&amp;gt;tfc_is_team_ally&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Fixed {{AMBug|49337}}: &amp;lt;tt&amp;gt;get_pcvar_float&amp;lt;/tt&amp;gt;() malfunctioned on high numbers.&lt;br /&gt;
*Fixed {{amb|78}}: &amp;lt;tt&amp;gt;get_concmdsnum&amp;lt;/tt&amp;gt; could return an incorrect result.&lt;br /&gt;
*Fixed {{amb|85}}: Tag mismatches on &amp;lt;tt&amp;gt;ShowSyncHudMsg&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Fixed {{amb|90}}: &amp;lt;tt&amp;gt;set_native_filter&amp;lt;/tt&amp;gt;() did not work in rare cases.&lt;br /&gt;
*Fixed {{amb|107}}: &amp;lt;tt&amp;gt;socket_open&amp;lt;/tt&amp;gt;() didn't return an error by reference.&lt;br /&gt;
*Fixed {{amb|110}}: &amp;lt;tt&amp;gt;socket_change&amp;lt;/tt&amp;gt;() could return 1 on certain failures.&lt;br /&gt;
*Fixed {{amb|116}}: &amp;lt;tt&amp;gt;DispatchKeyValue&amp;lt;/tt&amp;gt;() did not work on worldspawn (entity 0).&lt;br /&gt;
*Fixed {{amb|149}}: &amp;lt;tt&amp;gt;register_event&amp;lt;/tt&amp;gt; with the &amp;quot;e&amp;quot; flag could catch incorrect players.&lt;br /&gt;
*Fixed {{amb|230}}: &amp;lt;tt&amp;gt;radius_damage&amp;lt;/tt&amp;gt;() didn't kill players on all mods.&lt;br /&gt;
*Fixed {{amb|257}}: &amp;lt;tt&amp;gt;get_user_origin&amp;lt;/tt&amp;gt;() mode 4 had false positives.&lt;br /&gt;
*Fixed {{amb|343}}: &amp;lt;tt&amp;gt;TFC_ClearModel&amp;lt;/tt&amp;gt;() did not function as documented.&lt;br /&gt;
*Fixed {{amb|421}}: &amp;lt;tt&amp;gt;get_user_weapons&amp;lt;/tt&amp;gt;() could omit a weapon on Day of Defeat.&lt;br /&gt;
*Fixed {{amb|437}}: &amp;lt;tt&amp;gt;dod_set_user_kills&amp;lt;/tt&amp;gt;() and &amp;lt;tt&amp;gt;dod_set_user_score&amp;lt;/tt&amp;gt;() could mess up the scoreboard.&lt;br /&gt;
*Fixed {{amb|519}}: &amp;lt;tt&amp;gt;geoip_code[2|3]&amp;lt;/tt&amp;gt;() buffer overflowed on error.&lt;br /&gt;
*Fixed {{amb|736}}: &amp;lt;tt&amp;gt;find_entity&amp;lt;/tt&amp;gt;() was defined twice.&lt;br /&gt;
*Fixed a memory leak in &amp;lt;tt&amp;gt;SortCustom1D&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Fixed a crash bug in &amp;lt;tt&amp;gt;fwrite_blocks&amp;lt;/tt&amp;gt;().&lt;br /&gt;
&lt;br /&gt;
==Plugin Changes==&lt;br /&gt;
*There is no longer a hardcoded limit to the number of admins.&lt;br /&gt;
*There is no longer a hardcoded limit to the map list.&lt;br /&gt;
*There is no longer a hardcoded limit to the number of &amp;quot;imessages.&amp;quot;&lt;br /&gt;
*Added {{amb|34}}: There are now plugin command/cvar menus.&lt;br /&gt;
*Added {{AMBug|45044}}: amx_banmenu now prints the ban time length.&lt;br /&gt;
*Added {{AMBug|43757}}: amx_addadmin now writes a comment with the player's name.&lt;br /&gt;
*Added {{AMBug|29353}}: amx_plugins now prints paginated output.&lt;br /&gt;
*Added {{AMBug|50742}}: admin.sma now supports prefix based per-map configs.&lt;br /&gt;
*Added {{amb|28}}: statscfg.sma can now use translations.&lt;br /&gt;
*Added {{amb|30}}: &amp;lt;tt&amp;gt;csstats_rankbots&amp;lt;/tt&amp;gt; prevents bots from showing on &amp;lt;tt&amp;gt;/top15&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*Added {{amb|31}}: plmenu.sma ban and slap options are now configurable.&lt;br /&gt;
*Added {{amb|42}}: Added new values for &amp;lt;tt&amp;gt;amx_show_activity&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*Added {{amb|51}}: amx_vote can now take more than two options.&lt;br /&gt;
*Added {{amb|64}}: amx_voteban autodetects whether it should IP ban.&lt;br /&gt;
*Added {{amb|307}}: amx_addban now caches the last ten connections.&lt;br /&gt;
*Added {{amb|311}}: mapcycle file now ignores .bsp extensions.&lt;br /&gt;
*Added {{amb|340}}: amx_ban/amx_banip now display a reason in the activity.&lt;br /&gt;
*Added {{amb|427}}: Additional weapons to &amp;lt;tt&amp;gt;dod_[g|s]et_user_ammo&amp;lt;/tt&amp;gt;().&lt;br /&gt;
*Fixed {{amb|29}}: pausecfg.sma did not translate two phrases.&lt;br /&gt;
*Fixed {{amb|91}}: miscstats.sma truncated some language translations.&lt;br /&gt;
*Fixed {{amb|94}}: amx_psay sometimes sent truncated messages.&lt;br /&gt;
*Fixed {{amb|109}}: mapsmenu.sma now checks &amp;lt;tt&amp;gt;mapcyclefile&amp;lt;/tt&amp;gt; before reverting to &amp;lt;tt&amp;gt;mapcycle.txt&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*Fixed {{amb|118}}: amx_help would not list &amp;lt;tt&amp;gt;ADMIN_ADMIN&amp;lt;/tt&amp;gt; commands.&lt;br /&gt;
*Fixed {{amb|130}}: Various menus did not take &amp;lt;tt&amp;gt;ADMIN_ALL&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;ADMIN_ADMIN&amp;lt;/tt&amp;gt; into account.&lt;br /&gt;
*Fixed {{amb|183}}: plmenu.sma did not work on Natural Selection.&lt;br /&gt;
*Fixed {{amb|196}}: amx_modules did not handle invalid modules properly.&lt;br /&gt;
*Fixed {{amb|222}}: cl_rebuy could exploit CS weapon restrictions.  This also makes CZ bots obey restrictions.&lt;br /&gt;
*Fixed {{amb|228}}: amxmod_compat could cause &amp;lt;tt&amp;gt;set_user_hitzones&amp;lt;/tt&amp;gt;() to break.&lt;br /&gt;
*Fixed {{amb|350}}: &amp;lt;tt&amp;gt;traceline_set_float&amp;lt;/tt&amp;gt; from the AMX Mod Compat layer was broken.&lt;br /&gt;
*Fixed {{amb|467}}: &amp;lt;tt&amp;gt;conmotd.txt&amp;lt;/tt&amp;gt; is now removed.&lt;br /&gt;
*Fixed {{amb|633}}: Immune admins can now target themselves.&lt;br /&gt;
*Fixed a potential exploit in adminslots.sma.&lt;br /&gt;
*SQL cvars are now protected.&lt;br /&gt;
==Module Changes==&lt;br /&gt;
*Fixed {{amb|108}}: IP-based stats no longer include a port when saving.&lt;br /&gt;
*Fixed {{amb|503}}: CSX did not set a META_RESULT when paused.&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Admin_Commands_(SourceMod)&amp;diff=4657</id>
		<title>Admin Commands (SourceMod)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Admin_Commands_(SourceMod)&amp;diff=4657"/>
		<updated>2007-06-08T15:00:10Z</updated>

		<summary type="html">&lt;p&gt;Sawce: Format fixes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page lists all of the major admin commands in SourceMod.  &lt;br /&gt;
&lt;br /&gt;
'''Chat Triggers''': Remember that commands do not have to be entered through the console; they can be entered via chat triggers.  For example, saying &amp;quot;!ban bail&amp;quot; in chat will execute the same command as &amp;quot;sm_ban&amp;quot; and forward the output to chat.  You can also use &amp;quot;/&amp;quot; instead of &amp;quot;!&amp;quot; to suppress your command from being shown to users.&lt;br /&gt;
&lt;br /&gt;
'''Targetting Players''': There are a number of ways to target players:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;name - The player will be targeted by a partial name match (multiple matches will report back an error).&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;#userid - If userid is numeric, the player will be targeted by their userid (found via the &amp;quot;users&amp;quot; command).&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;#name - If name is non-numeric, the player will be targeted by an exact name match.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Basic Commands=&lt;br /&gt;
These commands are found in the &amp;quot;basecommands&amp;quot; plugin.&lt;br /&gt;
&lt;br /&gt;
:{|&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| Command&lt;br /&gt;
| Format&lt;br /&gt;
| Access&lt;br /&gt;
| Description&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| sm_kick&lt;br /&gt;
| &amp;lt;#userid|name&amp;gt; [reason]&lt;br /&gt;
| kick&lt;br /&gt;
| Kicks a player.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| sm_map&lt;br /&gt;
| &amp;lt;map&amp;gt;&lt;br /&gt;
| map&lt;br /&gt;
| Changes the current map.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| sm_rcon&lt;br /&gt;
| &amp;lt;argstring&amp;gt;&lt;br /&gt;
| rcon&lt;br /&gt;
| Executes the argument string via rcon.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| sm_cvar&lt;br /&gt;
| &amp;lt;cvar&amp;gt; [value]&lt;br /&gt;
| cvar&lt;br /&gt;
| Retrieves or changes a cvar value.  Protected cvars can only be accessed with rcon access, and sv_cheats can only be accessed with cheat access.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| sm_execcfg&lt;br /&gt;
| &amp;lt;filename&amp;gt;&lt;br /&gt;
| config&lt;br /&gt;
| Executes a config file (path not needed, but extension is).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| sm_who&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;[#userid|name]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
| admin&lt;br /&gt;
| Lists all users and their access rights, or a specific user's access rights.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| sm_ban&lt;br /&gt;
| &amp;lt;nowiki&amp;gt;&amp;lt;#userid|name&amp;gt; &amp;lt;minutes|0&amp;gt; &amp;lt;/nowiki&amp;gt;[reason]&lt;br /&gt;
| ban&lt;br /&gt;
| Bans a client.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| sm_unban&lt;br /&gt;
| &amp;lt;steamid&amp;gt;&lt;br /&gt;
| unban&lt;br /&gt;
| Unbans a Steam ID.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| sm_addban&lt;br /&gt;
| &amp;lt;time&amp;gt; &amp;lt;steamid&amp;gt; [reason]&lt;br /&gt;
| rcon&lt;br /&gt;
| Adds a Steam ID to Source's ban list.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| sm_banip&lt;br /&gt;
| &amp;lt;time&amp;gt; &amp;lt;ip&amp;gt; [reason]&lt;br /&gt;
| rcon&lt;br /&gt;
| Adds an IP address to Source's ban list.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Documentation]]&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4514</id>
		<title>HamSandwich General Usage (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4514"/>
		<updated>2007-05-11T03:39:55Z</updated>

		<summary type="html">&lt;p&gt;Sawce: /* Changing Hook Parameters */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Ham Sandwich ==&lt;br /&gt;
Ham Sandwich is a module that provides additional hooking and function calling capabilities to [[AMX Mod X]].  It is scheduled to be included with the 1.8 branch of AMX Mod X.&lt;br /&gt;
&lt;br /&gt;
Instead of hooking and executing Half-Life engine calls, like the modules FakeMeta and Engine do, this hooks and executes virtual function calls.&lt;br /&gt;
&lt;br /&gt;
=== What is a virtual function? ===&lt;br /&gt;
A virtual function is a member function of a class in C++.  In the case of Ham Sandwich, the virtual function would be a member function of a game entity.  The virtual functions deal with various events in game, such as damage, and using entities.&lt;br /&gt;
&lt;br /&gt;
Unlike normal member functions, virtual functions can be changed by class derivatives.  For example, a typical hierarchy of entities in Half-Life game dlls look something like this:&lt;br /&gt;
&lt;br /&gt;
 CBaseEntity&lt;br /&gt;
    CBaseAnimating&lt;br /&gt;
       CBaseMonster&lt;br /&gt;
          CZombie&lt;br /&gt;
          CHeadCrab&lt;br /&gt;
          CBarnacle&lt;br /&gt;
          CBasePlayer&lt;br /&gt;
             CBot&lt;br /&gt;
&lt;br /&gt;
Now for example, if CBaseEntity has the virtual function called &amp;quot;FunctionA&amp;quot;, and that function does nothing.  But, CBarnacle also declares the function &amp;quot;FunctionA&amp;quot;, and instead of doing nothing it causes the barnacle to die.&lt;br /&gt;
&lt;br /&gt;
If something like this were to be executed:&lt;br /&gt;
 CBaseEntity *ent=GET_PRIVATE(entity);&lt;br /&gt;
 ent-&amp;gt;FunctionA();&lt;br /&gt;
&lt;br /&gt;
And the entity were a barnacle, the barnacle would die.  If the entity was a zombie, nothing would happen.&lt;br /&gt;
&lt;br /&gt;
=== What are some limitations? ===&lt;br /&gt;
&lt;br /&gt;
Dealing with virtual functions have a couple minor drawbacks.&lt;br /&gt;
==== Custom Entities ====&lt;br /&gt;
Hooking virtual functions, such as TakeDamage, that get called on custom entities is a little bit awkward.&lt;br /&gt;
&lt;br /&gt;
Because of the way where classes derive, and they get their own virtual table for each class, the type of class that the game dll allocates will be whatever gets hooked for a particular hook.&lt;br /&gt;
&lt;br /&gt;
For example, say you have a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 new myStr;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   myStr = engfunc( EngFunc_AllocString, &amp;quot;info_target&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   register_clcmd( &amp;quot;make_entity&amp;quot;, &amp;quot;cmdMakeEntity&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;damageHook&amp;quot;, &amp;quot;MyEntityClass&amp;quot;); // Error!&lt;br /&gt;
 }&lt;br /&gt;
 public cmdMakeEntity( id )&lt;br /&gt;
 {&lt;br /&gt;
   new ent = engfunc( EngFunc_CreateEntity, myStr );&lt;br /&gt;
   set_pev( ent, pev_classname, &amp;quot;MyEntityClass&amp;quot; );&lt;br /&gt;
   // ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
That will not work, because the class &amp;quot;MyEntityClass&amp;quot; is not native to the gamedll.  Instead, you would need to hook TakeDamage for &amp;quot;info_target&amp;quot;, and do some form of parsing on the entities that get passed to it (such as checking classname), if you want to deal with custom entity hooking.&lt;br /&gt;
&lt;br /&gt;
==== End of Chain Derivatives ====&lt;br /&gt;
The normal way virtual functions get called is by a virtual table that resides somewhere in the class.  A magical index is assigned to each function, and then it looks up the function pointer inside of the virtual table, and executes the required function.&lt;br /&gt;
&lt;br /&gt;
However, compilers are smart enough to optimize away the virtual function lookup if it knows two things about a call:&lt;br /&gt;
* The exact class type of the entity.&lt;br /&gt;
* That the entity is not derived any further.&lt;br /&gt;
&lt;br /&gt;
An example would be using the hierarchy shown earlier.  If, inside of CBot::TakeDamage a call to the virtual function CBot::Killed is made, most compilers will optimize the virtual function lookup out, so that CBot::TakeDamage would then directly call CBot::Killed.  This means that the hook would never be called.&lt;br /&gt;
&lt;br /&gt;
Fortunately, these instances are kind of rare.&lt;br /&gt;
&lt;br /&gt;
==== Config File Requirements ====&lt;br /&gt;
Every hook and every ExecuteHam() call requires an entry for the function which the scripter is attempting to hook or execute.  The function needs to be in the amxmodx/configs/hamdata.ini config file, under the game mod and operating system.&lt;br /&gt;
&lt;br /&gt;
If a function that the script attempts to hook or call is not configured in the hamdata.ini file, then the module will cause the plugin to cease operation, as this is a fatal error.&lt;br /&gt;
&lt;br /&gt;
The fatal errors can be filtered out by including a forward in the script called '''HamFilter'''.  This is similar to native/module filters available inside of the core of amxmodx, whenever a fatal error occurs, it will pass along the parameters to HamFilter, and if HamFilter returns '''PLUGIN_HANDLED''', the error will be ignored (but the attempted hook or execution will not take place).  If the forward does not exist, or if it returns something other than PLUGIN_HANDLED, the plugin will fail.&lt;br /&gt;
&lt;br /&gt;
An example layout for HamFilter:&lt;br /&gt;
 public HamFilter(Ham:which, HamError:err, const reason[])&lt;br /&gt;
 {&lt;br /&gt;
   // Ignore an unconfigured ns_awardkill&lt;br /&gt;
   if (which == Ham_NS_AwardKill &amp;amp;&amp;amp; err == HAM_FUNC_NOT_CONFIGURED)(&lt;br /&gt;
   {&lt;br /&gt;
     return PLUGIN_HANDLED;&lt;br /&gt;
   }&lt;br /&gt;
   // We absolutely need to be able to use cs_roundrespawn!&lt;br /&gt;
   // If we can't, then the plugin cannot continue.&lt;br /&gt;
   if (which == Ham_CS_RoundRespawn)&lt;br /&gt;
   {&lt;br /&gt;
     return 0;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Additionally, you can check to see if a function is valid to execute or hook by using the '''IsHamValid()''' native.  The validity of a function is determined when the module is first loaded, and it will never change, so if you want to check it, there is no need to do so before every execute.&lt;br /&gt;
&lt;br /&gt;
== Supported Mods ==&lt;br /&gt;
=== Mostly Supported ===&lt;br /&gt;
These mods have a very large list of functions that are usable in the module. &lt;br /&gt;
* Counter-Strike 1.6&lt;br /&gt;
* Condition Zero&lt;br /&gt;
* Day of Defeat&lt;br /&gt;
* Team Fortress Classic&lt;br /&gt;
* The Specialists&lt;br /&gt;
* Natural-Selection&lt;br /&gt;
&lt;br /&gt;
=== Weakly Supported ===&lt;br /&gt;
Because these mods do not contain a Linux binary, they are much harder to disassemble.  There is only plans for disassembling two functions for each (TakeDamage and Use).&lt;br /&gt;
* Sven-Coop&lt;br /&gt;
* Earth's Special Forces&lt;br /&gt;
&lt;br /&gt;
== Hooking Functions ==&lt;br /&gt;
The big feature for Ham Sandwich is the ability to hook virtual functions.&lt;br /&gt;
&lt;br /&gt;
=== Creating the Hook ===&lt;br /&gt;
Creating a hook is a lot like creating a hook in Fakemeta.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;player_hurt&amp;quot;, &amp;quot;player&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public player_hurt(this, inflictor, attacker, Float:damage, damagebits)&lt;br /&gt;
 {&lt;br /&gt;
   // Stuff...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This creates a basic hook which is called any time a player takes damage.  Look in '''ham_const.inc''' for forward parameters for each hook.&lt;br /&gt;
&lt;br /&gt;
Like FakeMeta, there is a hidden last parameter (it goes after the classname in this case).  Set it to 1 to do post hooking.&lt;br /&gt;
&lt;br /&gt;
=== Blocking the Hook ===&lt;br /&gt;
Like Fakemeta and Engine, it is possible to stop a function from being called.  This is called '''superceding'''.&lt;br /&gt;
&lt;br /&gt;
Blocking in Ham Sandwich is identical to how it is accomplished in Fakemeta.  In each hook, you return one of four special values:&lt;br /&gt;
&lt;br /&gt;
* HAM_IGNORED - Nothing happened, the call continues.&lt;br /&gt;
* HAM_HANDLED - You did something, but the call continues.&lt;br /&gt;
* HAM_OVERRIDE - The call will still be executed, but instead you will change the return value.&lt;br /&gt;
* HAM_SUPERCEDE - The call is not executed, and you use your return value, if applicable.&lt;br /&gt;
&lt;br /&gt;
You can use the native '''GetHamReturnStatus()''' to check the current return status of the hook.&lt;br /&gt;
&lt;br /&gt;
=== Return Values ===&lt;br /&gt;
You can get or change the return values for all the hooks available in Ham Sandwich.  Look in '''ham_const.inc''' for a list of all hooks and their return values.&lt;br /&gt;
&lt;br /&gt;
These natives will get any ''modified'' return values.&lt;br /&gt;
* native GetHamReturnInteger(&amp;amp;output);&lt;br /&gt;
* native GetHamReturnFloat(&amp;amp;Float:output);&lt;br /&gt;
* native GetHamReturnVector(Float:output[3]);&lt;br /&gt;
* native GetHamReturnEntity(&amp;amp;output);&lt;br /&gt;
* native GetHamReturnString(output[], size);&lt;br /&gt;
&lt;br /&gt;
These natives will get the ''original'' return value from the function.&lt;br /&gt;
Note that this is '''only''' valid to call in a post hook, it will be undefined to call it at any other time.&lt;br /&gt;
* native GetOrigHamReturnInteger(&amp;amp;output);&lt;br /&gt;
* native GetOrigHamReturnFloat(&amp;amp;Float:output);&lt;br /&gt;
* native GetOrigHamReturnVector(Float:output[3]);&lt;br /&gt;
* native GetOrigHamReturnCbase(&amp;amp;output);&lt;br /&gt;
* native GetOrigHamReturnString(output[], size);&lt;br /&gt;
&lt;br /&gt;
These natives will change the return value to whatever you please.&lt;br /&gt;
Note that this will have no effect on the actual return value from the function '''unless''' the return status of the hook is HAM_OVERRIDE or HAM_SUPERCEDE.&lt;br /&gt;
* native SetHamReturnInteger(value);&lt;br /&gt;
* native SetHamReturnFloat(Float:value);&lt;br /&gt;
* native SetHamReturnVector(const Float:value[3]);&lt;br /&gt;
* native SetHamReturnEntity(value);&lt;br /&gt;
* native SetHamReturnString(const value[]);&lt;br /&gt;
&lt;br /&gt;
=== Changing Hook Parameters ===&lt;br /&gt;
One feature available in Ham Sandwich that is not available in FakeMeta is the ability to change all parameters on the fly for each hook.&lt;br /&gt;
&lt;br /&gt;
This means that, for example, if you wanted to make a plugin that halved all damage players take, you would do something like this:&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;player_hurt&amp;quot;, &amp;quot;player&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 public player_hurt(this, inflictor, attacker, Float:damage, damagebits)&lt;br /&gt;
 {&lt;br /&gt;
   SetHamParamFloat(4, damage / 2.0);&lt;br /&gt;
   return HAM_HANDLED;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
All hooks after the one you change them in will see the modified values.  Hooks are executed in the order in which they are registered.&lt;br /&gt;
&lt;br /&gt;
All available parameter changing natives are:&lt;br /&gt;
&lt;br /&gt;
* native SetHamParamInteger(which, value);&lt;br /&gt;
* native SetHamParamFloat(which, Float:value);&lt;br /&gt;
* native SetHamParamVector(which, const Float:value[3]);&lt;br /&gt;
* native SetHamParamEntity(which, value);&lt;br /&gt;
* native SetHamParamString(which, const output[]);&lt;br /&gt;
* native SetHamParamTraceResult(which, tr_handle);&lt;br /&gt;
&lt;br /&gt;
=== Disabling Hooks ===&lt;br /&gt;
&lt;br /&gt;
Similar to how FakeMeta allows for unregistering of hooks with unregister_forward, HamSandwich will allow you to disable and enable hooks whenever you want.&lt;br /&gt;
&lt;br /&gt;
The '''RegisterHam''' function will return a handle (tagged with HamHook).  You can then make subsequent calls to DisableHamHook() and EnableHamHook() with the handle to stop it from forwarding, or enable its forwards again.&lt;br /&gt;
&lt;br /&gt;
There is no way to completely unregister the hooks (until map change), as deleting a hook is a delicate process.&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4513</id>
		<title>HamSandwich General Usage (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4513"/>
		<updated>2007-05-11T03:39:13Z</updated>

		<summary type="html">&lt;p&gt;Sawce: /* Return Values */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Ham Sandwich ==&lt;br /&gt;
Ham Sandwich is a module that provides additional hooking and function calling capabilities to [[AMX Mod X]].  It is scheduled to be included with the 1.8 branch of AMX Mod X.&lt;br /&gt;
&lt;br /&gt;
Instead of hooking and executing Half-Life engine calls, like the modules FakeMeta and Engine do, this hooks and executes virtual function calls.&lt;br /&gt;
&lt;br /&gt;
=== What is a virtual function? ===&lt;br /&gt;
A virtual function is a member function of a class in C++.  In the case of Ham Sandwich, the virtual function would be a member function of a game entity.  The virtual functions deal with various events in game, such as damage, and using entities.&lt;br /&gt;
&lt;br /&gt;
Unlike normal member functions, virtual functions can be changed by class derivatives.  For example, a typical hierarchy of entities in Half-Life game dlls look something like this:&lt;br /&gt;
&lt;br /&gt;
 CBaseEntity&lt;br /&gt;
    CBaseAnimating&lt;br /&gt;
       CBaseMonster&lt;br /&gt;
          CZombie&lt;br /&gt;
          CHeadCrab&lt;br /&gt;
          CBarnacle&lt;br /&gt;
          CBasePlayer&lt;br /&gt;
             CBot&lt;br /&gt;
&lt;br /&gt;
Now for example, if CBaseEntity has the virtual function called &amp;quot;FunctionA&amp;quot;, and that function does nothing.  But, CBarnacle also declares the function &amp;quot;FunctionA&amp;quot;, and instead of doing nothing it causes the barnacle to die.&lt;br /&gt;
&lt;br /&gt;
If something like this were to be executed:&lt;br /&gt;
 CBaseEntity *ent=GET_PRIVATE(entity);&lt;br /&gt;
 ent-&amp;gt;FunctionA();&lt;br /&gt;
&lt;br /&gt;
And the entity were a barnacle, the barnacle would die.  If the entity was a zombie, nothing would happen.&lt;br /&gt;
&lt;br /&gt;
=== What are some limitations? ===&lt;br /&gt;
&lt;br /&gt;
Dealing with virtual functions have a couple minor drawbacks.&lt;br /&gt;
==== Custom Entities ====&lt;br /&gt;
Hooking virtual functions, such as TakeDamage, that get called on custom entities is a little bit awkward.&lt;br /&gt;
&lt;br /&gt;
Because of the way where classes derive, and they get their own virtual table for each class, the type of class that the game dll allocates will be whatever gets hooked for a particular hook.&lt;br /&gt;
&lt;br /&gt;
For example, say you have a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 new myStr;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   myStr = engfunc( EngFunc_AllocString, &amp;quot;info_target&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   register_clcmd( &amp;quot;make_entity&amp;quot;, &amp;quot;cmdMakeEntity&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;damageHook&amp;quot;, &amp;quot;MyEntityClass&amp;quot;); // Error!&lt;br /&gt;
 }&lt;br /&gt;
 public cmdMakeEntity( id )&lt;br /&gt;
 {&lt;br /&gt;
   new ent = engfunc( EngFunc_CreateEntity, myStr );&lt;br /&gt;
   set_pev( ent, pev_classname, &amp;quot;MyEntityClass&amp;quot; );&lt;br /&gt;
   // ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
That will not work, because the class &amp;quot;MyEntityClass&amp;quot; is not native to the gamedll.  Instead, you would need to hook TakeDamage for &amp;quot;info_target&amp;quot;, and do some form of parsing on the entities that get passed to it (such as checking classname), if you want to deal with custom entity hooking.&lt;br /&gt;
&lt;br /&gt;
==== End of Chain Derivatives ====&lt;br /&gt;
The normal way virtual functions get called is by a virtual table that resides somewhere in the class.  A magical index is assigned to each function, and then it looks up the function pointer inside of the virtual table, and executes the required function.&lt;br /&gt;
&lt;br /&gt;
However, compilers are smart enough to optimize away the virtual function lookup if it knows two things about a call:&lt;br /&gt;
* The exact class type of the entity.&lt;br /&gt;
* That the entity is not derived any further.&lt;br /&gt;
&lt;br /&gt;
An example would be using the hierarchy shown earlier.  If, inside of CBot::TakeDamage a call to the virtual function CBot::Killed is made, most compilers will optimize the virtual function lookup out, so that CBot::TakeDamage would then directly call CBot::Killed.  This means that the hook would never be called.&lt;br /&gt;
&lt;br /&gt;
Fortunately, these instances are kind of rare.&lt;br /&gt;
&lt;br /&gt;
==== Config File Requirements ====&lt;br /&gt;
Every hook and every ExecuteHam() call requires an entry for the function which the scripter is attempting to hook or execute.  The function needs to be in the amxmodx/configs/hamdata.ini config file, under the game mod and operating system.&lt;br /&gt;
&lt;br /&gt;
If a function that the script attempts to hook or call is not configured in the hamdata.ini file, then the module will cause the plugin to cease operation, as this is a fatal error.&lt;br /&gt;
&lt;br /&gt;
The fatal errors can be filtered out by including a forward in the script called '''HamFilter'''.  This is similar to native/module filters available inside of the core of amxmodx, whenever a fatal error occurs, it will pass along the parameters to HamFilter, and if HamFilter returns '''PLUGIN_HANDLED''', the error will be ignored (but the attempted hook or execution will not take place).  If the forward does not exist, or if it returns something other than PLUGIN_HANDLED, the plugin will fail.&lt;br /&gt;
&lt;br /&gt;
An example layout for HamFilter:&lt;br /&gt;
 public HamFilter(Ham:which, HamError:err, const reason[])&lt;br /&gt;
 {&lt;br /&gt;
   // Ignore an unconfigured ns_awardkill&lt;br /&gt;
   if (which == Ham_NS_AwardKill &amp;amp;&amp;amp; err == HAM_FUNC_NOT_CONFIGURED)(&lt;br /&gt;
   {&lt;br /&gt;
     return PLUGIN_HANDLED;&lt;br /&gt;
   }&lt;br /&gt;
   // We absolutely need to be able to use cs_roundrespawn!&lt;br /&gt;
   // If we can't, then the plugin cannot continue.&lt;br /&gt;
   if (which == Ham_CS_RoundRespawn)&lt;br /&gt;
   {&lt;br /&gt;
     return 0;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Additionally, you can check to see if a function is valid to execute or hook by using the '''IsHamValid()''' native.  The validity of a function is determined when the module is first loaded, and it will never change, so if you want to check it, there is no need to do so before every execute.&lt;br /&gt;
&lt;br /&gt;
== Supported Mods ==&lt;br /&gt;
=== Mostly Supported ===&lt;br /&gt;
These mods have a very large list of functions that are usable in the module. &lt;br /&gt;
* Counter-Strike 1.6&lt;br /&gt;
* Condition Zero&lt;br /&gt;
* Day of Defeat&lt;br /&gt;
* Team Fortress Classic&lt;br /&gt;
* The Specialists&lt;br /&gt;
* Natural-Selection&lt;br /&gt;
&lt;br /&gt;
=== Weakly Supported ===&lt;br /&gt;
Because these mods do not contain a Linux binary, they are much harder to disassemble.  There is only plans for disassembling two functions for each (TakeDamage and Use).&lt;br /&gt;
* Sven-Coop&lt;br /&gt;
* Earth's Special Forces&lt;br /&gt;
&lt;br /&gt;
== Hooking Functions ==&lt;br /&gt;
The big feature for Ham Sandwich is the ability to hook virtual functions.&lt;br /&gt;
&lt;br /&gt;
=== Creating the Hook ===&lt;br /&gt;
Creating a hook is a lot like creating a hook in Fakemeta.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;player_hurt&amp;quot;, &amp;quot;player&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public player_hurt(this, inflictor, attacker, Float:damage, damagebits)&lt;br /&gt;
 {&lt;br /&gt;
   // Stuff...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This creates a basic hook which is called any time a player takes damage.  Look in '''ham_const.inc''' for forward parameters for each hook.&lt;br /&gt;
&lt;br /&gt;
Like FakeMeta, there is a hidden last parameter (it goes after the classname in this case).  Set it to 1 to do post hooking.&lt;br /&gt;
&lt;br /&gt;
=== Blocking the Hook ===&lt;br /&gt;
Like Fakemeta and Engine, it is possible to stop a function from being called.  This is called '''superceding'''.&lt;br /&gt;
&lt;br /&gt;
Blocking in Ham Sandwich is identical to how it is accomplished in Fakemeta.  In each hook, you return one of four special values:&lt;br /&gt;
&lt;br /&gt;
* HAM_IGNORED - Nothing happened, the call continues.&lt;br /&gt;
* HAM_HANDLED - You did something, but the call continues.&lt;br /&gt;
* HAM_OVERRIDE - The call will still be executed, but instead you will change the return value.&lt;br /&gt;
* HAM_SUPERCEDE - The call is not executed, and you use your return value, if applicable.&lt;br /&gt;
&lt;br /&gt;
You can use the native '''GetHamReturnStatus()''' to check the current return status of the hook.&lt;br /&gt;
&lt;br /&gt;
=== Return Values ===&lt;br /&gt;
You can get or change the return values for all the hooks available in Ham Sandwich.  Look in '''ham_const.inc''' for a list of all hooks and their return values.&lt;br /&gt;
&lt;br /&gt;
These natives will get any ''modified'' return values.&lt;br /&gt;
* native GetHamReturnInteger(&amp;amp;output);&lt;br /&gt;
* native GetHamReturnFloat(&amp;amp;Float:output);&lt;br /&gt;
* native GetHamReturnVector(Float:output[3]);&lt;br /&gt;
* native GetHamReturnEntity(&amp;amp;output);&lt;br /&gt;
* native GetHamReturnString(output[], size);&lt;br /&gt;
&lt;br /&gt;
These natives will get the ''original'' return value from the function.&lt;br /&gt;
Note that this is '''only''' valid to call in a post hook, it will be undefined to call it at any other time.&lt;br /&gt;
* native GetOrigHamReturnInteger(&amp;amp;output);&lt;br /&gt;
* native GetOrigHamReturnFloat(&amp;amp;Float:output);&lt;br /&gt;
* native GetOrigHamReturnVector(Float:output[3]);&lt;br /&gt;
* native GetOrigHamReturnCbase(&amp;amp;output);&lt;br /&gt;
* native GetOrigHamReturnString(output[], size);&lt;br /&gt;
&lt;br /&gt;
These natives will change the return value to whatever you please.&lt;br /&gt;
Note that this will have no effect on the actual return value from the function '''unless''' the return status of the hook is HAM_OVERRIDE or HAM_SUPERCEDE.&lt;br /&gt;
* native SetHamReturnInteger(value);&lt;br /&gt;
* native SetHamReturnFloat(Float:value);&lt;br /&gt;
* native SetHamReturnVector(const Float:value[3]);&lt;br /&gt;
* native SetHamReturnEntity(value);&lt;br /&gt;
* native SetHamReturnString(const value[]);&lt;br /&gt;
&lt;br /&gt;
=== Changing Hook Parameters ===&lt;br /&gt;
One feature available in Ham Sandwich that is not available in FakeMeta is the ability to change all parameters on the fly for each hook.&lt;br /&gt;
&lt;br /&gt;
This means that, for example, if you wanted to make a plugin that halved all damage players take, you would do something like this:&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;player_hurt&amp;quot;, &amp;quot;player&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 public player_hurt(this, inflictor, attacker, Float:damage, damagebits)&lt;br /&gt;
 {&lt;br /&gt;
   SetHamParamFloat(4, damage / 2.0);&lt;br /&gt;
   return HAM_HANDLED;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
All hooks after the one you change them in will see the modified values.  Hooks are executed in the order in which they are registered.&lt;br /&gt;
&lt;br /&gt;
All available parameter changing natives are:&lt;br /&gt;
&lt;br /&gt;
* native SetHamParamInteger(which, value);&lt;br /&gt;
* native SetHamParamFloat(which, Float:value);&lt;br /&gt;
* native SetHamParamVector(which, const Float:value[3]);&lt;br /&gt;
* native SetHamParamEntity(which, value);&lt;br /&gt;
* native SetHamParamString(which, const output[]);&lt;br /&gt;
* native SetHamParamTraceResult(which, tr_handle);&lt;br /&gt;
&lt;br /&gt;
=== Disabling Hooks ===&lt;br /&gt;
&lt;br /&gt;
Similar to how FakeMeta allows for unregistering of hooks with unregister_forward, HamSandwich will allow you to disable and enable hooks whenever you want.&lt;br /&gt;
&lt;br /&gt;
The '''RegisterHam''' function will return a handle (tagged with HamHook).  You can then make subsequent calls to DisableHamHook() and EnableHamHook() with the handle to stop it from forwarding, or enable its forwards again.&lt;br /&gt;
&lt;br /&gt;
There is no way to completely unregister the hooks (until map change), as deleting a hook is a delicate process.&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4512</id>
		<title>HamSandwich General Usage (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4512"/>
		<updated>2007-05-11T03:36:14Z</updated>

		<summary type="html">&lt;p&gt;Sawce: /* Config File Requirements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Ham Sandwich ==&lt;br /&gt;
Ham Sandwich is a module that provides additional hooking and function calling capabilities to [[AMX Mod X]].  It is scheduled to be included with the 1.8 branch of AMX Mod X.&lt;br /&gt;
&lt;br /&gt;
Instead of hooking and executing Half-Life engine calls, like the modules FakeMeta and Engine do, this hooks and executes virtual function calls.&lt;br /&gt;
&lt;br /&gt;
=== What is a virtual function? ===&lt;br /&gt;
A virtual function is a member function of a class in C++.  In the case of Ham Sandwich, the virtual function would be a member function of a game entity.  The virtual functions deal with various events in game, such as damage, and using entities.&lt;br /&gt;
&lt;br /&gt;
Unlike normal member functions, virtual functions can be changed by class derivatives.  For example, a typical hierarchy of entities in Half-Life game dlls look something like this:&lt;br /&gt;
&lt;br /&gt;
 CBaseEntity&lt;br /&gt;
    CBaseAnimating&lt;br /&gt;
       CBaseMonster&lt;br /&gt;
          CZombie&lt;br /&gt;
          CHeadCrab&lt;br /&gt;
          CBarnacle&lt;br /&gt;
          CBasePlayer&lt;br /&gt;
             CBot&lt;br /&gt;
&lt;br /&gt;
Now for example, if CBaseEntity has the virtual function called &amp;quot;FunctionA&amp;quot;, and that function does nothing.  But, CBarnacle also declares the function &amp;quot;FunctionA&amp;quot;, and instead of doing nothing it causes the barnacle to die.&lt;br /&gt;
&lt;br /&gt;
If something like this were to be executed:&lt;br /&gt;
 CBaseEntity *ent=GET_PRIVATE(entity);&lt;br /&gt;
 ent-&amp;gt;FunctionA();&lt;br /&gt;
&lt;br /&gt;
And the entity were a barnacle, the barnacle would die.  If the entity was a zombie, nothing would happen.&lt;br /&gt;
&lt;br /&gt;
=== What are some limitations? ===&lt;br /&gt;
&lt;br /&gt;
Dealing with virtual functions have a couple minor drawbacks.&lt;br /&gt;
==== Custom Entities ====&lt;br /&gt;
Hooking virtual functions, such as TakeDamage, that get called on custom entities is a little bit awkward.&lt;br /&gt;
&lt;br /&gt;
Because of the way where classes derive, and they get their own virtual table for each class, the type of class that the game dll allocates will be whatever gets hooked for a particular hook.&lt;br /&gt;
&lt;br /&gt;
For example, say you have a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 new myStr;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   myStr = engfunc( EngFunc_AllocString, &amp;quot;info_target&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   register_clcmd( &amp;quot;make_entity&amp;quot;, &amp;quot;cmdMakeEntity&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;damageHook&amp;quot;, &amp;quot;MyEntityClass&amp;quot;); // Error!&lt;br /&gt;
 }&lt;br /&gt;
 public cmdMakeEntity( id )&lt;br /&gt;
 {&lt;br /&gt;
   new ent = engfunc( EngFunc_CreateEntity, myStr );&lt;br /&gt;
   set_pev( ent, pev_classname, &amp;quot;MyEntityClass&amp;quot; );&lt;br /&gt;
   // ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
That will not work, because the class &amp;quot;MyEntityClass&amp;quot; is not native to the gamedll.  Instead, you would need to hook TakeDamage for &amp;quot;info_target&amp;quot;, and do some form of parsing on the entities that get passed to it (such as checking classname), if you want to deal with custom entity hooking.&lt;br /&gt;
&lt;br /&gt;
==== End of Chain Derivatives ====&lt;br /&gt;
The normal way virtual functions get called is by a virtual table that resides somewhere in the class.  A magical index is assigned to each function, and then it looks up the function pointer inside of the virtual table, and executes the required function.&lt;br /&gt;
&lt;br /&gt;
However, compilers are smart enough to optimize away the virtual function lookup if it knows two things about a call:&lt;br /&gt;
* The exact class type of the entity.&lt;br /&gt;
* That the entity is not derived any further.&lt;br /&gt;
&lt;br /&gt;
An example would be using the hierarchy shown earlier.  If, inside of CBot::TakeDamage a call to the virtual function CBot::Killed is made, most compilers will optimize the virtual function lookup out, so that CBot::TakeDamage would then directly call CBot::Killed.  This means that the hook would never be called.&lt;br /&gt;
&lt;br /&gt;
Fortunately, these instances are kind of rare.&lt;br /&gt;
&lt;br /&gt;
==== Config File Requirements ====&lt;br /&gt;
Every hook and every ExecuteHam() call requires an entry for the function which the scripter is attempting to hook or execute.  The function needs to be in the amxmodx/configs/hamdata.ini config file, under the game mod and operating system.&lt;br /&gt;
&lt;br /&gt;
If a function that the script attempts to hook or call is not configured in the hamdata.ini file, then the module will cause the plugin to cease operation, as this is a fatal error.&lt;br /&gt;
&lt;br /&gt;
The fatal errors can be filtered out by including a forward in the script called '''HamFilter'''.  This is similar to native/module filters available inside of the core of amxmodx, whenever a fatal error occurs, it will pass along the parameters to HamFilter, and if HamFilter returns '''PLUGIN_HANDLED''', the error will be ignored (but the attempted hook or execution will not take place).  If the forward does not exist, or if it returns something other than PLUGIN_HANDLED, the plugin will fail.&lt;br /&gt;
&lt;br /&gt;
An example layout for HamFilter:&lt;br /&gt;
 public HamFilter(Ham:which, HamError:err, const reason[])&lt;br /&gt;
 {&lt;br /&gt;
   // Ignore an unconfigured ns_awardkill&lt;br /&gt;
   if (which == Ham_NS_AwardKill &amp;amp;&amp;amp; err == HAM_FUNC_NOT_CONFIGURED)(&lt;br /&gt;
   {&lt;br /&gt;
     return PLUGIN_HANDLED;&lt;br /&gt;
   }&lt;br /&gt;
   // We absolutely need to be able to use cs_roundrespawn!&lt;br /&gt;
   // If we can't, then the plugin cannot continue.&lt;br /&gt;
   if (which == Ham_CS_RoundRespawn)&lt;br /&gt;
   {&lt;br /&gt;
     return 0;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Additionally, you can check to see if a function is valid to execute or hook by using the '''IsHamValid()''' native.  The validity of a function is determined when the module is first loaded, and it will never change, so if you want to check it, there is no need to do so before every execute.&lt;br /&gt;
&lt;br /&gt;
== Supported Mods ==&lt;br /&gt;
=== Mostly Supported ===&lt;br /&gt;
These mods have a very large list of functions that are usable in the module. &lt;br /&gt;
* Counter-Strike 1.6&lt;br /&gt;
* Condition Zero&lt;br /&gt;
* Day of Defeat&lt;br /&gt;
* Team Fortress Classic&lt;br /&gt;
* The Specialists&lt;br /&gt;
* Natural-Selection&lt;br /&gt;
&lt;br /&gt;
=== Weakly Supported ===&lt;br /&gt;
Because these mods do not contain a Linux binary, they are much harder to disassemble.  There is only plans for disassembling two functions for each (TakeDamage and Use).&lt;br /&gt;
* Sven-Coop&lt;br /&gt;
* Earth's Special Forces&lt;br /&gt;
&lt;br /&gt;
== Hooking Functions ==&lt;br /&gt;
The big feature for Ham Sandwich is the ability to hook virtual functions.&lt;br /&gt;
&lt;br /&gt;
=== Creating the Hook ===&lt;br /&gt;
Creating a hook is a lot like creating a hook in Fakemeta.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;player_hurt&amp;quot;, &amp;quot;player&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public player_hurt(this, inflictor, attacker, Float:damage, damagebits)&lt;br /&gt;
 {&lt;br /&gt;
   // Stuff...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This creates a basic hook which is called any time a player takes damage.  Look in '''ham_const.inc''' for forward parameters for each hook.&lt;br /&gt;
&lt;br /&gt;
Like FakeMeta, there is a hidden last parameter (it goes after the classname in this case).  Set it to 1 to do post hooking.&lt;br /&gt;
&lt;br /&gt;
=== Blocking the Hook ===&lt;br /&gt;
Like Fakemeta and Engine, it is possible to stop a function from being called.  This is called '''superceding'''.&lt;br /&gt;
&lt;br /&gt;
Blocking in Ham Sandwich is identical to how it is accomplished in Fakemeta.  In each hook, you return one of four special values:&lt;br /&gt;
&lt;br /&gt;
* HAM_IGNORED - Nothing happened, the call continues.&lt;br /&gt;
* HAM_HANDLED - You did something, but the call continues.&lt;br /&gt;
* HAM_OVERRIDE - The call will still be executed, but instead you will change the return value.&lt;br /&gt;
* HAM_SUPERCEDE - The call is not executed, and you use your return value, if applicable.&lt;br /&gt;
&lt;br /&gt;
You can use the native '''GetHamReturnStatus()''' to check the current return status of the hook.&lt;br /&gt;
&lt;br /&gt;
=== Return Values ===&lt;br /&gt;
You can get or change the return values for all the hooks available in Ham Sandwich.  Look in '''ham_const.inc''' for a list of all hooks and their return values.&lt;br /&gt;
&lt;br /&gt;
These natives will get any ''modified'' return values.&lt;br /&gt;
* native GetHamReturnInteger(&amp;amp;output);&lt;br /&gt;
* native GetHamReturnFloat(&amp;amp;Float:output);&lt;br /&gt;
* native GetHamReturnVector(Float:output[3]);&lt;br /&gt;
* native GetHamReturnEntity(&amp;amp;output);&lt;br /&gt;
* native GetHamReturnString(output[], size);&lt;br /&gt;
&lt;br /&gt;
These natives will get the ''original'' return value from the function.&lt;br /&gt;
* native GetOrigHamReturnInteger(&amp;amp;output);&lt;br /&gt;
* native GetOrigHamReturnFloat(&amp;amp;Float:output);&lt;br /&gt;
* native GetOrigHamReturnVector(Float:output[3]);&lt;br /&gt;
* native GetOrigHamReturnCbase(&amp;amp;output);&lt;br /&gt;
* native GetOrigHamReturnString(output[], size);&lt;br /&gt;
&lt;br /&gt;
These natives will change the return value to whatever you please.&lt;br /&gt;
* native SetHamReturnInteger(value);&lt;br /&gt;
* native SetHamReturnFloat(Float:value);&lt;br /&gt;
* native SetHamReturnVector(const Float:value[3]);&lt;br /&gt;
* native SetHamReturnEntity(value);&lt;br /&gt;
* native SetHamReturnString(const value[]);&lt;br /&gt;
&lt;br /&gt;
=== Changing Hook Parameters ===&lt;br /&gt;
One feature available in Ham Sandwich that is not available in FakeMeta is the ability to change all parameters on the fly for each hook.&lt;br /&gt;
&lt;br /&gt;
This means that, for example, if you wanted to make a plugin that halved all damage players take, you would do something like this:&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;player_hurt&amp;quot;, &amp;quot;player&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 public player_hurt(this, inflictor, attacker, Float:damage, damagebits)&lt;br /&gt;
 {&lt;br /&gt;
   SetHamParamFloat(4, damage / 2.0);&lt;br /&gt;
   return HAM_HANDLED;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
All hooks after the one you change them in will see the modified values.  Hooks are executed in the order in which they are registered.&lt;br /&gt;
&lt;br /&gt;
All available parameter changing natives are:&lt;br /&gt;
&lt;br /&gt;
* native SetHamParamInteger(which, value);&lt;br /&gt;
* native SetHamParamFloat(which, Float:value);&lt;br /&gt;
* native SetHamParamVector(which, const Float:value[3]);&lt;br /&gt;
* native SetHamParamEntity(which, value);&lt;br /&gt;
* native SetHamParamString(which, const output[]);&lt;br /&gt;
* native SetHamParamTraceResult(which, tr_handle);&lt;br /&gt;
&lt;br /&gt;
=== Disabling Hooks ===&lt;br /&gt;
&lt;br /&gt;
Similar to how FakeMeta allows for unregistering of hooks with unregister_forward, HamSandwich will allow you to disable and enable hooks whenever you want.&lt;br /&gt;
&lt;br /&gt;
The '''RegisterHam''' function will return a handle (tagged with HamHook).  You can then make subsequent calls to DisableHamHook() and EnableHamHook() with the handle to stop it from forwarding, or enable its forwards again.&lt;br /&gt;
&lt;br /&gt;
There is no way to completely unregister the hooks (until map change), as deleting a hook is a delicate process.&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4511</id>
		<title>HamSandwich General Usage (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4511"/>
		<updated>2007-05-11T03:34:30Z</updated>

		<summary type="html">&lt;p&gt;Sawce: /* About Ham Sandwich */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Ham Sandwich ==&lt;br /&gt;
Ham Sandwich is a module that provides additional hooking and function calling capabilities to [[AMX Mod X]].  It is scheduled to be included with the 1.8 branch of AMX Mod X.&lt;br /&gt;
&lt;br /&gt;
Instead of hooking and executing Half-Life engine calls, like the modules FakeMeta and Engine do, this hooks and executes virtual function calls.&lt;br /&gt;
&lt;br /&gt;
=== What is a virtual function? ===&lt;br /&gt;
A virtual function is a member function of a class in C++.  In the case of Ham Sandwich, the virtual function would be a member function of a game entity.  The virtual functions deal with various events in game, such as damage, and using entities.&lt;br /&gt;
&lt;br /&gt;
Unlike normal member functions, virtual functions can be changed by class derivatives.  For example, a typical hierarchy of entities in Half-Life game dlls look something like this:&lt;br /&gt;
&lt;br /&gt;
 CBaseEntity&lt;br /&gt;
    CBaseAnimating&lt;br /&gt;
       CBaseMonster&lt;br /&gt;
          CZombie&lt;br /&gt;
          CHeadCrab&lt;br /&gt;
          CBarnacle&lt;br /&gt;
          CBasePlayer&lt;br /&gt;
             CBot&lt;br /&gt;
&lt;br /&gt;
Now for example, if CBaseEntity has the virtual function called &amp;quot;FunctionA&amp;quot;, and that function does nothing.  But, CBarnacle also declares the function &amp;quot;FunctionA&amp;quot;, and instead of doing nothing it causes the barnacle to die.&lt;br /&gt;
&lt;br /&gt;
If something like this were to be executed:&lt;br /&gt;
 CBaseEntity *ent=GET_PRIVATE(entity);&lt;br /&gt;
 ent-&amp;gt;FunctionA();&lt;br /&gt;
&lt;br /&gt;
And the entity were a barnacle, the barnacle would die.  If the entity was a zombie, nothing would happen.&lt;br /&gt;
&lt;br /&gt;
=== What are some limitations? ===&lt;br /&gt;
&lt;br /&gt;
Dealing with virtual functions have a couple minor drawbacks.&lt;br /&gt;
==== Custom Entities ====&lt;br /&gt;
Hooking virtual functions, such as TakeDamage, that get called on custom entities is a little bit awkward.&lt;br /&gt;
&lt;br /&gt;
Because of the way where classes derive, and they get their own virtual table for each class, the type of class that the game dll allocates will be whatever gets hooked for a particular hook.&lt;br /&gt;
&lt;br /&gt;
For example, say you have a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 new myStr;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   myStr = engfunc( EngFunc_AllocString, &amp;quot;info_target&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   register_clcmd( &amp;quot;make_entity&amp;quot;, &amp;quot;cmdMakeEntity&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;damageHook&amp;quot;, &amp;quot;MyEntityClass&amp;quot;); // Error!&lt;br /&gt;
 }&lt;br /&gt;
 public cmdMakeEntity( id )&lt;br /&gt;
 {&lt;br /&gt;
   new ent = engfunc( EngFunc_CreateEntity, myStr );&lt;br /&gt;
   set_pev( ent, pev_classname, &amp;quot;MyEntityClass&amp;quot; );&lt;br /&gt;
   // ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
That will not work, because the class &amp;quot;MyEntityClass&amp;quot; is not native to the gamedll.  Instead, you would need to hook TakeDamage for &amp;quot;info_target&amp;quot;, and do some form of parsing on the entities that get passed to it (such as checking classname), if you want to deal with custom entity hooking.&lt;br /&gt;
&lt;br /&gt;
==== End of Chain Derivatives ====&lt;br /&gt;
The normal way virtual functions get called is by a virtual table that resides somewhere in the class.  A magical index is assigned to each function, and then it looks up the function pointer inside of the virtual table, and executes the required function.&lt;br /&gt;
&lt;br /&gt;
However, compilers are smart enough to optimize away the virtual function lookup if it knows two things about a call:&lt;br /&gt;
* The exact class type of the entity.&lt;br /&gt;
* That the entity is not derived any further.&lt;br /&gt;
&lt;br /&gt;
An example would be using the hierarchy shown earlier.  If, inside of CBot::TakeDamage a call to the virtual function CBot::Killed is made, most compilers will optimize the virtual function lookup out, so that CBot::TakeDamage would then directly call CBot::Killed.  This means that the hook would never be called.&lt;br /&gt;
&lt;br /&gt;
Fortunately, these instances are kind of rare.&lt;br /&gt;
&lt;br /&gt;
==== Config File Requirements ====&lt;br /&gt;
Every hook and every ExecuteHam() call requires an entry for the function which the scripter is attempting to hook or execute.  The function needs to be in the amxmodx/configs/hamdata.ini config file, under the game mod and operating system.&lt;br /&gt;
&lt;br /&gt;
If a function that the script attempts to hook or call is not configured in the hamdata.ini file, then the module will cause the plugin to cease operation, as this is a fatal error.&lt;br /&gt;
&lt;br /&gt;
The fatal errors can be filtered out by including a forward in the script called '''HamFilter'''.  This is similar to native/module filters available inside of the core of amxmodx, whenever a fatal error occurs, it will pass along the parameters to HamFilter, and if HamFilter returns '''PLUGIN_HANDLED''', the error will be ignored (but the attempted hook or execution will not take place).  If the forward does not exist, or if it returns something other than PLUGIN_HANDLED, the plugin will fail.&lt;br /&gt;
&lt;br /&gt;
An example layout for HamFilter:&lt;br /&gt;
 public HamFilter(Ham:which, HamError:err, const reason[])&lt;br /&gt;
 {&lt;br /&gt;
   // Ignore an unconfigured ns_awardkill&lt;br /&gt;
   if (which == Ham_NS_AwardKill &amp;amp;&amp;amp; err == HAM_FUNC_NOT_CONFIGURED)(&lt;br /&gt;
   {&lt;br /&gt;
     return PLUGIN_HANDLED;&lt;br /&gt;
   }&lt;br /&gt;
   // We absolutely need to be able to use cs_roundrespawn!&lt;br /&gt;
   // If we can't, then the plugin cannot continue.&lt;br /&gt;
   if (which == Ham_CS_RoundRespawn)&lt;br /&gt;
   {&lt;br /&gt;
     return 0;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Supported Mods ==&lt;br /&gt;
=== Mostly Supported ===&lt;br /&gt;
These mods have a very large list of functions that are usable in the module. &lt;br /&gt;
* Counter-Strike 1.6&lt;br /&gt;
* Condition Zero&lt;br /&gt;
* Day of Defeat&lt;br /&gt;
* Team Fortress Classic&lt;br /&gt;
* The Specialists&lt;br /&gt;
* Natural-Selection&lt;br /&gt;
&lt;br /&gt;
=== Weakly Supported ===&lt;br /&gt;
Because these mods do not contain a Linux binary, they are much harder to disassemble.  There is only plans for disassembling two functions for each (TakeDamage and Use).&lt;br /&gt;
* Sven-Coop&lt;br /&gt;
* Earth's Special Forces&lt;br /&gt;
&lt;br /&gt;
== Hooking Functions ==&lt;br /&gt;
The big feature for Ham Sandwich is the ability to hook virtual functions.&lt;br /&gt;
&lt;br /&gt;
=== Creating the Hook ===&lt;br /&gt;
Creating a hook is a lot like creating a hook in Fakemeta.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;player_hurt&amp;quot;, &amp;quot;player&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public player_hurt(this, inflictor, attacker, Float:damage, damagebits)&lt;br /&gt;
 {&lt;br /&gt;
   // Stuff...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This creates a basic hook which is called any time a player takes damage.  Look in '''ham_const.inc''' for forward parameters for each hook.&lt;br /&gt;
&lt;br /&gt;
Like FakeMeta, there is a hidden last parameter (it goes after the classname in this case).  Set it to 1 to do post hooking.&lt;br /&gt;
&lt;br /&gt;
=== Blocking the Hook ===&lt;br /&gt;
Like Fakemeta and Engine, it is possible to stop a function from being called.  This is called '''superceding'''.&lt;br /&gt;
&lt;br /&gt;
Blocking in Ham Sandwich is identical to how it is accomplished in Fakemeta.  In each hook, you return one of four special values:&lt;br /&gt;
&lt;br /&gt;
* HAM_IGNORED - Nothing happened, the call continues.&lt;br /&gt;
* HAM_HANDLED - You did something, but the call continues.&lt;br /&gt;
* HAM_OVERRIDE - The call will still be executed, but instead you will change the return value.&lt;br /&gt;
* HAM_SUPERCEDE - The call is not executed, and you use your return value, if applicable.&lt;br /&gt;
&lt;br /&gt;
You can use the native '''GetHamReturnStatus()''' to check the current return status of the hook.&lt;br /&gt;
&lt;br /&gt;
=== Return Values ===&lt;br /&gt;
You can get or change the return values for all the hooks available in Ham Sandwich.  Look in '''ham_const.inc''' for a list of all hooks and their return values.&lt;br /&gt;
&lt;br /&gt;
These natives will get any ''modified'' return values.&lt;br /&gt;
* native GetHamReturnInteger(&amp;amp;output);&lt;br /&gt;
* native GetHamReturnFloat(&amp;amp;Float:output);&lt;br /&gt;
* native GetHamReturnVector(Float:output[3]);&lt;br /&gt;
* native GetHamReturnEntity(&amp;amp;output);&lt;br /&gt;
* native GetHamReturnString(output[], size);&lt;br /&gt;
&lt;br /&gt;
These natives will get the ''original'' return value from the function.&lt;br /&gt;
* native GetOrigHamReturnInteger(&amp;amp;output);&lt;br /&gt;
* native GetOrigHamReturnFloat(&amp;amp;Float:output);&lt;br /&gt;
* native GetOrigHamReturnVector(Float:output[3]);&lt;br /&gt;
* native GetOrigHamReturnCbase(&amp;amp;output);&lt;br /&gt;
* native GetOrigHamReturnString(output[], size);&lt;br /&gt;
&lt;br /&gt;
These natives will change the return value to whatever you please.&lt;br /&gt;
* native SetHamReturnInteger(value);&lt;br /&gt;
* native SetHamReturnFloat(Float:value);&lt;br /&gt;
* native SetHamReturnVector(const Float:value[3]);&lt;br /&gt;
* native SetHamReturnEntity(value);&lt;br /&gt;
* native SetHamReturnString(const value[]);&lt;br /&gt;
&lt;br /&gt;
=== Changing Hook Parameters ===&lt;br /&gt;
One feature available in Ham Sandwich that is not available in FakeMeta is the ability to change all parameters on the fly for each hook.&lt;br /&gt;
&lt;br /&gt;
This means that, for example, if you wanted to make a plugin that halved all damage players take, you would do something like this:&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;player_hurt&amp;quot;, &amp;quot;player&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 public player_hurt(this, inflictor, attacker, Float:damage, damagebits)&lt;br /&gt;
 {&lt;br /&gt;
   SetHamParamFloat(4, damage / 2.0);&lt;br /&gt;
   return HAM_HANDLED;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
All hooks after the one you change them in will see the modified values.  Hooks are executed in the order in which they are registered.&lt;br /&gt;
&lt;br /&gt;
All available parameter changing natives are:&lt;br /&gt;
&lt;br /&gt;
* native SetHamParamInteger(which, value);&lt;br /&gt;
* native SetHamParamFloat(which, Float:value);&lt;br /&gt;
* native SetHamParamVector(which, const Float:value[3]);&lt;br /&gt;
* native SetHamParamEntity(which, value);&lt;br /&gt;
* native SetHamParamString(which, const output[]);&lt;br /&gt;
* native SetHamParamTraceResult(which, tr_handle);&lt;br /&gt;
&lt;br /&gt;
=== Disabling Hooks ===&lt;br /&gt;
&lt;br /&gt;
Similar to how FakeMeta allows for unregistering of hooks with unregister_forward, HamSandwich will allow you to disable and enable hooks whenever you want.&lt;br /&gt;
&lt;br /&gt;
The '''RegisterHam''' function will return a handle (tagged with HamHook).  You can then make subsequent calls to DisableHamHook() and EnableHamHook() with the handle to stop it from forwarding, or enable its forwards again.&lt;br /&gt;
&lt;br /&gt;
There is no way to completely unregister the hooks (until map change), as deleting a hook is a delicate process.&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4510</id>
		<title>HamSandwich General Usage (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4510"/>
		<updated>2007-05-11T03:24:43Z</updated>

		<summary type="html">&lt;p&gt;Sawce: /* Hooking Functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Ham Sandwich ==&lt;br /&gt;
Ham Sandwich is a module that provides additional hooking and function calling capabilities to [[AMX Mod X]].  It is scheduled to be included with the 1.8 branch of AMX Mod X.&lt;br /&gt;
&lt;br /&gt;
Instead of hooking and executing Half-Life engine calls, like the modules FakeMeta and Engine do, this hooks and executes virtual function calls.&lt;br /&gt;
&lt;br /&gt;
=== What is a virtual function? ===&lt;br /&gt;
A virtual function is a member function of a class in C++.  In the case of Ham Sandwich, the virtual function would be a member function of a game entity.  The virtual functions deal with various events in game, such as damage, and using entities.&lt;br /&gt;
&lt;br /&gt;
Unlike normal member functions, virtual functions can be changed by class derivatives.  For example, a typical hierarchy of entities in Half-Life game dlls look something like this:&lt;br /&gt;
&lt;br /&gt;
 CBaseEntity&lt;br /&gt;
    CBaseAnimating&lt;br /&gt;
       CBaseMonster&lt;br /&gt;
          CZombie&lt;br /&gt;
          CHeadCrab&lt;br /&gt;
          CBarnacle&lt;br /&gt;
          CBasePlayer&lt;br /&gt;
             CBot&lt;br /&gt;
&lt;br /&gt;
Now for example, if CBaseEntity has the virtual function called &amp;quot;FunctionA&amp;quot;, and that function does nothing.  But, CBarnacle also declares the function &amp;quot;FunctionA&amp;quot;, and instead of doing nothing it causes the barnacle to die.&lt;br /&gt;
&lt;br /&gt;
If something like this were to be executed:&lt;br /&gt;
 CBaseEntity *ent=GET_PRIVATE(entity);&lt;br /&gt;
 ent-&amp;gt;FunctionA();&lt;br /&gt;
&lt;br /&gt;
And the entity were a barnacle, the barnacle would die.  If the entity was a zombie, nothing would happen.&lt;br /&gt;
&lt;br /&gt;
=== What are some limitations? ===&lt;br /&gt;
&lt;br /&gt;
Dealing with virtual functions have a couple minor drawbacks.&lt;br /&gt;
==== Custom Entities ====&lt;br /&gt;
Hooking virtual functions, such as TakeDamage, that get called on custom entities is a little bit awkward.&lt;br /&gt;
&lt;br /&gt;
Because of the way where classes derive, and they get their own virtual table for each class, the type of class that the game dll allocates will be whatever gets hooked for a particular hook.&lt;br /&gt;
&lt;br /&gt;
For example, say you have a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 new myStr;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   myStr = engfunc( EngFunc_AllocString, &amp;quot;info_target&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   register_clcmd( &amp;quot;make_entity&amp;quot;, &amp;quot;cmdMakeEntity&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;damageHook&amp;quot;, &amp;quot;MyEntityClass&amp;quot;); // Error!&lt;br /&gt;
 }&lt;br /&gt;
 public cmdMakeEntity( id )&lt;br /&gt;
 {&lt;br /&gt;
   new ent = engfunc( EngFunc_CreateEntity, myStr );&lt;br /&gt;
   set_pev( ent, pev_classname, &amp;quot;MyEntityClass&amp;quot; );&lt;br /&gt;
   // ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
That will not work, because the class &amp;quot;MyEntityClass&amp;quot; is not native to the gamedll.  Instead, you would need to hook TakeDamage for &amp;quot;info_target&amp;quot;, and do some form of parsing on the entities that get passed to it (such as checking classname), if you want to deal with custom entity hooking.&lt;br /&gt;
&lt;br /&gt;
==== End of Chain Derivatives ====&lt;br /&gt;
The normal way virtual functions get called is by a virtual table that resides somewhere in the class.  A magical index is assigned to each function, and then it looks up the function pointer inside of the virtual table, and executes the required function.&lt;br /&gt;
&lt;br /&gt;
However, compilers are smart enough to optimize away the virtual function lookup if it knows two things about a call:&lt;br /&gt;
* The exact class type of the entity.&lt;br /&gt;
* That the entity is not derived any further.&lt;br /&gt;
&lt;br /&gt;
An example would be using the hierarchy shown earlier.  If, inside of CBot::TakeDamage a call to the virtual function CBot::Killed is made, most compilers will optimize the virtual function lookup out, so that CBot::TakeDamage would then directly call CBot::Killed.  This means that the hook would never be called.&lt;br /&gt;
&lt;br /&gt;
Fortunately, these instances are kind of rare.&lt;br /&gt;
&lt;br /&gt;
== Supported Mods ==&lt;br /&gt;
=== Mostly Supported ===&lt;br /&gt;
These mods have a very large list of functions that are usable in the module. &lt;br /&gt;
* Counter-Strike 1.6&lt;br /&gt;
* Condition Zero&lt;br /&gt;
* Day of Defeat&lt;br /&gt;
* Team Fortress Classic&lt;br /&gt;
* The Specialists&lt;br /&gt;
* Natural-Selection&lt;br /&gt;
&lt;br /&gt;
=== Weakly Supported ===&lt;br /&gt;
Because these mods do not contain a Linux binary, they are much harder to disassemble.  There is only plans for disassembling two functions for each (TakeDamage and Use).&lt;br /&gt;
* Sven-Coop&lt;br /&gt;
* Earth's Special Forces&lt;br /&gt;
&lt;br /&gt;
== Hooking Functions ==&lt;br /&gt;
The big feature for Ham Sandwich is the ability to hook virtual functions.&lt;br /&gt;
&lt;br /&gt;
=== Creating the Hook ===&lt;br /&gt;
Creating a hook is a lot like creating a hook in Fakemeta.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;player_hurt&amp;quot;, &amp;quot;player&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public player_hurt(this, inflictor, attacker, Float:damage, damagebits)&lt;br /&gt;
 {&lt;br /&gt;
   // Stuff...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This creates a basic hook which is called any time a player takes damage.  Look in '''ham_const.inc''' for forward parameters for each hook.&lt;br /&gt;
&lt;br /&gt;
Like FakeMeta, there is a hidden last parameter (it goes after the classname in this case).  Set it to 1 to do post hooking.&lt;br /&gt;
&lt;br /&gt;
=== Blocking the Hook ===&lt;br /&gt;
Like Fakemeta and Engine, it is possible to stop a function from being called.  This is called '''superceding'''.&lt;br /&gt;
&lt;br /&gt;
Blocking in Ham Sandwich is identical to how it is accomplished in Fakemeta.  In each hook, you return one of four special values:&lt;br /&gt;
&lt;br /&gt;
* HAM_IGNORED - Nothing happened, the call continues.&lt;br /&gt;
* HAM_HANDLED - You did something, but the call continues.&lt;br /&gt;
* HAM_OVERRIDE - The call will still be executed, but instead you will change the return value.&lt;br /&gt;
* HAM_SUPERCEDE - The call is not executed, and you use your return value, if applicable.&lt;br /&gt;
&lt;br /&gt;
You can use the native '''GetHamReturnStatus()''' to check the current return status of the hook.&lt;br /&gt;
&lt;br /&gt;
=== Return Values ===&lt;br /&gt;
You can get or change the return values for all the hooks available in Ham Sandwich.  Look in '''ham_const.inc''' for a list of all hooks and their return values.&lt;br /&gt;
&lt;br /&gt;
These natives will get any ''modified'' return values.&lt;br /&gt;
* native GetHamReturnInteger(&amp;amp;output);&lt;br /&gt;
* native GetHamReturnFloat(&amp;amp;Float:output);&lt;br /&gt;
* native GetHamReturnVector(Float:output[3]);&lt;br /&gt;
* native GetHamReturnEntity(&amp;amp;output);&lt;br /&gt;
* native GetHamReturnString(output[], size);&lt;br /&gt;
&lt;br /&gt;
These natives will get the ''original'' return value from the function.&lt;br /&gt;
* native GetOrigHamReturnInteger(&amp;amp;output);&lt;br /&gt;
* native GetOrigHamReturnFloat(&amp;amp;Float:output);&lt;br /&gt;
* native GetOrigHamReturnVector(Float:output[3]);&lt;br /&gt;
* native GetOrigHamReturnCbase(&amp;amp;output);&lt;br /&gt;
* native GetOrigHamReturnString(output[], size);&lt;br /&gt;
&lt;br /&gt;
These natives will change the return value to whatever you please.&lt;br /&gt;
* native SetHamReturnInteger(value);&lt;br /&gt;
* native SetHamReturnFloat(Float:value);&lt;br /&gt;
* native SetHamReturnVector(const Float:value[3]);&lt;br /&gt;
* native SetHamReturnEntity(value);&lt;br /&gt;
* native SetHamReturnString(const value[]);&lt;br /&gt;
&lt;br /&gt;
=== Changing Hook Parameters ===&lt;br /&gt;
One feature available in Ham Sandwich that is not available in FakeMeta is the ability to change all parameters on the fly for each hook.&lt;br /&gt;
&lt;br /&gt;
This means that, for example, if you wanted to make a plugin that halved all damage players take, you would do something like this:&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;player_hurt&amp;quot;, &amp;quot;player&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 public player_hurt(this, inflictor, attacker, Float:damage, damagebits)&lt;br /&gt;
 {&lt;br /&gt;
   SetHamParamFloat(4, damage / 2.0);&lt;br /&gt;
   return HAM_HANDLED;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
All hooks after the one you change them in will see the modified values.  Hooks are executed in the order in which they are registered.&lt;br /&gt;
&lt;br /&gt;
All available parameter changing natives are:&lt;br /&gt;
&lt;br /&gt;
* native SetHamParamInteger(which, value);&lt;br /&gt;
* native SetHamParamFloat(which, Float:value);&lt;br /&gt;
* native SetHamParamVector(which, const Float:value[3]);&lt;br /&gt;
* native SetHamParamEntity(which, value);&lt;br /&gt;
* native SetHamParamString(which, const output[]);&lt;br /&gt;
* native SetHamParamTraceResult(which, tr_handle);&lt;br /&gt;
&lt;br /&gt;
=== Disabling Hooks ===&lt;br /&gt;
&lt;br /&gt;
Similar to how FakeMeta allows for unregistering of hooks with unregister_forward, HamSandwich will allow you to disable and enable hooks whenever you want.&lt;br /&gt;
&lt;br /&gt;
The '''RegisterHam''' function will return a handle (tagged with HamHook).  You can then make subsequent calls to DisableHamHook() and EnableHamHook() with the handle to stop it from forwarding, or enable its forwards again.&lt;br /&gt;
&lt;br /&gt;
There is no way to completely unregister the hooks (until map change), as deleting a hook is a delicate process.&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4508</id>
		<title>HamSandwich General Usage (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4508"/>
		<updated>2007-05-10T18:38:16Z</updated>

		<summary type="html">&lt;p&gt;Sawce: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Ham Sandwich ==&lt;br /&gt;
Ham Sandwich is a module that provides additional hooking and function calling capabilities to [[AMX Mod X]].  It is scheduled to be included with the 1.8 branch of AMX Mod X.&lt;br /&gt;
&lt;br /&gt;
Instead of hooking and executing Half-Life engine calls, like the modules FakeMeta and Engine do, this hooks and executes virtual function calls.&lt;br /&gt;
&lt;br /&gt;
=== What is a virtual function? ===&lt;br /&gt;
A virtual function is a member function of a class in C++.  In the case of Ham Sandwich, the virtual function would be a member function of a game entity.  The virtual functions deal with various events in game, such as damage, and using entities.&lt;br /&gt;
&lt;br /&gt;
Unlike normal member functions, virtual functions can be changed by class derivatives.  For example, a typical hierarchy of entities in Half-Life game dlls look something like this:&lt;br /&gt;
&lt;br /&gt;
 CBaseEntity&lt;br /&gt;
    CBaseAnimating&lt;br /&gt;
       CBaseMonster&lt;br /&gt;
          CZombie&lt;br /&gt;
          CHeadCrab&lt;br /&gt;
          CBarnacle&lt;br /&gt;
          CBasePlayer&lt;br /&gt;
             CBot&lt;br /&gt;
&lt;br /&gt;
Now for example, if CBaseEntity has the virtual function called &amp;quot;FunctionA&amp;quot;, and that function does nothing.  But, CBarnacle also declares the function &amp;quot;FunctionA&amp;quot;, and instead of doing nothing it causes the barnacle to die.&lt;br /&gt;
&lt;br /&gt;
If something like this were to be executed:&lt;br /&gt;
 CBaseEntity *ent=GET_PRIVATE(entity);&lt;br /&gt;
 ent-&amp;gt;FunctionA();&lt;br /&gt;
&lt;br /&gt;
And the entity were a barnacle, the barnacle would die.  If the entity was a zombie, nothing would happen.&lt;br /&gt;
&lt;br /&gt;
=== What are some limitations? ===&lt;br /&gt;
&lt;br /&gt;
Dealing with virtual functions have a couple minor drawbacks.&lt;br /&gt;
==== Custom Entities ====&lt;br /&gt;
Hooking virtual functions, such as TakeDamage, that get called on custom entities is a little bit awkward.&lt;br /&gt;
&lt;br /&gt;
Because of the way where classes derive, and they get their own virtual table for each class, the type of class that the game dll allocates will be whatever gets hooked for a particular hook.&lt;br /&gt;
&lt;br /&gt;
For example, say you have a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 new myStr;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   myStr = engfunc( EngFunc_AllocString, &amp;quot;info_target&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   register_clcmd( &amp;quot;make_entity&amp;quot;, &amp;quot;cmdMakeEntity&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;damageHook&amp;quot;, &amp;quot;MyEntityClass&amp;quot;); // Error!&lt;br /&gt;
 }&lt;br /&gt;
 public cmdMakeEntity( id )&lt;br /&gt;
 {&lt;br /&gt;
   new ent = engfunc( EngFunc_CreateEntity, myStr );&lt;br /&gt;
   set_pev( ent, pev_classname, &amp;quot;MyEntityClass&amp;quot; );&lt;br /&gt;
   // ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
That will not work, because the class &amp;quot;MyEntityClass&amp;quot; is not native to the gamedll.  Instead, you would need to hook TakeDamage for &amp;quot;info_target&amp;quot;, and do some form of parsing on the entities that get passed to it (such as checking classname), if you want to deal with custom entity hooking.&lt;br /&gt;
&lt;br /&gt;
==== End of Chain Derivatives ====&lt;br /&gt;
The normal way virtual functions get called is by a virtual table that resides somewhere in the class.  A magical index is assigned to each function, and then it looks up the function pointer inside of the virtual table, and executes the required function.&lt;br /&gt;
&lt;br /&gt;
However, compilers are smart enough to optimize away the virtual function lookup if it knows two things about a call:&lt;br /&gt;
* The exact class type of the entity.&lt;br /&gt;
* That the entity is not derived any further.&lt;br /&gt;
&lt;br /&gt;
An example would be using the hierarchy shown earlier.  If, inside of CBot::TakeDamage a call to the virtual function CBot::Killed is made, most compilers will optimize the virtual function lookup out, so that CBot::TakeDamage would then directly call CBot::Killed.  This means that the hook would never be called.&lt;br /&gt;
&lt;br /&gt;
Fortunately, these instances are kind of rare.&lt;br /&gt;
&lt;br /&gt;
== Supported Mods ==&lt;br /&gt;
=== Mostly Supported ===&lt;br /&gt;
These mods have a very large list of functions that are usable in the module. &lt;br /&gt;
* Counter-Strike 1.6&lt;br /&gt;
* Condition Zero&lt;br /&gt;
* Day of Defeat&lt;br /&gt;
* Team Fortress Classic&lt;br /&gt;
* The Specialists&lt;br /&gt;
* Natural-Selection&lt;br /&gt;
&lt;br /&gt;
=== Weakly Supported ===&lt;br /&gt;
Because these mods do not contain a Linux binary, they are much harder to disassemble.  There is only plans for disassembling two functions for each (TakeDamage and Use).&lt;br /&gt;
* Sven-Coop&lt;br /&gt;
* Earth's Special Forces&lt;br /&gt;
&lt;br /&gt;
== Hooking Functions ==&lt;br /&gt;
The big feature for Ham Sandwich is the ability to hook virtual functions.&lt;br /&gt;
&lt;br /&gt;
=== Creating the Hook ===&lt;br /&gt;
Creating a hook is a lot like creating a hook in Fakemeta.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;player_hurt&amp;quot;, &amp;quot;player&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public player_hurt(this, inflictor, attacker, Float:damage, damagebits)&lt;br /&gt;
 {&lt;br /&gt;
   // Stuff...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This creates a basic hook which is called any time a player takes damage.  Look in '''ham_const.inc''' for forward parameters for each hook.&lt;br /&gt;
&lt;br /&gt;
Like FakeMeta, there is a hidden last parameter (it goes after the classname in this case).  Set it to 1 to do post hooking.&lt;br /&gt;
&lt;br /&gt;
=== Blocking the Hook ===&lt;br /&gt;
Like Fakemeta and Engine, it is possible to stop a function from being called.  This is called '''superceding'''.&lt;br /&gt;
&lt;br /&gt;
Blocking in Ham Sandwich is identical to how it is accomplished in Fakemeta.  In each hook, you return one of four special values:&lt;br /&gt;
&lt;br /&gt;
* HAM_IGNORED - Nothing happened, the call continues.&lt;br /&gt;
* HAM_HANDLED - You did something, but the call continues.&lt;br /&gt;
* HAM_OVERRIDE - The call will still be executed, but instead you will change the return value.&lt;br /&gt;
* HAM_SUPERCEDE - The call is not executed, and you use your return value, if applicable.&lt;br /&gt;
&lt;br /&gt;
You can use the native '''GetHamReturnStatus()''' to check the current return status of the hook.&lt;br /&gt;
&lt;br /&gt;
=== Return Values ===&lt;br /&gt;
You can get or change the return values for all the hooks available in Ham Sandwich.  Look in '''ham_const.inc''' for a list of all hooks and their return values.&lt;br /&gt;
&lt;br /&gt;
These natives will get any ''modified'' return values.&lt;br /&gt;
* native GetHamReturnInteger(&amp;amp;output);&lt;br /&gt;
* native GetHamReturnFloat(&amp;amp;Float:output);&lt;br /&gt;
* native GetHamReturnVector(Float:output[3]);&lt;br /&gt;
* native GetHamReturnEntity(&amp;amp;output);&lt;br /&gt;
* native GetHamReturnString(output[], size);&lt;br /&gt;
&lt;br /&gt;
These natives will get the ''original'' return value from the function.&lt;br /&gt;
* native GetOrigHamReturnInteger(&amp;amp;output);&lt;br /&gt;
* native GetOrigHamReturnFloat(&amp;amp;Float:output);&lt;br /&gt;
* native GetOrigHamReturnVector(Float:output[3]);&lt;br /&gt;
* native GetOrigHamReturnCbase(&amp;amp;output);&lt;br /&gt;
* native GetOrigHamReturnString(output[], size);&lt;br /&gt;
&lt;br /&gt;
These natives will change the return value to whatever you please.&lt;br /&gt;
* native SetHamReturnInteger(value);&lt;br /&gt;
* native SetHamReturnFloat(Float:value);&lt;br /&gt;
* native SetHamReturnVector(const Float:value[3]);&lt;br /&gt;
* native SetHamReturnEntity(value);&lt;br /&gt;
* native SetHamReturnString(const value[]);&lt;br /&gt;
&lt;br /&gt;
=== Changing Hook Parameters ===&lt;br /&gt;
One feature available in Ham Sandwich that is not available in FakeMeta is the ability to change all parameters on the fly for each hook.&lt;br /&gt;
&lt;br /&gt;
This means that, for example, if you wanted to make a plugin that halved all damage players take, you would do something like this:&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;player_hurt&amp;quot;, &amp;quot;player&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 public player_hurt(this, inflictor, attacker, Float:damage, damagebits)&lt;br /&gt;
 {&lt;br /&gt;
   SetHamParamFloat(4, damage / 2.0);&lt;br /&gt;
   return HAM_HANDLED;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
All hooks after the one you change them in will see the modified values.  Hooks are executed in the order in which they are registered.&lt;br /&gt;
&lt;br /&gt;
All available parameter changing natives are:&lt;br /&gt;
&lt;br /&gt;
* native SetHamParamInteger(which, value);&lt;br /&gt;
* native SetHamParamFloat(which, Float:value);&lt;br /&gt;
* native SetHamParamVector(which, const Float:value[3]);&lt;br /&gt;
* native SetHamParamEntity(which, value);&lt;br /&gt;
* native SetHamParamString(which, const output[]);&lt;br /&gt;
* native SetHamParamTraceResult(which, tr_handle);&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4507</id>
		<title>HamSandwich General Usage (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4507"/>
		<updated>2007-05-10T18:36:38Z</updated>

		<summary type="html">&lt;p&gt;Sawce: /* Hooking Functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Ham Sandwich ==&lt;br /&gt;
Ham Sandwich is a module that provides additional hooking and function calling capabilities to [[AMX Mod X]].  It is scheduled to be included with the 1.8 branch of AMX Mod X.&lt;br /&gt;
&lt;br /&gt;
Instead of hooking and executing Half-Life engine calls, like the modules FakeMeta and Engine do, this hooks and executes virtual function calls.&lt;br /&gt;
&lt;br /&gt;
=== What is a virtual function? ===&lt;br /&gt;
A virtual function is a member function of a class in C++.  In the case of Ham Sandwich, the virtual function would be a member function of a game entity.  The virtual functions deal with various events in game, such as damage, and using entities.&lt;br /&gt;
&lt;br /&gt;
Unlike normal member functions, virtual functions can be changed by class derivatives.  For example, a typical hierarchy of entities in Half-Life game dlls look something like this:&lt;br /&gt;
&lt;br /&gt;
 CBaseEntity&lt;br /&gt;
    CBaseAnimating&lt;br /&gt;
       CBaseMonster&lt;br /&gt;
          CZombie&lt;br /&gt;
          CHeadCrab&lt;br /&gt;
          CBarnacle&lt;br /&gt;
          CBasePlayer&lt;br /&gt;
             CBot&lt;br /&gt;
&lt;br /&gt;
Now for example, if CBaseEntity has the virtual function called &amp;quot;FunctionA&amp;quot;, and that function does nothing.  But, CBarnacle also declares the function &amp;quot;FunctionA&amp;quot;, and instead of doing nothing it causes the barnacle to die.&lt;br /&gt;
&lt;br /&gt;
If something like this were to be executed:&lt;br /&gt;
 CBaseEntity *ent=GET_PRIVATE(entity);&lt;br /&gt;
 ent-&amp;gt;FunctionA();&lt;br /&gt;
&lt;br /&gt;
And the entity were a barnacle, the barnacle would die.  If the entity was a zombie, nothing would happen.&lt;br /&gt;
&lt;br /&gt;
=== What are some limitations? ===&lt;br /&gt;
&lt;br /&gt;
Dealing with virtual functions have a couple minor drawbacks.&lt;br /&gt;
==== Custom Entities ====&lt;br /&gt;
Hooking virtual functions, such as TakeDamage, that get called on custom entities is a little bit awkward.&lt;br /&gt;
&lt;br /&gt;
Because of the way where classes derive, and they get their own virtual table for each class, the type of class that the game dll allocates will be whatever gets hooked for a particular hook.&lt;br /&gt;
&lt;br /&gt;
For example, say you have a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 new myStr;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   myStr = engfunc( EngFunc_AllocString, &amp;quot;info_target&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   register_clcmd( &amp;quot;make_entity&amp;quot;, &amp;quot;cmdMakeEntity&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;damageHook&amp;quot;, &amp;quot;MyEntityClass&amp;quot;); // Error!&lt;br /&gt;
 }&lt;br /&gt;
 public cmdMakeEntity( id )&lt;br /&gt;
 {&lt;br /&gt;
   new ent = engfunc( EngFunc_CreateEntity, myStr );&lt;br /&gt;
   set_pev( ent, pev_classname, &amp;quot;MyEntityClass&amp;quot; );&lt;br /&gt;
   // ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
That will not work, because the class &amp;quot;MyEntityClass&amp;quot; is not native to the gamedll.  Instead, you would need to hook TakeDamage for &amp;quot;info_target&amp;quot;, and do some form of parsing on the entities that get passed to it (such as checking classname), if you want to deal with custom entity hooking.&lt;br /&gt;
&lt;br /&gt;
==== End of Chain Derivatives ====&lt;br /&gt;
The normal way virtual functions get called is by a virtual table that resides somewhere in the class.  A magical index is assigned to each function, and then it looks up the function pointer inside of the virtual table, and executes the required function.&lt;br /&gt;
&lt;br /&gt;
However, compilers are smart enough to optimize away the virtual function lookup if it knows two things about a call:&lt;br /&gt;
* The exact class type of the entity.&lt;br /&gt;
* That the entity is not derived any further.&lt;br /&gt;
&lt;br /&gt;
An example would be using the hierarchy shown earlier.  If, inside of CBot::TakeDamage a call to the virtual function CBot::Killed is made, most compilers will optimize the virtual function lookup out, so that CBot::TakeDamage would then directly call CBot::Killed.  This means that the hook would never be called.&lt;br /&gt;
&lt;br /&gt;
Fortunately, these instances are kind of rare.&lt;br /&gt;
&lt;br /&gt;
=== Supported Mods ===&lt;br /&gt;
==== Mostly Supported ====&lt;br /&gt;
These mods have a very large list of functions that are usable in the module. &lt;br /&gt;
* Counter-Strike 1.6&lt;br /&gt;
* Condition Zero&lt;br /&gt;
* Day of Defeat&lt;br /&gt;
* Team Fortress Classic&lt;br /&gt;
* The Specialists&lt;br /&gt;
* Natural-Selection&lt;br /&gt;
&lt;br /&gt;
==== Weakly Supported ====&lt;br /&gt;
Because these mods do not contain a Linux binary, they are much harder to disassemble.  There is only plans for disassembling two functions for each (TakeDamage and Use).&lt;br /&gt;
* Sven-Coop&lt;br /&gt;
* Earth's Special Forces&lt;br /&gt;
&lt;br /&gt;
=== Hooking Functions ===&lt;br /&gt;
The big feature for Ham Sandwich is the ability to hook virtual functions.&lt;br /&gt;
&lt;br /&gt;
==== Creating the Hook ====&lt;br /&gt;
Creating a hook is a lot like creating a hook in Fakemeta.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;player_hurt&amp;quot;, &amp;quot;player&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public player_hurt(this, inflictor, attacker, Float:damage, damagebits)&lt;br /&gt;
 {&lt;br /&gt;
   // Stuff...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This creates a basic hook which is called any time a player takes damage.  Look in '''ham_const.inc''' for forward parameters for each hook.&lt;br /&gt;
&lt;br /&gt;
Like FakeMeta, there is a hidden last parameter (it goes after the classname in this case).  Set it to 1 to do post hooking.&lt;br /&gt;
&lt;br /&gt;
==== Blocking the Hook ====&lt;br /&gt;
Like Fakemeta and Engine, it is possible to stop a function from being called.  This is called '''superceding'''.&lt;br /&gt;
&lt;br /&gt;
Blocking in HamSandwich is identical to how it is accomplished in Fakemeta.  In each hook, you return one of four special values:&lt;br /&gt;
&lt;br /&gt;
* HAM_IGNORED - Nothing happened, the call continues.&lt;br /&gt;
* HAM_HANDLED - You did something, but the call continues.&lt;br /&gt;
* HAM_OVERRIDE - The call will still be executed, but instead you will change the return value.&lt;br /&gt;
* HAM_SUPERCEDE - The call is not executed, and you use your return value, if applicable.&lt;br /&gt;
&lt;br /&gt;
You can use the native '''GetHamReturnStatus()''' to check the current return status of the hook.&lt;br /&gt;
&lt;br /&gt;
==== Return Values ====&lt;br /&gt;
You can get or change the return values for all the hooks available in HamSandwich.  Look in '''ham_const.inc''' for a list of all hooks and their return values.&lt;br /&gt;
&lt;br /&gt;
These natives will get any ''modified'' return values.&lt;br /&gt;
* native GetHamReturnInteger(&amp;amp;output);&lt;br /&gt;
* native GetHamReturnFloat(&amp;amp;Float:output);&lt;br /&gt;
* native GetHamReturnVector(Float:output[3]);&lt;br /&gt;
* native GetHamReturnEntity(&amp;amp;output);&lt;br /&gt;
* native GetHamReturnString(output[], size);&lt;br /&gt;
&lt;br /&gt;
These natives will get the ''original'' return value from the function.&lt;br /&gt;
* native GetOrigHamReturnInteger(&amp;amp;output);&lt;br /&gt;
* native GetOrigHamReturnFloat(&amp;amp;Float:output);&lt;br /&gt;
* native GetOrigHamReturnVector(Float:output[3]);&lt;br /&gt;
* native GetOrigHamReturnCbase(&amp;amp;output);&lt;br /&gt;
* native GetOrigHamReturnString(output[], size);&lt;br /&gt;
&lt;br /&gt;
These natives will change the return value to whatever you please.&lt;br /&gt;
* native SetHamReturnInteger(value);&lt;br /&gt;
* native SetHamReturnFloat(Float:value);&lt;br /&gt;
* native SetHamReturnVector(const Float:value[3]);&lt;br /&gt;
* native SetHamReturnEntity(value);&lt;br /&gt;
* native SetHamReturnString(const value[]);&lt;br /&gt;
&lt;br /&gt;
==== Changing Hook Parameters ====&lt;br /&gt;
One feature available in HamSandwich that is not available in FakeMeta is the ability to change all parameters on the fly for each hook.&lt;br /&gt;
&lt;br /&gt;
This means that, for example, if you wanted to make a plugin that halved all damage players take, you would do something like this:&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;player_hurt&amp;quot;, &amp;quot;player&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 public player_hurt(this, inflictor, attacker, Float:damage, damagebits)&lt;br /&gt;
 {&lt;br /&gt;
   SetHamParamFloat(4, damage / 2.0);&lt;br /&gt;
   return HAM_HANDLED;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
All hooks after the one you change them in will see the modified values.  Hooks are executed in the order in which they are registered.&lt;br /&gt;
&lt;br /&gt;
All available parameter changing natives are:&lt;br /&gt;
&lt;br /&gt;
* native SetHamParamInteger(which, value);&lt;br /&gt;
* native SetHamParamFloat(which, Float:value);&lt;br /&gt;
* native SetHamParamVector(which, const Float:value[3]);&lt;br /&gt;
* native SetHamParamEntity(which, value);&lt;br /&gt;
* native SetHamParamString(which, const output[]);&lt;br /&gt;
* native SetHamParamTraceResult(which, tr_handle);&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4506</id>
		<title>HamSandwich General Usage (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4506"/>
		<updated>2007-05-10T18:32:55Z</updated>

		<summary type="html">&lt;p&gt;Sawce: /* Hooking Functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Ham Sandwich ==&lt;br /&gt;
Ham Sandwich is a module that provides additional hooking and function calling capabilities to [[AMX Mod X]].  It is scheduled to be included with the 1.8 branch of AMX Mod X.&lt;br /&gt;
&lt;br /&gt;
Instead of hooking and executing Half-Life engine calls, like the modules FakeMeta and Engine do, this hooks and executes virtual function calls.&lt;br /&gt;
&lt;br /&gt;
=== What is a virtual function? ===&lt;br /&gt;
A virtual function is a member function of a class in C++.  In the case of Ham Sandwich, the virtual function would be a member function of a game entity.  The virtual functions deal with various events in game, such as damage, and using entities.&lt;br /&gt;
&lt;br /&gt;
Unlike normal member functions, virtual functions can be changed by class derivatives.  For example, a typical hierarchy of entities in Half-Life game dlls look something like this:&lt;br /&gt;
&lt;br /&gt;
 CBaseEntity&lt;br /&gt;
    CBaseAnimating&lt;br /&gt;
       CBaseMonster&lt;br /&gt;
          CZombie&lt;br /&gt;
          CHeadCrab&lt;br /&gt;
          CBarnacle&lt;br /&gt;
          CBasePlayer&lt;br /&gt;
             CBot&lt;br /&gt;
&lt;br /&gt;
Now for example, if CBaseEntity has the virtual function called &amp;quot;FunctionA&amp;quot;, and that function does nothing.  But, CBarnacle also declares the function &amp;quot;FunctionA&amp;quot;, and instead of doing nothing it causes the barnacle to die.&lt;br /&gt;
&lt;br /&gt;
If something like this were to be executed:&lt;br /&gt;
 CBaseEntity *ent=GET_PRIVATE(entity);&lt;br /&gt;
 ent-&amp;gt;FunctionA();&lt;br /&gt;
&lt;br /&gt;
And the entity were a barnacle, the barnacle would die.  If the entity was a zombie, nothing would happen.&lt;br /&gt;
&lt;br /&gt;
=== What are some limitations? ===&lt;br /&gt;
&lt;br /&gt;
Dealing with virtual functions have a couple minor drawbacks.&lt;br /&gt;
==== Custom Entities ====&lt;br /&gt;
Hooking virtual functions, such as TakeDamage, that get called on custom entities is a little bit awkward.&lt;br /&gt;
&lt;br /&gt;
Because of the way where classes derive, and they get their own virtual table for each class, the type of class that the game dll allocates will be whatever gets hooked for a particular hook.&lt;br /&gt;
&lt;br /&gt;
For example, say you have a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 new myStr;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   myStr = engfunc( EngFunc_AllocString, &amp;quot;info_target&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   register_clcmd( &amp;quot;make_entity&amp;quot;, &amp;quot;cmdMakeEntity&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;damageHook&amp;quot;, &amp;quot;MyEntityClass&amp;quot;); // Error!&lt;br /&gt;
 }&lt;br /&gt;
 public cmdMakeEntity( id )&lt;br /&gt;
 {&lt;br /&gt;
   new ent = engfunc( EngFunc_CreateEntity, myStr );&lt;br /&gt;
   set_pev( ent, pev_classname, &amp;quot;MyEntityClass&amp;quot; );&lt;br /&gt;
   // ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
That will not work, because the class &amp;quot;MyEntityClass&amp;quot; is not native to the gamedll.  Instead, you would need to hook TakeDamage for &amp;quot;info_target&amp;quot;, and do some form of parsing on the entities that get passed to it (such as checking classname), if you want to deal with custom entity hooking.&lt;br /&gt;
&lt;br /&gt;
==== End of Chain Derivatives ====&lt;br /&gt;
The normal way virtual functions get called is by a virtual table that resides somewhere in the class.  A magical index is assigned to each function, and then it looks up the function pointer inside of the virtual table, and executes the required function.&lt;br /&gt;
&lt;br /&gt;
However, compilers are smart enough to optimize away the virtual function lookup if it knows two things about a call:&lt;br /&gt;
* The exact class type of the entity.&lt;br /&gt;
* That the entity is not derived any further.&lt;br /&gt;
&lt;br /&gt;
An example would be using the hierarchy shown earlier.  If, inside of CBot::TakeDamage a call to the virtual function CBot::Killed is made, most compilers will optimize the virtual function lookup out, so that CBot::TakeDamage would then directly call CBot::Killed.  This means that the hook would never be called.&lt;br /&gt;
&lt;br /&gt;
Fortunately, these instances are kind of rare.&lt;br /&gt;
&lt;br /&gt;
=== Supported Mods ===&lt;br /&gt;
==== Mostly Supported ====&lt;br /&gt;
These mods have a very large list of functions that are usable in the module. &lt;br /&gt;
* Counter-Strike 1.6&lt;br /&gt;
* Condition Zero&lt;br /&gt;
* Day of Defeat&lt;br /&gt;
* Team Fortress Classic&lt;br /&gt;
* The Specialists&lt;br /&gt;
* Natural-Selection&lt;br /&gt;
&lt;br /&gt;
==== Weakly Supported ====&lt;br /&gt;
Because these mods do not contain a Linux binary, they are much harder to disassemble.  There is only plans for disassembling two functions for each (TakeDamage and Use).&lt;br /&gt;
* Sven-Coop&lt;br /&gt;
* Earth's Special Forces&lt;br /&gt;
&lt;br /&gt;
=== Hooking Functions ===&lt;br /&gt;
The big feature for Ham Sandwich is the ability to hook virtual functions.&lt;br /&gt;
&lt;br /&gt;
==== Creating the Hook ====&lt;br /&gt;
Creating a hook is a lot like creating a hook in Fakemeta.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;player_hurt&amp;quot;, &amp;quot;player&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public player_hurt(this, inflictor, attacker, Float:damage, damagebits)&lt;br /&gt;
 {&lt;br /&gt;
   // Stuff...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This creates a basic hook which is called any time a player takes damage.  Look in '''ham_const.inc''' for forward parameters for each hook.&lt;br /&gt;
&lt;br /&gt;
==== Blocking the Hook ====&lt;br /&gt;
Like Fakemeta and Engine, it is possible to stop a function from being called.  This is called '''superceding'''.&lt;br /&gt;
&lt;br /&gt;
Blocking in HamSandwich is identical to how it is accomplished in Fakemeta.  In each hook, you return one of four special values:&lt;br /&gt;
&lt;br /&gt;
* HAM_IGNORED - Nothing happened, the call continues.&lt;br /&gt;
* HAM_HANDLED - You did something, but the call continues.&lt;br /&gt;
* HAM_OVERRIDE - The call will still be executed, but instead you will change the return value.&lt;br /&gt;
* HAM_SUPERCEDE - The call is not executed, and you use your return value, if applicable.&lt;br /&gt;
&lt;br /&gt;
You can use the native '''GetHamReturnStatus()''' to check the current return status of the hook.&lt;br /&gt;
&lt;br /&gt;
==== Return Values ====&lt;br /&gt;
You can get or change the return values for all the hooks available in HamSandwich.  Look in '''ham_const.inc''' for a list of all hooks and their return values.&lt;br /&gt;
&lt;br /&gt;
These natives will get any ''modified'' return values.&lt;br /&gt;
* native GetHamReturnInteger(&amp;amp;output);&lt;br /&gt;
* native GetHamReturnFloat(&amp;amp;Float:output);&lt;br /&gt;
* native GetHamReturnVector(Float:output[3]);&lt;br /&gt;
* native GetHamReturnEntity(&amp;amp;output);&lt;br /&gt;
* native GetHamReturnString(output[], size);&lt;br /&gt;
&lt;br /&gt;
These natives will get the ''original'' return value from the function.&lt;br /&gt;
* native GetOrigHamReturnInteger(&amp;amp;output);&lt;br /&gt;
* native GetOrigHamReturnFloat(&amp;amp;Float:output);&lt;br /&gt;
* native GetOrigHamReturnVector(Float:output[3]);&lt;br /&gt;
* native GetOrigHamReturnCbase(&amp;amp;output);&lt;br /&gt;
* native GetOrigHamReturnString(output[], size);&lt;br /&gt;
&lt;br /&gt;
These natives will change the return value to whatever you please.&lt;br /&gt;
* native SetHamReturnInteger(value);&lt;br /&gt;
* native SetHamReturnFloat(Float:value);&lt;br /&gt;
* native SetHamReturnVector(const Float:value[3]);&lt;br /&gt;
* native SetHamReturnEntity(value);&lt;br /&gt;
* native SetHamReturnString(const value[]);&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4505</id>
		<title>HamSandwich General Usage (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4505"/>
		<updated>2007-05-10T18:28:40Z</updated>

		<summary type="html">&lt;p&gt;Sawce: /* Hooking Functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Ham Sandwich ==&lt;br /&gt;
Ham Sandwich is a module that provides additional hooking and function calling capabilities to [[AMX Mod X]].  It is scheduled to be included with the 1.8 branch of AMX Mod X.&lt;br /&gt;
&lt;br /&gt;
Instead of hooking and executing Half-Life engine calls, like the modules FakeMeta and Engine do, this hooks and executes virtual function calls.&lt;br /&gt;
&lt;br /&gt;
=== What is a virtual function? ===&lt;br /&gt;
A virtual function is a member function of a class in C++.  In the case of Ham Sandwich, the virtual function would be a member function of a game entity.  The virtual functions deal with various events in game, such as damage, and using entities.&lt;br /&gt;
&lt;br /&gt;
Unlike normal member functions, virtual functions can be changed by class derivatives.  For example, a typical hierarchy of entities in Half-Life game dlls look something like this:&lt;br /&gt;
&lt;br /&gt;
 CBaseEntity&lt;br /&gt;
    CBaseAnimating&lt;br /&gt;
       CBaseMonster&lt;br /&gt;
          CZombie&lt;br /&gt;
          CHeadCrab&lt;br /&gt;
          CBarnacle&lt;br /&gt;
          CBasePlayer&lt;br /&gt;
             CBot&lt;br /&gt;
&lt;br /&gt;
Now for example, if CBaseEntity has the virtual function called &amp;quot;FunctionA&amp;quot;, and that function does nothing.  But, CBarnacle also declares the function &amp;quot;FunctionA&amp;quot;, and instead of doing nothing it causes the barnacle to die.&lt;br /&gt;
&lt;br /&gt;
If something like this were to be executed:&lt;br /&gt;
 CBaseEntity *ent=GET_PRIVATE(entity);&lt;br /&gt;
 ent-&amp;gt;FunctionA();&lt;br /&gt;
&lt;br /&gt;
And the entity were a barnacle, the barnacle would die.  If the entity was a zombie, nothing would happen.&lt;br /&gt;
&lt;br /&gt;
=== What are some limitations? ===&lt;br /&gt;
&lt;br /&gt;
Dealing with virtual functions have a couple minor drawbacks.&lt;br /&gt;
==== Custom Entities ====&lt;br /&gt;
Hooking virtual functions, such as TakeDamage, that get called on custom entities is a little bit awkward.&lt;br /&gt;
&lt;br /&gt;
Because of the way where classes derive, and they get their own virtual table for each class, the type of class that the game dll allocates will be whatever gets hooked for a particular hook.&lt;br /&gt;
&lt;br /&gt;
For example, say you have a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 new myStr;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   myStr = engfunc( EngFunc_AllocString, &amp;quot;info_target&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   register_clcmd( &amp;quot;make_entity&amp;quot;, &amp;quot;cmdMakeEntity&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;damageHook&amp;quot;, &amp;quot;MyEntityClass&amp;quot;); // Error!&lt;br /&gt;
 }&lt;br /&gt;
 public cmdMakeEntity( id )&lt;br /&gt;
 {&lt;br /&gt;
   new ent = engfunc( EngFunc_CreateEntity, myStr );&lt;br /&gt;
   set_pev( ent, pev_classname, &amp;quot;MyEntityClass&amp;quot; );&lt;br /&gt;
   // ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
That will not work, because the class &amp;quot;MyEntityClass&amp;quot; is not native to the gamedll.  Instead, you would need to hook TakeDamage for &amp;quot;info_target&amp;quot;, and do some form of parsing on the entities that get passed to it (such as checking classname), if you want to deal with custom entity hooking.&lt;br /&gt;
&lt;br /&gt;
==== End of Chain Derivatives ====&lt;br /&gt;
The normal way virtual functions get called is by a virtual table that resides somewhere in the class.  A magical index is assigned to each function, and then it looks up the function pointer inside of the virtual table, and executes the required function.&lt;br /&gt;
&lt;br /&gt;
However, compilers are smart enough to optimize away the virtual function lookup if it knows two things about a call:&lt;br /&gt;
* The exact class type of the entity.&lt;br /&gt;
* That the entity is not derived any further.&lt;br /&gt;
&lt;br /&gt;
An example would be using the hierarchy shown earlier.  If, inside of CBot::TakeDamage a call to the virtual function CBot::Killed is made, most compilers will optimize the virtual function lookup out, so that CBot::TakeDamage would then directly call CBot::Killed.  This means that the hook would never be called.&lt;br /&gt;
&lt;br /&gt;
Fortunately, these instances are kind of rare.&lt;br /&gt;
&lt;br /&gt;
=== Supported Mods ===&lt;br /&gt;
==== Mostly Supported ====&lt;br /&gt;
These mods have a very large list of functions that are usable in the module. &lt;br /&gt;
* Counter-Strike 1.6&lt;br /&gt;
* Condition Zero&lt;br /&gt;
* Day of Defeat&lt;br /&gt;
* Team Fortress Classic&lt;br /&gt;
* The Specialists&lt;br /&gt;
* Natural-Selection&lt;br /&gt;
&lt;br /&gt;
==== Weakly Supported ====&lt;br /&gt;
Because these mods do not contain a Linux binary, they are much harder to disassemble.  There is only plans for disassembling two functions for each (TakeDamage and Use).&lt;br /&gt;
* Sven-Coop&lt;br /&gt;
* Earth's Special Forces&lt;br /&gt;
&lt;br /&gt;
=== Hooking Functions ===&lt;br /&gt;
The big feature for Ham Sandwich is the ability to hook virtual functions.&lt;br /&gt;
&lt;br /&gt;
==== Creating the Hook ====&lt;br /&gt;
Creating a hook is a lot like creating a hook in Fakemeta.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;player_hurt&amp;quot;, &amp;quot;player&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public player_hurt(this, inflictor, attacker, Float:damage, damagebits)&lt;br /&gt;
 {&lt;br /&gt;
   // Stuff...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This creates a basic hook which is called any time a player takes damage.  Look in '''ham_const.inc''' for forward parameters for each hook.&lt;br /&gt;
&lt;br /&gt;
==== Blocking the Hook ====&lt;br /&gt;
Like Fakemeta and Engine, it is possible to stop a function from being called.  This is called '''superceding'''.&lt;br /&gt;
&lt;br /&gt;
Blocking in HamSandwich is identical to how it is accomplished in Fakemeta.  In each hook, you return one of four special values:&lt;br /&gt;
&lt;br /&gt;
* HAM_IGNORED - Nothing happened, the call continues.&lt;br /&gt;
* HAM_HANDLED - You did something, but the call continues.&lt;br /&gt;
* HAM_OVERRIDE - The call will still be executed, but instead you will change the return value.&lt;br /&gt;
* HAM_SUPERCEDE - The call is not executed, and you use your return value, if applicable.&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4504</id>
		<title>HamSandwich General Usage (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4504"/>
		<updated>2007-05-10T18:23:34Z</updated>

		<summary type="html">&lt;p&gt;Sawce: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Ham Sandwich ==&lt;br /&gt;
Ham Sandwich is a module that provides additional hooking and function calling capabilities to [[AMX Mod X]].  It is scheduled to be included with the 1.8 branch of AMX Mod X.&lt;br /&gt;
&lt;br /&gt;
Instead of hooking and executing Half-Life engine calls, like the modules FakeMeta and Engine do, this hooks and executes virtual function calls.&lt;br /&gt;
&lt;br /&gt;
=== What is a virtual function? ===&lt;br /&gt;
A virtual function is a member function of a class in C++.  In the case of Ham Sandwich, the virtual function would be a member function of a game entity.  The virtual functions deal with various events in game, such as damage, and using entities.&lt;br /&gt;
&lt;br /&gt;
Unlike normal member functions, virtual functions can be changed by class derivatives.  For example, a typical hierarchy of entities in Half-Life game dlls look something like this:&lt;br /&gt;
&lt;br /&gt;
 CBaseEntity&lt;br /&gt;
    CBaseAnimating&lt;br /&gt;
       CBaseMonster&lt;br /&gt;
          CZombie&lt;br /&gt;
          CHeadCrab&lt;br /&gt;
          CBarnacle&lt;br /&gt;
          CBasePlayer&lt;br /&gt;
             CBot&lt;br /&gt;
&lt;br /&gt;
Now for example, if CBaseEntity has the virtual function called &amp;quot;FunctionA&amp;quot;, and that function does nothing.  But, CBarnacle also declares the function &amp;quot;FunctionA&amp;quot;, and instead of doing nothing it causes the barnacle to die.&lt;br /&gt;
&lt;br /&gt;
If something like this were to be executed:&lt;br /&gt;
 CBaseEntity *ent=GET_PRIVATE(entity);&lt;br /&gt;
 ent-&amp;gt;FunctionA();&lt;br /&gt;
&lt;br /&gt;
And the entity were a barnacle, the barnacle would die.  If the entity was a zombie, nothing would happen.&lt;br /&gt;
&lt;br /&gt;
=== What are some limitations? ===&lt;br /&gt;
&lt;br /&gt;
Dealing with virtual functions have a couple minor drawbacks.&lt;br /&gt;
==== Custom Entities ====&lt;br /&gt;
Hooking virtual functions, such as TakeDamage, that get called on custom entities is a little bit awkward.&lt;br /&gt;
&lt;br /&gt;
Because of the way where classes derive, and they get their own virtual table for each class, the type of class that the game dll allocates will be whatever gets hooked for a particular hook.&lt;br /&gt;
&lt;br /&gt;
For example, say you have a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 new myStr;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   myStr = engfunc( EngFunc_AllocString, &amp;quot;info_target&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   register_clcmd( &amp;quot;make_entity&amp;quot;, &amp;quot;cmdMakeEntity&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;damageHook&amp;quot;, &amp;quot;MyEntityClass&amp;quot;); // Error!&lt;br /&gt;
 }&lt;br /&gt;
 public cmdMakeEntity( id )&lt;br /&gt;
 {&lt;br /&gt;
   new ent = engfunc( EngFunc_CreateEntity, myStr );&lt;br /&gt;
   set_pev( ent, pev_classname, &amp;quot;MyEntityClass&amp;quot; );&lt;br /&gt;
   // ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
That will not work, because the class &amp;quot;MyEntityClass&amp;quot; is not native to the gamedll.  Instead, you would need to hook TakeDamage for &amp;quot;info_target&amp;quot;, and do some form of parsing on the entities that get passed to it (such as checking classname), if you want to deal with custom entity hooking.&lt;br /&gt;
&lt;br /&gt;
==== End of Chain Derivatives ====&lt;br /&gt;
The normal way virtual functions get called is by a virtual table that resides somewhere in the class.  A magical index is assigned to each function, and then it looks up the function pointer inside of the virtual table, and executes the required function.&lt;br /&gt;
&lt;br /&gt;
However, compilers are smart enough to optimize away the virtual function lookup if it knows two things about a call:&lt;br /&gt;
* The exact class type of the entity.&lt;br /&gt;
* That the entity is not derived any further.&lt;br /&gt;
&lt;br /&gt;
An example would be using the hierarchy shown earlier.  If, inside of CBot::TakeDamage a call to the virtual function CBot::Killed is made, most compilers will optimize the virtual function lookup out, so that CBot::TakeDamage would then directly call CBot::Killed.  This means that the hook would never be called.&lt;br /&gt;
&lt;br /&gt;
Fortunately, these instances are kind of rare.&lt;br /&gt;
&lt;br /&gt;
=== Supported Mods ===&lt;br /&gt;
==== Mostly Supported ====&lt;br /&gt;
These mods have a very large list of functions that are usable in the module. &lt;br /&gt;
* Counter-Strike 1.6&lt;br /&gt;
* Condition Zero&lt;br /&gt;
* Day of Defeat&lt;br /&gt;
* Team Fortress Classic&lt;br /&gt;
* The Specialists&lt;br /&gt;
* Natural-Selection&lt;br /&gt;
&lt;br /&gt;
==== Weakly Supported ====&lt;br /&gt;
Because these mods do not contain a Linux binary, they are much harder to disassemble.  There is only plans for disassembling two functions for each (TakeDamage and Use).&lt;br /&gt;
* Sven-Coop&lt;br /&gt;
* Earth's Special Forces&lt;br /&gt;
&lt;br /&gt;
=== Hooking Functions ===&lt;br /&gt;
The big feature for Ham Sandwich is the ability to hook virtual functions.&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4502</id>
		<title>HamSandwich General Usage (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4502"/>
		<updated>2007-05-10T18:15:07Z</updated>

		<summary type="html">&lt;p&gt;Sawce: HamSandwich General Usage (AMX Madsfod X) moved to HamSandwich General Usage (AMX Mod X): lol typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Ham Sandwich ==&lt;br /&gt;
Ham Sandwich is a module that provides additional hooking and function calling capabilities to [[AMX Mod X]].&lt;br /&gt;
&lt;br /&gt;
Instead of hooking and executing Half-Life engine calls, like the modules FakeMeta and Engine do, this hooks and executes virtual function calls.&lt;br /&gt;
&lt;br /&gt;
=== What is a virtual function? ===&lt;br /&gt;
A virtual function is a member function of a class in C++.  In the case of Ham Sandwich, the virtual function would be a member function of a game entity.  The virtual functions deal with various events in game, such as damage, and using entities.&lt;br /&gt;
&lt;br /&gt;
Unlike normal member functions, virtual functions can be changed by class derivatives.  For example, a typical hierarchy of entities in Half-Life game dlls look something like this:&lt;br /&gt;
&lt;br /&gt;
 CBaseEntity&lt;br /&gt;
    CBaseAnimating&lt;br /&gt;
       CBaseMonster&lt;br /&gt;
          CZombie&lt;br /&gt;
          CHeadCrab&lt;br /&gt;
          CBarnacle&lt;br /&gt;
          CBasePlayer&lt;br /&gt;
             CBot&lt;br /&gt;
&lt;br /&gt;
Now for example, if CBaseEntity has the virtual function called &amp;quot;FunctionA&amp;quot;, and that function does nothing.  But, CBarnacle also declares the function &amp;quot;FunctionA&amp;quot;, and instead of doing nothing it causes the barnacle to die.&lt;br /&gt;
&lt;br /&gt;
If something like this were to be executed:&lt;br /&gt;
 CBaseEntity *ent=GET_PRIVATE(entity);&lt;br /&gt;
 ent-&amp;gt;FunctionA();&lt;br /&gt;
&lt;br /&gt;
And the entity were a barnacle, the barnacle would die.  If the entity was a zombie, nothing would happen.&lt;br /&gt;
&lt;br /&gt;
=== What are some limitations? ===&lt;br /&gt;
&lt;br /&gt;
Dealing with virtual functions have a couple minor drawbacks.&lt;br /&gt;
==== Custom Entities ====&lt;br /&gt;
Hooking virtual functions, such as TakeDamage, that get called on custom entities is a little bit awkward.&lt;br /&gt;
&lt;br /&gt;
Because of the way where classes derive, and they get their own virtual table for each class, the type of class that the game dll allocates will be whatever gets hooked for a particular hook.&lt;br /&gt;
&lt;br /&gt;
For example, say you have a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 new myStr;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   myStr = engfunc( EngFunc_AllocString, &amp;quot;info_target&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   register_clcmd( &amp;quot;make_entity&amp;quot;, &amp;quot;cmdMakeEntity&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;damageHook&amp;quot;, &amp;quot;MyEntityClass&amp;quot;); // Error!&lt;br /&gt;
 }&lt;br /&gt;
 public cmdMakeEntity( id )&lt;br /&gt;
 {&lt;br /&gt;
   new ent = engfunc( EngFunc_CreateEntity, myStr );&lt;br /&gt;
   set_pev( ent, pev_classname, &amp;quot;MyEntityClass&amp;quot; );&lt;br /&gt;
   // ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
That will not work, because the class &amp;quot;MyEntityClass&amp;quot; is not native to the gamedll.  Instead, you would need to hook TakeDamage for &amp;quot;info_target&amp;quot;, and do some form of parsing on the entities that get passed to it (such as checking classname), if you want to deal with custom entity hooking.&lt;br /&gt;
&lt;br /&gt;
==== End of Chain Derivatives ====&lt;br /&gt;
The normal way virtual functions get called is by a virtual table that resides somewhere in the class.  A magical index is assigned to each function, and then it looks up the function pointer inside of the virtual table, and executes the required function.&lt;br /&gt;
&lt;br /&gt;
However, compilers are smart enough to optimize away the virtual function lookup if it knows two things about a call:&lt;br /&gt;
* The exact class type of the entity.&lt;br /&gt;
* That the entity is not derived any further.&lt;br /&gt;
&lt;br /&gt;
An example would be using the hierarchy shown earlier.  If, inside of CBot::TakeDamage a call to the virtual function CBot::Killed is made, most compilers will optimize the virtual function lookup out, so that CBot::TakeDamage would then directly call CBot::Killed.  This means that the hook would never be called.&lt;br /&gt;
&lt;br /&gt;
Fortunately, these instances are kind of rare.&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Madsfod_X)&amp;diff=4503</id>
		<title>HamSandwich General Usage (AMX Madsfod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Madsfod_X)&amp;diff=4503"/>
		<updated>2007-05-10T18:15:07Z</updated>

		<summary type="html">&lt;p&gt;Sawce: HamSandwich General Usage (AMX Madsfod X) moved to HamSandwich General Usage (AMX Mod X): lol typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[HamSandwich General Usage (AMX Mod X)]]&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4501</id>
		<title>HamSandwich General Usage (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4501"/>
		<updated>2007-05-10T18:10:52Z</updated>

		<summary type="html">&lt;p&gt;Sawce: /* What are some limitations? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Ham Sandwich ==&lt;br /&gt;
Ham Sandwich is a module that provides additional hooking and function calling capabilities to [[AMX Mod X]].&lt;br /&gt;
&lt;br /&gt;
Instead of hooking and executing Half-Life engine calls, like the modules FakeMeta and Engine do, this hooks and executes virtual function calls.&lt;br /&gt;
&lt;br /&gt;
=== What is a virtual function? ===&lt;br /&gt;
A virtual function is a member function of a class in C++.  In the case of Ham Sandwich, the virtual function would be a member function of a game entity.  The virtual functions deal with various events in game, such as damage, and using entities.&lt;br /&gt;
&lt;br /&gt;
Unlike normal member functions, virtual functions can be changed by class derivatives.  For example, a typical hierarchy of entities in Half-Life game dlls look something like this:&lt;br /&gt;
&lt;br /&gt;
 CBaseEntity&lt;br /&gt;
    CBaseAnimating&lt;br /&gt;
       CBaseMonster&lt;br /&gt;
          CZombie&lt;br /&gt;
          CHeadCrab&lt;br /&gt;
          CBarnacle&lt;br /&gt;
          CBasePlayer&lt;br /&gt;
             CBot&lt;br /&gt;
&lt;br /&gt;
Now for example, if CBaseEntity has the virtual function called &amp;quot;FunctionA&amp;quot;, and that function does nothing.  But, CBarnacle also declares the function &amp;quot;FunctionA&amp;quot;, and instead of doing nothing it causes the barnacle to die.&lt;br /&gt;
&lt;br /&gt;
If something like this were to be executed:&lt;br /&gt;
 CBaseEntity *ent=GET_PRIVATE(entity);&lt;br /&gt;
 ent-&amp;gt;FunctionA();&lt;br /&gt;
&lt;br /&gt;
And the entity were a barnacle, the barnacle would die.  If the entity was a zombie, nothing would happen.&lt;br /&gt;
&lt;br /&gt;
=== What are some limitations? ===&lt;br /&gt;
&lt;br /&gt;
Dealing with virtual functions have a couple minor drawbacks.&lt;br /&gt;
==== Custom Entities ====&lt;br /&gt;
Hooking virtual functions, such as TakeDamage, that get called on custom entities is a little bit awkward.&lt;br /&gt;
&lt;br /&gt;
Because of the way where classes derive, and they get their own virtual table for each class, the type of class that the game dll allocates will be whatever gets hooked for a particular hook.&lt;br /&gt;
&lt;br /&gt;
For example, say you have a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 new myStr;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
   myStr = engfunc( EngFunc_AllocString, &amp;quot;info_target&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   register_clcmd( &amp;quot;make_entity&amp;quot;, &amp;quot;cmdMakeEntity&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
   RegisterHam(Ham_TakeDamage, &amp;quot;damageHook&amp;quot;, &amp;quot;MyEntityClass&amp;quot;); // Error!&lt;br /&gt;
 }&lt;br /&gt;
 public cmdMakeEntity( id )&lt;br /&gt;
 {&lt;br /&gt;
   new ent = engfunc( EngFunc_CreateEntity, myStr );&lt;br /&gt;
   set_pev( ent, pev_classname, &amp;quot;MyEntityClass&amp;quot; );&lt;br /&gt;
   // ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
That will not work, because the class &amp;quot;MyEntityClass&amp;quot; is not native to the gamedll.  Instead, you would need to hook TakeDamage for &amp;quot;info_target&amp;quot;, and do some form of parsing on the entities that get passed to it (such as checking classname), if you want to deal with custom entity hooking.&lt;br /&gt;
&lt;br /&gt;
==== End of Chain Derivatives ====&lt;br /&gt;
The normal way virtual functions get called is by a virtual table that resides somewhere in the class.  A magical index is assigned to each function, and then it looks up the function pointer inside of the virtual table, and executes the required function.&lt;br /&gt;
&lt;br /&gt;
However, compilers are smart enough to optimize away the virtual function lookup if it knows two things about a call:&lt;br /&gt;
* The exact class type of the entity.&lt;br /&gt;
* That the entity is not derived any further.&lt;br /&gt;
&lt;br /&gt;
An example would be using the hierarchy shown earlier.  If, inside of CBot::TakeDamage a call to the virtual function CBot::Killed is made, most compilers will optimize the virtual function lookup out, so that CBot::TakeDamage would then directly call CBot::Killed.  This means that the hook would never be called.&lt;br /&gt;
&lt;br /&gt;
Fortunately, these instances are kind of rare.&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4500</id>
		<title>HamSandwich General Usage (AMX Mod X)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=HamSandwich_General_Usage_(AMX_Mod_X)&amp;diff=4500"/>
		<updated>2007-05-10T18:01:43Z</updated>

		<summary type="html">&lt;p&gt;Sawce: New page: == About Ham Sandwich == Ham Sandwich is a module that provides additional hooking and function calling capabilities to AMX Mod X.  Instead of hooking and executing Half-Life engine ca...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About Ham Sandwich ==&lt;br /&gt;
Ham Sandwich is a module that provides additional hooking and function calling capabilities to [[AMX Mod X]].&lt;br /&gt;
&lt;br /&gt;
Instead of hooking and executing Half-Life engine calls, like the modules FakeMeta and Engine do, this hooks and executes virtual function calls.&lt;br /&gt;
&lt;br /&gt;
=== What is a virtual function? ===&lt;br /&gt;
A virtual function is a member function of a class in C++.  In the case of Ham Sandwich, the virtual function would be a member function of a game entity.  The virtual functions deal with various events in game, such as damage, and using entities.&lt;br /&gt;
&lt;br /&gt;
Unlike normal member functions, virtual functions can be changed by class derivatives.  For example, a typical hierarchy of entities in Half-Life game dlls look something like this:&lt;br /&gt;
&lt;br /&gt;
 CBaseEntity&lt;br /&gt;
    CBaseAnimating&lt;br /&gt;
       CBaseMonster&lt;br /&gt;
          CZombie&lt;br /&gt;
          CHeadCrab&lt;br /&gt;
          CBarnacle&lt;br /&gt;
          CBasePlayer&lt;br /&gt;
             CBot&lt;br /&gt;
&lt;br /&gt;
Now for example, if CBaseEntity has the virtual function called &amp;quot;FunctionA&amp;quot;, and that function does nothing.  But, CBarnacle also declares the function &amp;quot;FunctionA&amp;quot;, and instead of doing nothing it causes the barnacle to die.&lt;br /&gt;
&lt;br /&gt;
If something like this were to be executed:&lt;br /&gt;
 CBaseEntity *ent=GET_PRIVATE(entity);&lt;br /&gt;
 ent-&amp;gt;FunctionA();&lt;br /&gt;
&lt;br /&gt;
And the entity were a barnacle, the barnacle would die.  If the entity was a zombie, nothing would happen.&lt;br /&gt;
&lt;br /&gt;
=== What are some limitations? ===&lt;br /&gt;
==== Custom Entities ====&lt;br /&gt;
Hooking virtual functions, such as TakeDamage, that get called on custom entities is a little bit awkward.&lt;br /&gt;
&lt;br /&gt;
Because of the way where classes derive, and they get their own virtual table for each class, the type of class that the game dll allocates will be whatever gets hooked for a particular hook.&lt;br /&gt;
&lt;br /&gt;
For example, say you have a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;amxmodx&amp;gt;&lt;br /&gt;
 #include &amp;lt;fakemeta&amp;gt;&lt;br /&gt;
 #include &amp;lt;hamsandwich&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 new myStr;&lt;br /&gt;
 public plugin_init()&lt;br /&gt;
 {&lt;br /&gt;
 &lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Signature_Scanning&amp;diff=3934</id>
		<title>Signature Scanning</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Signature_Scanning&amp;diff=3934"/>
		<updated>2007-02-19T21:01:41Z</updated>

		<summary type="html">&lt;p&gt;Sawce: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Documentation (SourceMM)]]&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This article demonstrates a technique developed by Lance Vorgin known as &amp;quot;Signature Scanning&amp;quot;, or sigscanning for short. &lt;br /&gt;
&lt;br /&gt;
== What is Sigscanning? ==&lt;br /&gt;
&lt;br /&gt;
Sigscanning is a multi-step process involving extracting function signatures from a binary and then scanning for them at run-time to locate an otherwise-hidden function. A signature for a function is a set of bytes unique to a function. These bytes are the instructions a program uses to operate. These sets of bytes are what make up functions (or subroutines as they are called in Assembly). When we have enough of these bytes to form a unique set, we can then match them again to the function in memory.&lt;br /&gt;
&lt;br /&gt;
Why is this useful for plugins? Each time Valve releases an update for their mods, they may change classes such as CBaseEntity used by many plugin coders to interact with a player’s entity. Due to the fact that we do not have the appropriate class headers for each of these changes, we may be using virtual functions that now exist at different addresses. This would cause a crash at run-time. To avoid this, the following solutions are available:&lt;br /&gt;
*rely on manual offsets into the class' vtable&lt;br /&gt;
*modify the provided class headers by inserting dummy virtual functions to fix the offsets&lt;br /&gt;
*sigscanning&lt;br /&gt;
&lt;br /&gt;
Each have their pros and cons, but it turns out that although sigscanning is the most tedious out of the three, it is the most reliable. The first two choices are typically broken by updates.&lt;br /&gt;
&lt;br /&gt;
== Assembly and Memory ==&lt;br /&gt;
&lt;br /&gt;
To understand all of this, one must first understand how the code of a C++ program is compiled into a binary file.&lt;br /&gt;
&lt;br /&gt;
When you hit &amp;quot;Build Solution&amp;quot; on your IDE or run a makefile, your compiler does a multitude of operations. First it takes the code and runs it through a preprocessor. The preprocessor takes all the &amp;quot;#&amp;quot; directives (e.g. #define, #include, etc.) and substitutes them with normal C++ code. After the preprocessor has done its job, the code is passed on to the parser. In simplified terms, the parser basically takes C++ code and turns it into Assembly (asm) code. After the parser has parsed the code into Assembly code, the assembler &amp;quot;assembles&amp;quot; the code into mostly machine (byte) code which is put into object files that carry the .obj or .o extension. Then the linker gathers all the object files where it looks for function calls and sets the &amp;quot;links&amp;quot; to them (static linking) as well as external calls to functions outside the scope of the assembled code (dynamic linking) and finally maps any runtime calls (runtime linking). After this, it finally outputs the finished product (a binary file, i.e. an executable or library). When a server loads your plugin, it uses runtime calls to call functions from within your plugin, and likewise your plugin calls functions from the server.&lt;br /&gt;
&lt;br /&gt;
Now where this all comes into play in sigscanning is where you will be taking the server module (.dll or .so file) from memory and scanning it in its machine-code form for those functions that you need. This is done by first disassembling the server module back into Assembly form and finding the instructions that make up that function you want.&lt;br /&gt;
&lt;br /&gt;
Assembly is the &amp;quot;lowest-level&amp;quot; language in programming terms. It is easy to flip-flop between Assembly and machine code because they are basically the same, except Assembly uses something called &amp;quot;Mnemonics&amp;quot; before every instruction. These are the human-readable keywords &amp;lt;i&amp;gt;push&amp;lt;/i&amp;gt;, &amp;lt;i&amp;gt;pop&amp;lt;/i&amp;gt;, &amp;lt;i&amp;gt;mov&amp;lt;/i&amp;gt;, &amp;lt;i&amp;gt;call&amp;lt;/i&amp;gt;, etc. that define what the instruction does. As C++ code is translated into Assembly, you can imagine the very structured syntax of C++ flattened out into primitive simple Assembly instructions. I won’t go into further detail on Assembly due to its complex nature. The best way to learn more about it (which is recommended) is to read one of the reference links provided at the bottom of this writing.&lt;br /&gt;
&lt;br /&gt;
== Before We Go Further ==&lt;br /&gt;
&lt;br /&gt;
Read BAILOPAN’s three DevLogs on sigscanning to gain an understanding of the proceeding sections.&lt;br /&gt;
*&amp;lt;i&amp;gt;Oh, you’ve not hacked yet?&amp;lt;/i&amp;gt; – http://www.sourcemod.net/devlog/?p=55&lt;br /&gt;
*&amp;lt;i&amp;gt;Finding Functions, Part 2&amp;lt;/i&amp;gt; – http://www.sourcemod.net/devlog/?p=56&lt;br /&gt;
*&amp;lt;i&amp;gt;Finding Functions, Part 3&amp;lt;/i&amp;gt; – http://www.sourcemod.net/devlog/?p=57&lt;br /&gt;
&lt;br /&gt;
== Scanning for Signatures at Run-time ==&lt;br /&gt;
&lt;br /&gt;
This is the complete code for a basic sigscanner. All functions and variables are described with comments.&lt;br /&gt;
&lt;br /&gt;
=== sigscan.h ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;#ifndef SIGSCAN_H&lt;br /&gt;
#define SIGSCAN_H&lt;br /&gt;
&lt;br /&gt;
class CSigScan {&lt;br /&gt;
private:&lt;br /&gt;
    /* Private Variables */&lt;br /&gt;
    /* Base Address of the server module in memory */&lt;br /&gt;
    static unsigned char *base_addr;&lt;br /&gt;
    /* The length to the module's ending address */&lt;br /&gt;
    static size_t base_len;&lt;br /&gt;
&lt;br /&gt;
    /* The signature to scan for */&lt;br /&gt;
    unsigned char *sig_str;&lt;br /&gt;
    /* A mask to ignore certain bytes in the signature such as addresses&lt;br /&gt;
       The mask should be as long as all the bytes in the signature string&lt;br /&gt;
       Use '?' to ignore a byte and 'x' to check it&lt;br /&gt;
       Example: &amp;quot;xxx????xx&amp;quot; - The first 3 bytes are checked, then the next 4 are&lt;br /&gt;
       ignored, then the last 2 are checked */&lt;br /&gt;
    char *sig_mask;&lt;br /&gt;
    /* The length of sig_str and sig_mask (not including a terminating null for sig_mask) */&lt;br /&gt;
    size_t sig_len;&lt;br /&gt;
&lt;br /&gt;
    /* Private Functions */&lt;br /&gt;
    void* FindSignature(void);&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    /* Public Variables */&lt;br /&gt;
&lt;br /&gt;
    /* sigscan_dllfunc is a pointer of something that resides inside the gamedll so we can get&lt;br /&gt;
       the base address of it. From a SourceMM plugin, just set this to ismm-&amp;gt;serverFactory(0)&lt;br /&gt;
       in Load(). From a Valve Server Plugin, you must set this to an actual factory returned&lt;br /&gt;
       from gameServerFactory and hope that a SourceMM plugin did not override it. */&lt;br /&gt;
    static void *(*sigscan_dllfunc)(const char *pName, int *pReturnCode);&lt;br /&gt;
&lt;br /&gt;
    /* If the scan was successful or not */&lt;br /&gt;
    char is_set;&lt;br /&gt;
    /* Starting address of the found function */&lt;br /&gt;
    void *sig_addr;&lt;br /&gt;
&lt;br /&gt;
    /* Public Functions */&lt;br /&gt;
    CSigScan(void)sig_str(NULL), sig_mask(NULL), sig_len(0), sig_addr(NULL) {}&lt;br /&gt;
    ~CSigScan(void);&lt;br /&gt;
&lt;br /&gt;
    static bool GetDllMemInfo(void);&lt;br /&gt;
    void Init(unsigned char *sig, char *mask, size_t len);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* Sigscanned member functions are casted to member function pointers of this class&lt;br /&gt;
   and called with member function pointer syntax */&lt;br /&gt;
class EmptyClass { };&lt;br /&gt;
&lt;br /&gt;
void InitSigs(void);&lt;br /&gt;
&lt;br /&gt;
/* Sig Functions */&lt;br /&gt;
class CBaseAnimating;&lt;br /&gt;
void CBaseAnimating_Ignite(CBaseAnimating *cba, float flFlameLifetime);&lt;br /&gt;
&lt;br /&gt;
#endif&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== sigscan.cpp ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#ifdef WIN32&lt;br /&gt;
    #define WIN32_LEAN_AND_MEAN&lt;br /&gt;
    #include &amp;lt;windows.h&amp;gt;&lt;br /&gt;
#else&lt;br /&gt;
    #include &amp;lt;dlfcn.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;sys/stat.h&amp;gt; &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;sigscan.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* There is no ANSI ustrncpy */&lt;br /&gt;
unsigned char* ustrncpy(unsigned char *dest, const unsigned char *src, int len) {&lt;br /&gt;
    while(len--)&lt;br /&gt;
        dest[len] = src[len];&lt;br /&gt;
&lt;br /&gt;
    return dest;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* //////////////////////////////////////&lt;br /&gt;
    CSigScan Class&lt;br /&gt;
    ////////////////////////////////////// */&lt;br /&gt;
unsigned char* CSigScan::base_addr;&lt;br /&gt;
size_t CSigScan::base_len;&lt;br /&gt;
void *(*CSigScan::sigscan_dllfunc)(const char *pName, int *pReturnCode);&lt;br /&gt;
&lt;br /&gt;
/* Initialize the Signature Object */&lt;br /&gt;
void CSigScan::Init(unsigned char *sig, char *mask, size_t len) {&lt;br /&gt;
    is_set = 0;&lt;br /&gt;
&lt;br /&gt;
    sig_len = len;&lt;br /&gt;
    sig_str = new unsigned char[sig_len];&lt;br /&gt;
    ustrncpy(sig_str, sig, sig_len);&lt;br /&gt;
&lt;br /&gt;
    sig_mask = new char[sig_len+1];&lt;br /&gt;
    strncpy(sig_mask, mask, sig_len);&lt;br /&gt;
    sig_mask[sig_len+1] = 0;&lt;br /&gt;
&lt;br /&gt;
    if(!base_addr)&lt;br /&gt;
        return ; // GetDllMemInfo() Failed&lt;br /&gt;
&lt;br /&gt;
    if((sig_addr = FindSignature()) == NULL)&lt;br /&gt;
        return ; // FindSignature() Failed&lt;br /&gt;
&lt;br /&gt;
    is_set = 1;&lt;br /&gt;
    // SigScan Successful!&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Destructor frees sig-string allocated memory */&lt;br /&gt;
CSigScan::~CSigScan(void) {&lt;br /&gt;
    delete[] sig_str;&lt;br /&gt;
    delete[] sig_mask;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Get base address of the server module (base_addr) and get its ending offset (base_len) */&lt;br /&gt;
bool CSigScan::GetDllMemInfo(void) {&lt;br /&gt;
    void *pAddr = (void*)sigscan_dllfunc;&lt;br /&gt;
    base_addr = 0;&lt;br /&gt;
    base_len = 0;&lt;br /&gt;
&lt;br /&gt;
    #ifdef WIN32&lt;br /&gt;
    MEMORY_BASIC_INFORMATION mem;&lt;br /&gt;
&lt;br /&gt;
    if(!pAddr)&lt;br /&gt;
        return false; // GetDllMemInfo failed!pAddr&lt;br /&gt;
&lt;br /&gt;
    if(!VirtualQuery(pAddr, &amp;amp;mem, sizeof(mem)))&lt;br /&gt;
        return false;&lt;br /&gt;
&lt;br /&gt;
    base_addr = (unsigned char*)mem.AllocationBase;&lt;br /&gt;
&lt;br /&gt;
    IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER*)mem.AllocationBase;&lt;br /&gt;
    IMAGE_NT_HEADERS *pe = (IMAGE_NT_HEADERS*)((unsigned long)dos+(unsigned long)dos-&amp;gt;e_lfanew);&lt;br /&gt;
&lt;br /&gt;
    if(pe-&amp;gt;Signature != IMAGE_NT_SIGNATURE) {&lt;br /&gt;
        base_addr = 0;&lt;br /&gt;
        return false; // GetDllMemInfo failedpe points to a bad location&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    base_len = (size_t)pe-&amp;gt;OptionalHeader.SizeOfImage;&lt;br /&gt;
&lt;br /&gt;
    #else&lt;br /&gt;
&lt;br /&gt;
    Dl_info info;&lt;br /&gt;
    struct stat buf;&lt;br /&gt;
    &lt;br /&gt;
    if(!dladdr(pAddr, &amp;amp;info))&lt;br /&gt;
        return false;&lt;br /&gt;
    &lt;br /&gt;
    if(!info.dli_fbase || !info.dli_fname)&lt;br /&gt;
        return false;&lt;br /&gt;
    &lt;br /&gt;
    if(stat(info.dli_fname, &amp;amp;buf) != 0)&lt;br /&gt;
        return false;&lt;br /&gt;
    &lt;br /&gt;
    base_addr = (unsigned char*)info.dli_fbase;&lt;br /&gt;
    base_len = buf.st_size;&lt;br /&gt;
    #endif&lt;br /&gt;
&lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Scan for the signature in memory then return the starting position's address */&lt;br /&gt;
void* CSigScan::FindSignature(void) {&lt;br /&gt;
    unsigned char *pBasePtr = base_addr;&lt;br /&gt;
    unsigned char *pEndPtr = base_addr+base_len;&lt;br /&gt;
    size_t i;&lt;br /&gt;
&lt;br /&gt;
    while(pBasePtr &amp;lt; pEndPtr) {&lt;br /&gt;
        for(i = 0;i &amp;lt; sig_len;i++) {&lt;br /&gt;
            if((sig_mask[i] != '?') &amp;amp;&amp;amp; (sig_str[i] != pBasePtr[i]))&lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // If 'i' reached the end, we know we have a match!&lt;br /&gt;
        if(i == sig_len)&lt;br /&gt;
            return (void*)pBasePtr;&lt;br /&gt;
&lt;br /&gt;
        pBasePtr++;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return NULL;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Signature Objects */&lt;br /&gt;
CSigScan CBaseAnimating_Ignite_Sig;&lt;br /&gt;
&lt;br /&gt;
/* Set the static base_addr and base_len variables then initialize all Signature Objects */&lt;br /&gt;
void InitSigs(void) {&lt;br /&gt;
    CSigScan::GetDllMemInfo();&lt;br /&gt;
&lt;br /&gt;
    /* void CBaseAnimating::Ignite(float flFlameLifetime, bool bNPCOnly, float flSize,&lt;br /&gt;
        bool bCalledByLevelDesigner);&lt;br /&gt;
    Last Address: 0x220BC7A0&lt;br /&gt;
    Signature: 56  8B  F1  8B? 86? BC? 00? 00? 00? C1? E8? 1B? A8? 01? 0F? 85?&lt;br /&gt;
           9A? 00? 00? 00? 8B  16  FF  92? F0? 00? 00? 00? 80? 7C? 24? 0C?&lt;br /&gt;
           00? 74? 08? 84  C0  0F? 84? 83? 00? 00? 00? 3C  01  75? 20? 80&lt;br /&gt;
           7C  24  14  00  75? 19? 8B  CE  E8  83? 1A? 01? 00? 85? C0? 74?&lt;br /&gt;
           0E? 8B  10  8B  C8  FF  92? 08? 05? 00? 00? 84  C0  74? 5F? 57&lt;br /&gt;
           6A  01  56  E8  48? EA? 07? 00? 8B  F8  83  C4  08  85  FF  74?&lt;br /&gt;
           3D? 8B  44  24  0C  50  8B  CF  E8  83? E5? 07? 00? 68  00  00&lt;br /&gt;
           00  08  8B  CE&lt;br /&gt;
    */&lt;br /&gt;
    CBaseAnimating_Ignite_Sig.Init((unsigned char*)&lt;br /&gt;
    &amp;quot;\x56\x8B\xF1\x8B\x86\xBC\x00\x00\x00\xC1\xE8\x1B\xA8\x01\x0F\x85\x9A\x00\x00\x00&amp;quot;&lt;br /&gt;
    &amp;quot;\x8B\x16\xFF\x92\xF0\x00\x00\x00\x80\x7C\x24\x0C\x00\x74\x08\x84\xC0\x0F\x84\x83&amp;quot;&lt;br /&gt;
    &amp;quot;\x00\x00\x00\x3C\x01\x75\x20\x80\x7C\x24\x14\x00\x75\x19\x8B\xCE\xE8\x83\x1A\x01&amp;quot;&lt;br /&gt;
    &amp;quot;\x00\x85\xC0\x74\x0E\x8B\x10\x8B\xC8\xFF\x92\x08\x05\x00\x00\x84\xC0\x74\x5F\x57&amp;quot;&lt;br /&gt;
    &amp;quot;\x6A\x01\x56\xE8\x48\xEA\x07\x00\x8B\xF8\x83\xC4\x08\x85\xFF\x74\x3D\x8B\x44\x24&amp;quot;&lt;br /&gt;
    &amp;quot;\x0C\x50\x8B\xCF\xE8\x83\xE5\x07\x00\x68\x00\x00\x00\x08\x8B\xCE&amp;quot;&lt;br /&gt;
    ,&lt;br /&gt;
    &amp;quot;xxx?????????????????&amp;quot;&lt;br /&gt;
    &amp;quot;xxx????????????xx???&amp;quot;&lt;br /&gt;
    &amp;quot;???xx??xxxxx??xxx???&amp;quot;&lt;br /&gt;
    &amp;quot;?????xxxxx?????xx??x&amp;quot;&lt;br /&gt;
    &amp;quot;xxxx????xxxxxxx??xxx&amp;quot;&lt;br /&gt;
    &amp;quot;xxxxx????xxxxxxx&amp;quot;&lt;br /&gt;
    ,&lt;br /&gt;
    116);&lt;br /&gt;
&lt;br /&gt;
    return ;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Example of a sig-scanned method function */&lt;br /&gt;
void CBaseAnimating_Ignite(CBaseAnimating *cba, float flFlameLifetime) {&lt;br /&gt;
    int bNPCOnly = false, bCalledByLevelDesigner = false;&lt;br /&gt;
    float flSize = 0.0f;&lt;br /&gt;
&lt;br /&gt;
    if(!CBaseAnimating_Ignite_Sig.is_set)&lt;br /&gt;
        return ; // sigscan failed&lt;br /&gt;
&lt;br /&gt;
    union {&lt;br /&gt;
        void (EmptyClass::*mfpnew)(float, bool, float, bool);&lt;br /&gt;
        void* addr;&lt;br /&gt;
    } u;&lt;br /&gt;
    u.addr = CBaseAnimating_Ignite_Sig.sig_addr;&lt;br /&gt;
&lt;br /&gt;
    (reinterpret_cast&amp;lt;EmptyClass*&amp;gt;(cba)-&amp;gt;*u.mfpnew)(flFlameLifetime, (bool)bNPCOnly, flSize,&lt;br /&gt;
        (bool)bCalledByLevelDesigner);&lt;br /&gt;
&lt;br /&gt;
    return;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
This will find the signature of a function at runtime, however it is useless unless you already have or know how to find signatures for which it can scan.&lt;br /&gt;
&lt;br /&gt;
== Finding the Signature of a Function ==&lt;br /&gt;
&lt;br /&gt;
To find a signature for a function, we need a Disassembler to disassemble the server module. Here are links to free Disassemblers that seem to work well:&lt;br /&gt;
* [http://www.dirfile.com/ida_pro_freeware_version.htm IDA Pro Freeware Version (Windows)]&lt;br /&gt;
* [http://www.smidgeonsoft.prohosting.com/pebrowse-pro-file-viewer.html PEBrowse Professional (Windows)]&lt;br /&gt;
* [http://pvdasm.reverse-engineering.net/index.php?Section=1 Proview “PVDasm” Disassembler (Windows)]&lt;br /&gt;
* [http://www.gnu.org/software/binutils/manual/html_chapter/binutils_4.html GNU objdump (Linux)]&lt;br /&gt;
* [http://www.gnu.org/software/ddd/ Data Display Debugger (Linux)]&lt;br /&gt;
&lt;br /&gt;
=== Linux ===&lt;br /&gt;
&lt;br /&gt;
Showdax pointed out a very helpful way that makes finding signatures under Linux much easier than under Windows. The GNU tool &amp;quot;objdump&amp;quot; can be used against the server module to disassemble the binary into AT&amp;amp;T Assembly code with each subroutine given its name from the source code. Here is an example of how to use the objdump tool:&lt;br /&gt;
&amp;lt;pre&amp;gt;~/usr/srcds/dod/bin$ objdump -d server_i486.so &amp;gt; server_i486.so.objdump&amp;lt;/pre&amp;gt;&lt;br /&gt;
This dumps the disassembled code into the file &amp;quot;server_i486.so.objdump&amp;quot;. You can then simply open up that file and search for the function name that corresponds to its subroutine then extract its bytes to create a signature (discussed later in [[#Creating a Searchable Signature]]).&lt;br /&gt;
&lt;br /&gt;
=== Windows ===&lt;br /&gt;
&lt;br /&gt;
Under Windows, finding a signature becomes much more complicated as PE-format binaries do not include symbol names for each subroutine. I suggest using the IDA Pro Freeware Disassembler since I will be using a method I have found to find signatures that I only know how to do in IDA Pro (although you may be able to find a way to do my method in the other disassemblers).&lt;br /&gt;
&lt;br /&gt;
The rest of this section will assume you are running Windows, have a copy of Microsoft Visual Studio C++ and are using the IDA Pro Freeware Disassembler. First what you need to do is compile the HL2:DM server module. So navigate your way to the &amp;quot;hl2src/dlls&amp;quot; directory and open up &amp;quot;hl_sdk.vcproj&amp;quot;. Once open inside MSVC++, go to the Build menu and select Configuration Manager. Set the configuration to &amp;quot;Release&amp;quot; and press OK. Go to the Build menu again and select Build. This may take a bit as everything is compiled together. Once finished, you should have a new directory named &amp;quot;Release_hl2.&amp;quot; Inside, there will be the compiled server.dll file and a server.pdb file. The PDB file is key to finding the subroutines in Assembly for the function you want to use.&lt;br /&gt;
&lt;br /&gt;
Now open IDA Pro and go to the File menu and open the server.dll file you just compiled. When you open it, a dialog will pop up. Just press &amp;quot;OK&amp;quot; and everything will start to load. Eventually IDA Pro will say something akin to &amp;quot;There is a PDB file located in the same directory for this binary.&amp;quot; Click &amp;quot;Yes&amp;quot; and it will use that PDB file to name the subroutines which will make this process much easier. As things load, IDA Pro will go through the DLL, disassembling it and naming everything to their corresponding function or variable name. This may take a while and may even appear that IDA has frozen, but it has not so don't close it or you will have to start over.&lt;br /&gt;
&lt;br /&gt;
After some time, everything will have finished. Before we continue, however, we have to open up yet another IDA Pro again (don't close the other IDA Pro) and load the server.dll for the mod we will be sigscanning (in this case, Counter-Strike: Source). This file is located in &amp;quot;cstrike/bin&amp;quot; in your game installation directory. Again, do the same procedure, except this time we won't have a PDB file for it. This should take a shorter time than last time since there is no PDB file. After both IDA Pro processes have finished disassembling, we are ready to start finding signatures.&lt;br /&gt;
&lt;br /&gt;
To start looking for a signature, switch over to the HL2:DM server module IDA Pro window. Above, we have the signature for CBaseAnimating::Ignite in the [[#sigscan.cpp]] section. As a new example, let's try to find the signature for Teleporting an entity. This is the prototype for its method from the source code:&lt;br /&gt;
&amp;lt;cpp&amp;gt;virtual void CBaseEntity::Teleport(const Vector *newPosition, const QAngle *newAngles,&lt;br /&gt;
    const Vector *newVelocity);&amp;lt;/cpp&amp;gt;&lt;br /&gt;
Now in IDA Pro look for &amp;lt;i&amp;gt;CBaseEntity::Teleport&amp;lt;/i&amp;gt; in the &amp;lt;i&amp;gt;Names&amp;lt;/i&amp;gt; list then double click it. You should be brought to the location of &amp;lt;i&amp;gt;CBaseEntity::Teleport&amp;lt;/i&amp;gt; in the disassembly, however, its internal name is given as &amp;lt;i&amp;gt;CBaseEntity_Teleport&amp;lt;/i&amp;gt;. As you can see, IDA Pro lists all the local and parameter variables near the top (lines starting with &amp;lt;i&amp;gt;var_&amp;lt;/i&amp;gt; and &amp;lt;i&amp;gt;arg_&amp;lt;/i&amp;gt;), and then the actual code is listed below with its corresponding byte representation. (Tip: I had to actually set IDA Pro to list the opcode bytes from the Options menu, in &amp;quot;General&amp;quot; then under the tab &amp;quot;Disassembly&amp;quot;). At first, it seems feasible to just use the bytes here for the signature, but Valve decided to change almost all the CBase* methods (that I've seen) for Counter-Strike: Source from the Half-Life 2: Deathmatch code. Due to this fact, we will have to use the HL2:DM disassembly as clues for finding the same function/method in the CS:S disassembly. To find our Teleport function, we will have to find a unique set of instructions that wouldn't be repeated in another subroutine. I had to do some trial and error with this function since Valve had changed or moved various pieces of code. If you try looking over the subroutine for something unique, you may see a group of repeated &amp;lt;i&amp;gt;mov&amp;lt;/i&amp;gt; instructions:&lt;br /&gt;
&amp;lt;asm&amp;gt;.text:220C96CF 89 44 24 18          mov   [esp+30h+var_18], eax&lt;br /&gt;
.text:220C96D3 89 74 24 1C          mov   [esp+30h+var_14], esi&lt;br /&gt;
.text:220C96D7 89 74 24 20          mov   [esp+30h+var_10], esi&lt;br /&gt;
.text:220C96DB 89 74 24 24          mov   [esp+30h+var_C], esi&lt;br /&gt;
.text:220C96DF 89 74 24 28          mov   [esp+30h+var_8], esi&lt;br /&gt;
.text:220C96E3 89 74 24 2C          mov   [esp+30h+var_4], esi&amp;lt;/asm&amp;gt;&lt;br /&gt;
Try searching for part of this in the CS:S disassembly. If you get results, search for the next item to make sure there isn't another set of the same instructions. Then to verify this is the correct subroutine for the function Teleport(), compare the two subroutines to see if they have similar instructions in the same places. If they do then it is most likely correct and now you can use some of the instructions from your find in machine-code form to create a signature, which is discussed in the next section.&lt;br /&gt;
&lt;br /&gt;
== Creating a Searchable Signature ==&lt;br /&gt;
&lt;br /&gt;
Once we have found the subroutine for the function we want, we can start extracting the bytes for use in a signature. Here is part of the assembly for &amp;lt;i&amp;gt;CBaseEntity::Teleport&amp;lt;/i&amp;gt;:&lt;br /&gt;
&amp;lt;asm&amp;gt;220D9940                     CBaseEntity_Teleport proc near          ; CODE XREFsub_220B6330+14 p&lt;br /&gt;
220D9940                                                             ; sub_22143900+A p ...&lt;br /&gt;
220D9940&lt;br /&gt;
220D9940 83 EC 18            sub     esp, 18h&lt;br /&gt;
220D9943 53                  push    ebx&lt;br /&gt;
220D9944 56                  push    esi&lt;br /&gt;
220D9945 8B D9               mov     ebx, ecx&lt;br /&gt;
220D9947 8B 0D 78 B2 46 22   mov     ecx, dword_2246B278&lt;br /&gt;
220D994D 33 F6               xor     esi, esi&lt;br /&gt;
220D994F 33 C0               xor     eax, eax&lt;br /&gt;
220D9951 3B CE               cmp     ecx, esi&lt;br /&gt;
220D9953 7E 21               jle     short loc_220D9976&lt;br /&gt;
220D9955 8B 15 6C B2 46 22   mov     edx, dword_2246B26C&lt;br /&gt;
220D995B EB 03               jmp     short loc_220D9960&lt;br /&gt;
220D995B                     ; ---------------------------------------------------------------------------&lt;br /&gt;
220D995D 8D 49 00            align 10h&lt;br /&gt;
220D9960&lt;br /&gt;
220D9960                     loc_220D9960                          ; CODE XREFCBaseEntity_Teleport+1B j&lt;br /&gt;
220D9960                                                             ; CBaseEntity_Teleport+2A j&lt;br /&gt;
220D9960 39 1C 82            cmp     [edx+eax*4], ebx&lt;br /&gt;
220D9963 74 09               jz      short loc_220D996E&lt;br /&gt;
220D9965 83 C0 01            add     eax, 1&lt;br /&gt;
220D9968 3B C1               cmp     eax, ecx&lt;br /&gt;
220D996A 7C F4               jl      short loc_220D9960&lt;br /&gt;
220D996C EB 08               jmp     short loc_220D9976&lt;br /&gt;
220D996E                     ; ---------------------------------------------------------------------------&lt;br /&gt;
220D996E&lt;br /&gt;
220D996E                     loc_220D996E                          ; CODE XREFCBaseEntity_Teleport+23 j&lt;br /&gt;
220D996E 3B C6               cmp     eax, esi&lt;br /&gt;
220D9970 0F 8D 17 01 00 00   jge     loc_220D9A8D&lt;br /&gt;
220D9976&lt;br /&gt;
220D9976                     loc_220D9976                          ; CODE XREFCBaseEntity_Teleport+13 j&lt;br /&gt;
220D9976                                                             ; CBaseEntity_Teleport+2C j&lt;br /&gt;
220D9976 55                  push    ebp&lt;br /&gt;
220D9977 57                  push    edi&lt;br /&gt;
220D9978 8D 44 24 10         lea     eax, [esp+28h+var_18]&lt;br /&gt;
220D997C 50                  push    eax&lt;br /&gt;
220D997D 51                  push    ecx&lt;br /&gt;
220D997E B9 6C B2 46 22      mov     ecx, offset dword_2246B26C&lt;br /&gt;
220D9983 89 5C 24 18         mov     [esp+30h+var_18], ebx&lt;br /&gt;
220D9987 E8 B4 88 F9 FF      call    sub_22072240&lt;br /&gt;
220D998C 8D 4C 24 14         lea     ecx, [esp+28h+var_14]&lt;br /&gt;
220D9990 51                  push    ecx&lt;br /&gt;
220D9991 53                  push    ebx&lt;br /&gt;
220D9992 89 44 24 18         mov     [esp+30h+var_18], eax&lt;br /&gt;
220D9996 89 74 24 1C         mov     [esp+30h+var_14], esi&lt;br /&gt;
220D999A 89 74 24 20         mov     [esp+30h+var_10], esi&amp;lt;/asm&amp;gt;&lt;br /&gt;
I have written a small C program for which I use to create a signature string and signature mask from. It is not necessary to use, but it can help to reduce the amount of tedious work you have to do to create a signature.&lt;br /&gt;
&lt;br /&gt;
=== sigcreator.c ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;ctype.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    int i, len, out_i = 0, mask_i = 0;&lt;br /&gt;
    char *sig, *out, *mask;&lt;br /&gt;
    &lt;br /&gt;
    sig = (char*)calloc(1024, sizeof(char));&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;?&amp;quot;);&lt;br /&gt;
    fgets(sig, 1022, stdin);&lt;br /&gt;
    len = strlen(sig);&lt;br /&gt;
    &lt;br /&gt;
    out = (char*)calloc(len*2, sizeof(char));&lt;br /&gt;
    mask = (char*)calloc(len*2, sizeof(char));&lt;br /&gt;
    &lt;br /&gt;
    for(i = 0;i &amp;lt; len;i++) {&lt;br /&gt;
        if(isalnum(sig[i]) &amp;amp;&amp;amp; isalnum(sig[i+1])) {&lt;br /&gt;
            out[out_i++] = '\\';&lt;br /&gt;
            out[out_i++] = 'x';&lt;br /&gt;
            out[out_i++] = sig[i];&lt;br /&gt;
            out[out_i++] = sig[i+1];&lt;br /&gt;
            if(sig[i+2] == '?') {&lt;br /&gt;
                mask[mask_i++] = '?';&lt;br /&gt;
                i += 2;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                mask[mask_i++] = 'x';&lt;br /&gt;
                i++;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;\n\nSize%d\n\nSig:\n%s\n\nMask:\n%s&amp;quot;, strlen(mask), out, mask);&lt;br /&gt;
    getchar();&lt;br /&gt;
    &lt;br /&gt;
    free(sig);&lt;br /&gt;
    free(out);&lt;br /&gt;
    free(mask);&lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
It takes an input string of hexadecimal characters just as they appear in bold in the Assembly above. For each byte that should be ignored, a question mark after a hexadecimal byte will tell the program where a &amp;quot;?&amp;quot; should be in the signature mask. I will give an example of what the input and output should look like near the end of this section.&lt;br /&gt;
&lt;br /&gt;
When creating a signature, you must also create a signature mask as well. A signature mask tells the sigscanner which bytes to ignore, such as addresses which may change at runtime. The signature mask is the same length as the signature. A question mark (&amp;quot;?&amp;quot;) in the mask signifies the position of the byte in the signature string to be ignored. Any other character corresponding to a byte in the signature string will be checked (usually we use &amp;quot;x&amp;quot; to represent these).&lt;br /&gt;
&lt;br /&gt;
For the Teleport() function we found in the last section, we will build our signature from the bold hexadecimal characters in the Assembly above. I will be using the format of my &amp;quot;Sig Creator&amp;quot; for developing a signature string and mask for the sigscanner. The first three instructions in the subroutine are called the &amp;quot;function prologue.&amp;quot; These instructions will most likely never change as long as the variable declarations are not changed. So to start off, input &amp;quot;83 EC 18 53 56&amp;quot; into the sigcreator. Next is a mov instruction that probably won’t change &amp;quot;8B D9&amp;quot;. After that is another mov instruction, but this mov instruction contains an address in it, so add this to the input &amp;quot;8B? 0D? 78? B2? 46? 22?&amp;quot;. This will appear as question marks in the signature mask. The next set of xor instructions don’t reference an address so they’re safe to add normally to the input &amp;quot;33 F6 33 C0&amp;quot;. From here on, continue to input each segment of bytes into the sigcreator, where any segment referencing an address should have question marks following each hexadecimal character pairs (like I did for the mov instruction). Eventually you’ll end at those last mov instructions. This isn’t the end of the subroutine, but it’s enough to develop a worthy signature. So press enter in the sigcreator, and it should output something like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;?83 EC 18 53 56 8B D9 8B? 0D? 78? B2? 46? 22? 33 F6 33 C0 3B CE 7E? 21? 8B? 15?&lt;br /&gt;
6C? B2? 46? 22? EB? 03? 8D? 49? 00? 39 1C 82 74? 09? 83? C0? 01? 3B C1 7C? F4?&lt;br /&gt;
EB? 08? 3B C6 0F? 8D? 17? 01? 00? 00? 55 57? 8D? 44? 24? 10? 50 51 B9? 6C? B2?&lt;br /&gt;
46? 22? 89 5C 24 18 E8? B4? 88? F9? FF? 8D? 4C? 24? 14? 51 53 89 44 24 18 89&lt;br /&gt;
74 24 1C 89 74 24 20 89 74 24 24 89 74 24 28 89 74 24 2C&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Size106&lt;br /&gt;
&lt;br /&gt;
Sig:&lt;br /&gt;
\x83\xEC\x18\x53\x56\x8B\xD9\x8B\x0D\x78\xB2\x46\x22\x33\xF6\x33\xC0\x3B\xCE\x7E&lt;br /&gt;
\x21\x8B\x15\x6C\xB2\x46\x22\xEB\x03\x8D\x49\x00\x39\x1C\x82\x74\x09\x83\xC0\x01&lt;br /&gt;
\x3B\xC1\x7C\xF4\xEB\x08\x3B\xC6\x0F\x8D\x17\x01\x00\x00\x55\x57\x8D\x44\x24\x10&lt;br /&gt;
\x50\x51\xB9\x6C\xB2\x46\x22\x89\x5C\x24\x18\xE8\xB4\x88\xF9\xFF\x8D\x4C\x24\x14&lt;br /&gt;
\x51\x53\x89\x44\x24\x18\x89\x74\x24\x1C\x89\x74\x24\x20\x89\x74\x24\x24\x89\x74&lt;br /&gt;
\x24\x28\x89\x74\x24\x2C&lt;br /&gt;
&lt;br /&gt;
Mask:&lt;br /&gt;
xxxxxxx??????xxxxxx?????????????xxx?????xx????xx??????x?????xx?????xxxx?????????&lt;br /&gt;
xxxxxxxxxxxxxxxxxxxxxxxxxx&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now you have a nice signature and mask you can use for your sigscanner and it also gives you the length of the signature as well. Cheers!&lt;br /&gt;
&lt;br /&gt;
== Contributors ==&lt;br /&gt;
&lt;br /&gt;
Thank you to those who contributed to this document directly and/or indirectly:&lt;br /&gt;
*Lance Vorgin – Forefather of sigscanners, posted his sigscanner on the [[SourceMod]] forums somewhere&lt;br /&gt;
*BAILOPAN – Created his DevLogs on how to create a sigscanner, also gave tips as well as other useful information&lt;br /&gt;
*Showdax – Suggested the objdump command for disassembly on Linux&lt;br /&gt;
*CyberMind – Examples of how to use a different method of calling sig functions&lt;br /&gt;
*Jacob Lojo – Posted a thread on how to develop a signature from disassembly (I was having trouble finding sigs with my scanner before his post). Also contributed a link to another disassembler&lt;br /&gt;
*SeLfkiLL – Revision and completed code for the sigscanner and sigcreator&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;i&amp;gt;Oh, you’ve not hacked yet?&amp;lt;/i&amp;gt; – http://www.sourcemod.net/devlog/?p=55&lt;br /&gt;
*&amp;lt;i&amp;gt;Finding Functions, Part 2&amp;lt;/i&amp;gt; – http://www.sourcemod.net/devlog/?p=56&lt;br /&gt;
*&amp;lt;i&amp;gt;Finding Functions, Part 3&amp;lt;/i&amp;gt; – http://www.sourcemod.net/devlog/?p=57&lt;br /&gt;
*&amp;lt;i&amp;gt;Introduction to Reverse Engineering Software&amp;lt;/i&amp;gt; - http://www.acm.uiuc.edu/sigmil/RevEng/index.html&lt;br /&gt;
*&amp;lt;i&amp;gt;The Art of Assembly Language Programming&amp;lt;/i&amp;gt; - http://maven.smith.edu/~thiebaut/ArtOfAssembly/artofasm.html&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[Signatures_and_Offsets]]&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Mod_folder&amp;diff=3752</id>
		<title>Mod folder</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Mod_folder&amp;diff=3752"/>
		<updated>2007-01-14T05:26:23Z</updated>

		<summary type="html">&lt;p&gt;Sawce: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The subdirectory that your mod is stored in, in relation to the Half-Life base folder.&lt;br /&gt;
&lt;br /&gt;
Some common mod folders:&lt;br /&gt;
*'''cstrike''' - Counter-Strike&lt;br /&gt;
*'''czero''' - Counter-Strike: Condition Zero&lt;br /&gt;
*'''dod''' - Day of Defeat&lt;br /&gt;
*'''ns''' - Natural-Selection&lt;br /&gt;
*'''tfc''' - Team Fortress Classic&lt;br /&gt;
*'''ts''' - The Specialists&lt;br /&gt;
*'''valve''' - Half-Life Death Match&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Installing_AMX_Mod_X_Manually&amp;diff=3725</id>
		<title>Installing AMX Mod X Manually</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Installing_AMX_Mod_X_Manually&amp;diff=3725"/>
		<updated>2007-01-08T20:36:51Z</updated>

		<summary type="html">&lt;p&gt;Sawce: /* Configure */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide will help you install AMX Mod X without the assistance of an automated tool.&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
There are a few ways you can install [[AMX Mod X]]. If you have [[shell]] or direct access to your server, you can do all pf the operations directly on the server itself. If you only have [[FTP]] access, it's best to install [[AMX Mod X]] on a &amp;quot;[[dummy]]&amp;quot; folder on your hard drive, do all configuration there, and then upload the files to your server. Otherwise, you can upload the files as you're installing and then use [[FTP]] to change things along the way.&lt;br /&gt;
&lt;br /&gt;
Throughout the documentation we'll refer to your &amp;quot;[[mod folder]]&amp;quot; - this is the folder your mod is stored in, like &amp;quot;cstrike&amp;quot; (for Counter-Strike), or &amp;quot;dod&amp;quot; (for Day of Defeat).  If you're installing on a listen server, it will be in \Program Files\Steam\SteamApps\&amp;lt;your steam login&amp;gt;\&amp;lt;Valve game or Half-Life&amp;gt;\&amp;lt;mod folder&amp;gt;. If you're using a dedicated server, it will be HLServer\&amp;lt;mod folder&amp;gt;. On linux this is hlds_l/&amp;lt;mod folder&amp;gt;. If you are using remote/[[FTP]] access, you may be restricted to your [[mod folder]] or hlds_l already, and don't need to find it. For this documentation, &amp;lt;mod folder&amp;gt; will refer to the mod folder mentioned above. For [[Linux]] users, binaries will not end in &amp;quot;.dll&amp;quot;, they will usually end in &amp;quot;_i386.so&amp;quot; or &amp;quot;_amd64.so&amp;quot; for [[AMD64]] machines.&lt;br /&gt;
&lt;br /&gt;
=Directory Structure=&lt;br /&gt;
You should familiarize yourself with AMX Mod X's directory structure.  The addons folder resides in your [[mod folder]].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
--addons         - this is where Server addons go&lt;br /&gt;
 |--metamod      - this is where Metamod goes. Metamod is necessary to run AMX Mod X&lt;br /&gt;
   |--dlls       - this is where Metamod's binaries go&lt;br /&gt;
 |--amxmodx      - this is where AMX Mod X goes&lt;br /&gt;
   |--dlls       - amxmodx_mm.dll should go here&lt;br /&gt;
   |--modules    - Where modules are stored (_amxx.dll or _amxx_i386.so etc)&lt;br /&gt;
   |--plugins    - Where plugins are stored (.amx or .amxx)&lt;br /&gt;
   |--scripting  - Where example source code and the compiler/assembler are stored&lt;br /&gt;
     |--include  - Where include files for source code is stored&lt;br /&gt;
     |--compiled - Where the compiler batch file stores .amxx output&lt;br /&gt;
   |--doc        - This documentation is kept here&lt;br /&gt;
   |--data       - Binary data, for example saved stats, language caches, and GeoIP information&lt;br /&gt;
     |--lang     - Dictionary text files for AMX Mod X ML features (multi lingual)&lt;br /&gt;
   |--configs    - Configuration files&lt;br /&gt;
   |--logs       - AMX Mod X log files&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Installing Metamod=&lt;br /&gt;
Because AMX Mod X is a [[Metamod]] plugin, you must first install Metamod.  If you already have it installed, you may skip this section and jump to [[#Installing AMX Mod X]].  &lt;br /&gt;
==Directory Structure==&lt;br /&gt;
#In your mod folder, create a folder called &amp;quot;addons&amp;quot;.&lt;br /&gt;
#In &amp;lt;mod folder&amp;gt;\addons, create a folder called &amp;quot;metamod&amp;quot;.&lt;br /&gt;
#In &amp;lt;mod folder&amp;gt;\addons\metamod, create a folder called &amp;quot;dlls&amp;quot;.&lt;br /&gt;
==Upload Binaries==&lt;br /&gt;
#Go to the [http://www.metamod.org/ Metamod Website] and download Metamod.  You will want to get either the Windows [[DLL]] or the [[Linux SO]] (for either 32bit [[Linux]] or [[Linux]] on [[AMD64]]).&lt;br /&gt;
#Extract the metamod file and upload or copy it to your server.  It must be placed in &amp;lt;mod folder&amp;gt;\addons\metamod\dlls.&lt;br /&gt;
==Configure==&lt;br /&gt;
&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;In your mod folder, find the &amp;quot;[[liblist.gam]]&amp;quot; file.  Open the file with a text editor, such as [[notepad]].  If you're using FTP or a control panel, you will need to download the file first.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;For Windows, find this line:&lt;br /&gt;
::&amp;lt;pre&amp;gt;gamedll &amp;quot;dlls\mp.dll&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
::Replace it with this line:&lt;br /&gt;
::&amp;lt;pre&amp;gt;gamedll &amp;quot;addons\metamod\dlls\metamod.dll&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
For Linux, find this line:&lt;br /&gt;
::&amp;lt;pre&amp;gt;gamedll_linux &amp;quot;dlls/mp_i386.so&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
::Replace it with this line:&lt;br /&gt;
::&amp;lt;pre&amp;gt;gamedll_linux &amp;quot;addons/metamod/dlls/metamod_i386.so&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
::''(Note: AMD64 is no longer supported for various reasons, please use 32bit)''&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Save liblist.gam (and upload it over the old one if your server is remote).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Edit the file &amp;lt;mod folder&amp;gt;\addons\metamod\plugins.ini. If it does not exist, create it.  This file is your list of Metamod plugins.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;For Windows, add&lt;br /&gt;
&amp;lt;pre&amp;gt;win32 addons\amxmodx\dlls\amxmodx_mm.dll&amp;lt;/pre&amp;gt;&lt;br /&gt;
For Linux add:&lt;br /&gt;
&amp;lt;pre&amp;gt;linux addons/amxmodx/dlls/amxmodx_mm_i386.so&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Save (and upload) plugins.ini.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Installing AMX Mod X==&lt;br /&gt;
#Go to www.amxmodx.org and click &amp;quot;Downloads&amp;quot;. Download the amxmodx-base package for either Windows, Linux, or AMD64.&lt;br /&gt;
#Extract the base package to your mod folder. This will place AMX Mod X into &amp;lt;mod folder&amp;gt;\addons\amxmodx.  If you're uploading over FTP, you should extract it to a dummy location first (like your desktop).&lt;br /&gt;
#Go back to the AMX Mod X download site. If there is an addon pack for your mod available, and you want to use it, download the addon package corresponding to your mod.  As of this writing, addon packs are available for Counter-Strike/Condition-Zero, Team Fortress Classic, Day of Defeat, The Specialists, Natural Selection, and Earth's Special Forces.  Make sure you download the pack that corresponds to the server's operating system, either Windows, Linux, or Linux AMD64.&lt;br /&gt;
#Extract the addon pack to the same place as before, it should simply add more files to your AMX Mod X installation.&lt;br /&gt;
#If you're using FTP, upload the addons folder.&lt;br /&gt;
#AMX Mod X should now be installed!  You can type &amp;quot;meta list&amp;quot; in your [[server console]] to see if it was successful.  &lt;br /&gt;
#You can now move on to [[Configuring AMX Mod X]].  If you encountered problems, see [[Troubleshooting AMX Mod X]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation (AMX Mod X)]]&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Sawce&amp;diff=3546</id>
		<title>User:Sawce</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Sawce&amp;diff=3546"/>
		<updated>2006-12-10T08:31:37Z</updated>

		<summary type="html">&lt;p&gt;Sawce: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Man, hes so awesome.&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Configuring_AMX_Mod_X&amp;diff=3545</id>
		<title>Configuring AMX Mod X</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Configuring_AMX_Mod_X&amp;diff=3545"/>
		<updated>2006-12-10T08:31:12Z</updated>

		<summary type="html">&lt;p&gt;Sawce: /* Map Specific Plugins */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Admins=&lt;br /&gt;
See the section on [[Adding Admins (AMX Mod X)|Adding Admins]] for more information.&lt;br /&gt;
&lt;br /&gt;
=Plugins=&lt;br /&gt;
==Installing==&lt;br /&gt;
Often, plugins will have their own directions if they need special installation requirements.  However, this will instruct you on the basics of adding a plugin.&lt;br /&gt;
#Follow any directions the plugin author has given you. If the plugin requires extra steps or special files, make sure you have them in the proper place and order.&lt;br /&gt;
#If you are given a .sma source file instead of a .amxx, you must compile the plugin yourself.  For more information, see [[Compiling Plugins (AMX Mod X)]].&lt;br /&gt;
#Place the plugin's .amxx file in the addons/amxmodx/plugins folder.&lt;br /&gt;
#Add the plugin's name to addons\amxmodx\configs\plugins.ini. Example: &amp;lt;pre&amp;gt;myplugin.amxx&amp;lt;/pre&amp;gt;&lt;br /&gt;
#Change map or restart the server. If the plugin has any load errors, see [[Troubleshooting AMX Mod X#Plugins|Troubleshooting AMX Mod X]].&lt;br /&gt;
&lt;br /&gt;
==Removing==&lt;br /&gt;
#Remove the entry from addons\amxmodx\configs\plugins.ini by deleting it or prepending a semi-colon to comment it out.&lt;br /&gt;
#Delete any associated files.&lt;br /&gt;
&lt;br /&gt;
==Default Plugins==&lt;br /&gt;
:{|&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| Plugin&lt;br /&gt;
| Purpose&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| admin.amxx&lt;br /&gt;
| Administration Base&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| admin_sql.amxx 	&lt;br /&gt;
| Administration Base for SQL. Use only one base.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| admincmd.amxx 	&lt;br /&gt;
| Basic administration commands (such as kick/slap).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| adminhelp.amxx 	&lt;br /&gt;
| Help for admin commands.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| adminslots.amxx 	&lt;br /&gt;
| Slot reservation.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| multilingual.amxx 	&lt;br /&gt;
| Multi-Lingual client configuration.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| menufront.amxx 	&lt;br /&gt;
| Front-end for admin menus.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| cmdmenu.amxx 	&lt;br /&gt;
| Command menu for settings.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| plmenu.amxx 	&lt;br /&gt;
| Player menu commands (kick, ban, etc).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| telemenu.amxx 	&lt;br /&gt;
| Teleport Menu (fun module required).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| mapsmenu.amxx 	&lt;br /&gt;
| Maps menu (vote, changeleve, etc).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| adminchat.amxx 	&lt;br /&gt;
| Console-based chat commands.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| antiflood.amxx 	&lt;br /&gt;
| Prevents clients from flooding the say chat.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| scrollmsg.amxx 	&lt;br /&gt;
| Displays a scrolling message.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| imessage.amxx 	&lt;br /&gt;
| Displays a centered, timed information message.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| adminvote.amxx 	&lt;br /&gt;
| Voting commands.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| nextmap.amxx 	&lt;br /&gt;
| Displays next map in the mapcycle.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| mapchooser.amxx &lt;br /&gt;
| Allows players to vote for the next map.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| timeleft.amxx 	&lt;br /&gt;
| Displays time left on the current map.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| pausecfg.amxx 	&lt;br /&gt;
| Allows pausing/unpausing of plugins.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| statscfg.amxx 	&lt;br /&gt;
| Configuration of statistical plugins.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Modules=&lt;br /&gt;
Modules add additional functionality for plugins to use.&lt;br /&gt;
==Installing==&lt;br /&gt;
#Figure out what operating system your server is: Windows, Linux, or Linux using AMD64 (64bit).&lt;br /&gt;
#If the module is 3rd party, download the module corresponding to your OS.  It will end in .dll for Windows, _i386.so for Linux, or _amd64.so for AMD64.&lt;br /&gt;
#Place the file in addons/amxmodx/modules/ and follow any additional instructions.&lt;br /&gt;
#If the module is already in addons/amxmodx/configs/modules.ini, remove the ';' next to its name to enable it.&lt;br /&gt;
#Otherwise, add the module's name to modules.ini. [[AMX Mod X]] supports generic notation, for example: &amp;lt;pre&amp;gt;mysql_amxx&amp;lt;/pre&amp;gt; ... will automatically detect the correct module to use.&lt;br /&gt;
#To see if the module is working, you can type &amp;lt;tt&amp;gt;amxx modules&amp;lt;/tt&amp;gt; in your [[server console]].&lt;br /&gt;
&lt;br /&gt;
==Removing==&lt;br /&gt;
#Remove the entry from addons\amxmodx\configs\modules.ini by deleting it or prepending a semi-colon to comment it out.&lt;br /&gt;
#Delete any associated files if you don't need them.&lt;br /&gt;
&lt;br /&gt;
==Default Modules==&lt;br /&gt;
:{|&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| Module&lt;br /&gt;
| Purpose&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| fun_amxx&lt;br /&gt;
| General functions for changing game values.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| engine_amxx&lt;br /&gt;
| More advanced functions for getting and setting values in the HL engine.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| fakemeta_amxx&lt;br /&gt;
| Expert/advanced functions for manipulating, hooking, and calling functions in the HL engine.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| *sql_amxx&lt;br /&gt;
| SQL/Database scripting functions.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| geoip_amxx&lt;br /&gt;
| Functions for finding countries by IP address.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| array_amxx&lt;br /&gt;
| Functions for somewhat-dynamic arrays.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| sockets_amxx&lt;br /&gt;
| Functions for socket (TCP/UDP) control and manipulation.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| regex_amxx&lt;br /&gt;
| Functions for regular expression support.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=CVARs=&lt;br /&gt;
The base [[CVAR]]s AMX Mod X defines are located in amxmodx/configs/amxx.cfg.  You can edit these the same way you edit the server.cfg file:&lt;br /&gt;
:{|&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| CVAR&lt;br /&gt;
| Default Setting&lt;br /&gt;
| Purpose&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_default_access&lt;br /&gt;
| &amp;quot;z&amp;quot;&lt;br /&gt;
| Sets the default access level for non-admin players.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_password_field&lt;br /&gt;
| &amp;quot;_pw&amp;quot;&lt;br /&gt;
| Name of the setinfo key which a user should store their password in.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_mode&lt;br /&gt;
| 1&lt;br /&gt;
| Changes the mode of logging into a server:&amp;lt;br /&amp;gt;&lt;br /&gt;
0 - Disable logging, players won't be checked and no access will be given.&amp;lt;br /&amp;gt;&lt;br /&gt;
1 - Normal mode which obeys flags set in accounts.&amp;lt;br /&amp;gt;&lt;br /&gt;
2 - Kick all players not on the users list.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_show_activity&lt;br /&gt;
| 2&lt;br /&gt;
| Sets the mode of admin activity on the server:&amp;lt;br /&amp;gt;&lt;br /&gt;
0 - Disabled&amp;lt;br /&amp;gt;&lt;br /&gt;
1 - Show action anonymously&amp;lt;br /&amp;gt;&lt;br /&gt;
2 - Show action with the admin's name&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_scrollmsg&lt;br /&gt;
| &amp;quot;Welcome to %hostname% -- This server is using AMX Mod X&amp;quot; 600&lt;br /&gt;
| Sets the parameters (message and frequency) for a scrolling message.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_imessage&lt;br /&gt;
| &amp;quot;Welcome to %hostname&amp;quot; &amp;quot;000255100&amp;quot; &amp;lt;br /&amp;gt;&amp;quot;This server is using AMX Mod X\nVisit http://www.amxmodx.org&amp;quot; &amp;quot;00010025&amp;quot;&lt;br /&gt;
| Adds a center-typed colored message. The last parameter is in RRRGGGBBB format (red, green, blue).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_freq_imessage&lt;br /&gt;
| 180&lt;br /&gt;
| Frequency, in seconds, of the colored center messages.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_flood_time&lt;br /&gt;
| 0.75&lt;br /&gt;
| Chat flood prevention. Sets how fast a player can chat (in seconds).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_reservation&lt;br /&gt;
| 0&lt;br /&gt;
| Sets the amount of reserved slots.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_time_display&lt;br /&gt;
| &amp;quot;ab 1200&amp;quot; &amp;quot;ab 600&amp;quot; &amp;quot;ab 300&amp;quot; &amp;quot;ab 180&amp;quot; &amp;quot;ab 60&amp;quot; &amp;quot;bcde 11&amp;quot;&lt;br /&gt;
| Sets flags for remaining time display:&amp;lt;br /&amp;gt;&lt;br /&gt;
a - Display white text on bottom&amp;lt;br /&amp;gt;&lt;br /&gt;
b - Use voice&amp;lt;br /&amp;gt;&lt;br /&gt;
c - Don't add &amp;quot;remaining&amp;quot; in voice&amp;lt;br /&amp;gt;&lt;br /&gt;
d - Don't add &amp;quot;hours/minutes/seconds&amp;quot; in voice&amp;lt;br /&amp;gt;&lt;br /&gt;
e - Show/speak if current time is less than set in parameter&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_time_voice&lt;br /&gt;
| 1&lt;br /&gt;
| Sets whether to announce &amp;quot;say thetime&amp;quot; and &amp;quot;say timeleft&amp;quot; with voice.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_vote_delay&lt;br /&gt;
| 10&lt;br /&gt;
| Sets the minimum delay in seconds between two voting sessions.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_vote_time&lt;br /&gt;
| 10&lt;br /&gt;
| Sets how long a voting sessions lasts for.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_vote_answers&lt;br /&gt;
| 1&lt;br /&gt;
| Displays who votes for which options, publically.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_voteban_ratio&lt;br /&gt;
| 0.40&lt;br /&gt;
| Ratio for a ban vote to be successful.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_votekick_ratio&lt;br /&gt;
| 0.40&lt;br /&gt;
| Ratio for a kick vote to be successful.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_votemap_ratio&lt;br /&gt;
| 0.40&lt;br /&gt;
| Ratio for a map vote to be successful.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_vote_ratio&lt;br /&gt;
| 0.40&lt;br /&gt;
| Ratio for a general vote to be successful.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_extendmap_max&lt;br /&gt;
| 90&lt;br /&gt;
| Maximum time a mapvote can be extended.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_extendmap_step&lt;br /&gt;
| 15&lt;br /&gt;
| Amount of time a map extensions adds.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_client_languages&lt;br /&gt;
| 1&lt;br /&gt;
| Enables or disables the ability for clients to choose their own language.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_debug&lt;br /&gt;
| 1&lt;br /&gt;
| Sets the debug mode for plugins:&amp;lt;br /&amp;gt;&lt;br /&gt;
0 - No debugging (warning messages for plugin errors)&amp;lt;br /&amp;gt;&lt;br /&gt;
1 - Plugins with &amp;quot;debug&amp;quot; option in plugins.ini are put into debug mode.&amp;lt;br /&amp;gt;&lt;br /&gt;
2 - All plugins are put into debug mode (full backtraces for errors).&amp;lt;br /&amp;gt;&lt;br /&gt;
Note that debug mode greatly decreases JIT performance.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_mldebug&lt;br /&gt;
| 0&lt;br /&gt;
| Logs multi-lingual translation problems.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=SQL=&lt;br /&gt;
Make sure you have mysql_amxx enabled in AMX Mod X's amxmodx/configs/modules.ini file.  &lt;br /&gt;
&lt;br /&gt;
Then, open amxmodx/configs/sql.cfg and edit the cvars accordingly:&lt;br /&gt;
&lt;br /&gt;
:{|&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot; &lt;br /&gt;
| CVAR&lt;br /&gt;
| Default Setting&lt;br /&gt;
| Purpose&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_host&lt;br /&gt;
| &amp;quot;127.0.0.1&amp;quot;&lt;br /&gt;
| IP address of SQL server.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_user&lt;br /&gt;
| &amp;quot;root&amp;quot;&lt;br /&gt;
| Username to connect to the SQL server.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_pass&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Password to connect to the SQL server.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_db&lt;br /&gt;
| &amp;quot;amx&amp;quot;&lt;br /&gt;
| Database to use on the SQL server.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_table&lt;br /&gt;
| &amp;quot;admins&amp;quot;&lt;br /&gt;
| The table to use for the admin_sql plugin.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_type&lt;br /&gt;
| &amp;quot;mysql&amp;quot;&lt;br /&gt;
| The database type to connect to.&lt;br /&gt;
|}&lt;br /&gt;
*Note: amx_sql_type as of AMXX 1.75&lt;br /&gt;
&lt;br /&gt;
=Maps=&lt;br /&gt;
&lt;br /&gt;
==Map Cycle==&lt;br /&gt;
If you use the mapsmenu plugin, you can either use &amp;quot;maps.ini&amp;quot; or &amp;quot;mapcycle.txt&amp;quot; to manage map rotations.&lt;br /&gt;
&lt;br /&gt;
Delete &amp;quot;maps.ini&amp;quot; to use mapcycle.txt, otherwise, simply add a list of map names to maps.ini like so:&lt;br /&gt;
&amp;lt;pre&amp;gt;de_dust&lt;br /&gt;
cs_assault&lt;br /&gt;
de_aztec&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et cetera. &lt;br /&gt;
&lt;br /&gt;
==Map Config Files==&lt;br /&gt;
For each map, you can also add a configuration file that will execute when the map loads. This is useful to set certain settings for 3rd party maps, say, removing the freeze time on fy_iceworld.&lt;br /&gt;
&lt;br /&gt;
To do this, simply create a folder in amxmodx/configs called &amp;quot;maps&amp;quot; and place a .cfg file named after the map with the settings in it, for example, you might have amxmodx/configs/maps/fy_iceworld.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mp_startmoney 16000&lt;br /&gt;
mp_freezetime 0&lt;br /&gt;
mp_timelimit 20&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Map Specific Plugins==&lt;br /&gt;
Each map can have a specific plugins.ini file for which it will load on map change.  This plugins file will be loaded in addition to the standard plugins.ini file. &lt;br /&gt;
&lt;br /&gt;
The file is to be located at ''amxmodx/configs/maps/plugins-mapname.ini'' For example, for de_dust you would create the file '''amxmodx/configs/maps/plugins-de_dust.ini'''&lt;br /&gt;
&lt;br /&gt;
In addition, a plugin can be tagged as &amp;quot;''disabled''&amp;quot; which will prevent this plugin from being loaded.  You accomplish this the same way you tag a plugin as debug mode, by entering the word ''disabled'' after the plugin name in the file, which will prevent it from being loaded for that map.  &lt;br /&gt;
&lt;br /&gt;
For example, if you wanted the map de_dust to disable the plugin ''ham.amxx'' and enable the plugin ''pickle.amxx'' you would put this in ''amxmodx/configs/maps/plugins-de_dust.ini'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ham.amxx disabled&lt;br /&gt;
pickle.amxx&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This feature was added in [[AMX_Mod_X_1.76_Changes|AMX Mod X 1.76]]&lt;br /&gt;
&lt;br /&gt;
=Menus=&lt;br /&gt;
==Client Commands==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\clcmds.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Name&amp;quot; &amp;quot;Command&amp;quot; &amp;quot;Flags&amp;quot; &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | Name is the name that will appear on the menu.&amp;lt;br /&amp;gt;&lt;br /&gt;
Command is the format for the console command - you can use %userid% to insert the user's id.&amp;lt;br /&amp;gt;&lt;br /&gt;
Flags are one of the following:&amp;lt;br /&amp;gt;&lt;br /&gt;
  a - execute from server console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  b - execute from admin console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  c - execute on selected player.&amp;lt;br /&amp;gt;&lt;br /&gt;
  d - display menu again once done&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Slay player&amp;quot; &amp;quot;amx_slay #%userid%&amp;quot; &amp;quot;bd&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Commands==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\cmds.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Name&amp;quot; &amp;quot;Command&amp;quot; &amp;quot;Flags&amp;quot; &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | Name is the name that will appear on the menu.&amp;lt;br /&amp;gt;&lt;br /&gt;
Command is the format for the console command - you can use %userid% to insert the user's id.&amp;lt;br /&amp;gt;&lt;br /&gt;
Flags are one of the following:&amp;lt;br /&amp;gt;&lt;br /&gt;
  a - execute from server console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  b - execute from admin console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  c - execute on selected player.&amp;lt;br /&amp;gt;&lt;br /&gt;
  d - display menu again once done&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Pause&amp;quot; &amp;quot;amx_pause&amp;quot; &amp;quot;bd&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Configs==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\configs.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Name&amp;quot; &amp;quot;Command&amp;quot; &amp;quot;Flags&amp;quot; &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | Name is the name that will appear on the menu.&amp;lt;br /&amp;gt;&lt;br /&gt;
Command is the format for the console command.&lt;br /&gt;
Flags are one of the following:&amp;lt;br /&amp;gt;&lt;br /&gt;
  a - execute from server console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  b - execute from admin console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  d - display menu again once done&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;PUBLIC Settings&amp;quot; &amp;quot;servercfgfile server.cfg;exec server.cfg&amp;quot; &amp;quot;a&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==CVARs==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\cvars.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;CVAR&amp;quot; &amp;quot;Values&amp;quot; ... &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | CVAR - the CVAR's name&amp;lt;br /&amp;gt;&lt;br /&gt;
Values - list of space delimited, quotation enclosed values&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;mp_autoteambalance&amp;quot; &amp;quot;0&amp;quot; &amp;quot;1&amp;quot; &amp;quot;@&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Speech==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\speech.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Name&amp;quot; &amp;quot;Command&amp;quot; &amp;quot;Flags&amp;quot; &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | Name is the name that will appear on the menu.&amp;lt;br /&amp;gt;&lt;br /&gt;
Command is the format for the console command - you can use %userid% to insert the user's id.&amp;lt;br /&amp;gt;&lt;br /&gt;
Flags are one of the following:&amp;lt;br /&amp;gt;&lt;br /&gt;
  a - execute from server console&amp;lt;br /&amp;gt;&lt;br /&gt;
  b - execute from admin console&amp;lt;br /&amp;gt;&lt;br /&gt;
  c - execute on selected player&amp;lt;br /&amp;gt;&lt;br /&gt;
  d - display menu again once done&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Hello!&amp;quot; &amp;quot;spk \'vox/hello\'&amp;quot; &amp;quot;cd&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation (AMX Mod X)]]&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Configuring_AMX_Mod_X&amp;diff=3544</id>
		<title>Configuring AMX Mod X</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Configuring_AMX_Mod_X&amp;diff=3544"/>
		<updated>2006-12-10T07:54:27Z</updated>

		<summary type="html">&lt;p&gt;Sawce: /* Map Specific Config Files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Admins=&lt;br /&gt;
See the section on [[Adding Admins (AMX Mod X)|Adding Admins]] for more information.&lt;br /&gt;
&lt;br /&gt;
=Plugins=&lt;br /&gt;
==Installing==&lt;br /&gt;
Often, plugins will have their own directions if they need special installation requirements.  However, this will instruct you on the basics of adding a plugin.&lt;br /&gt;
#Follow any directions the plugin author has given you. If the plugin requires extra steps or special files, make sure you have them in the proper place and order.&lt;br /&gt;
#If you are given a .sma source file instead of a .amxx, you must compile the plugin yourself.  For more information, see [[Compiling Plugins (AMX Mod X)]].&lt;br /&gt;
#Place the plugin's .amxx file in the addons/amxmodx/plugins folder.&lt;br /&gt;
#Add the plugin's name to addons\amxmodx\configs\plugins.ini. Example: &amp;lt;pre&amp;gt;myplugin.amxx&amp;lt;/pre&amp;gt;&lt;br /&gt;
#Change map or restart the server. If the plugin has any load errors, see [[Troubleshooting AMX Mod X#Plugins|Troubleshooting AMX Mod X]].&lt;br /&gt;
&lt;br /&gt;
==Removing==&lt;br /&gt;
#Remove the entry from addons\amxmodx\configs\plugins.ini by deleting it or prepending a semi-colon to comment it out.&lt;br /&gt;
#Delete any associated files.&lt;br /&gt;
&lt;br /&gt;
==Default Plugins==&lt;br /&gt;
:{|&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| Plugin&lt;br /&gt;
| Purpose&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| admin.amxx&lt;br /&gt;
| Administration Base&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| admin_sql.amxx 	&lt;br /&gt;
| Administration Base for SQL. Use only one base.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| admincmd.amxx 	&lt;br /&gt;
| Basic administration commands (such as kick/slap).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| adminhelp.amxx 	&lt;br /&gt;
| Help for admin commands.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| adminslots.amxx 	&lt;br /&gt;
| Slot reservation.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| multilingual.amxx 	&lt;br /&gt;
| Multi-Lingual client configuration.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| menufront.amxx 	&lt;br /&gt;
| Front-end for admin menus.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| cmdmenu.amxx 	&lt;br /&gt;
| Command menu for settings.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| plmenu.amxx 	&lt;br /&gt;
| Player menu commands (kick, ban, etc).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| telemenu.amxx 	&lt;br /&gt;
| Teleport Menu (fun module required).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| mapsmenu.amxx 	&lt;br /&gt;
| Maps menu (vote, changeleve, etc).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| adminchat.amxx 	&lt;br /&gt;
| Console-based chat commands.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| antiflood.amxx 	&lt;br /&gt;
| Prevents clients from flooding the say chat.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| scrollmsg.amxx 	&lt;br /&gt;
| Displays a scrolling message.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| imessage.amxx 	&lt;br /&gt;
| Displays a centered, timed information message.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| adminvote.amxx 	&lt;br /&gt;
| Voting commands.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| nextmap.amxx 	&lt;br /&gt;
| Displays next map in the mapcycle.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| mapchooser.amxx &lt;br /&gt;
| Allows players to vote for the next map.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| timeleft.amxx 	&lt;br /&gt;
| Displays time left on the current map.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| pausecfg.amxx 	&lt;br /&gt;
| Allows pausing/unpausing of plugins.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| statscfg.amxx 	&lt;br /&gt;
| Configuration of statistical plugins.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Modules=&lt;br /&gt;
Modules add additional functionality for plugins to use.&lt;br /&gt;
==Installing==&lt;br /&gt;
#Figure out what operating system your server is: Windows, Linux, or Linux using AMD64 (64bit).&lt;br /&gt;
#If the module is 3rd party, download the module corresponding to your OS.  It will end in .dll for Windows, _i386.so for Linux, or _amd64.so for AMD64.&lt;br /&gt;
#Place the file in addons/amxmodx/modules/ and follow any additional instructions.&lt;br /&gt;
#If the module is already in addons/amxmodx/configs/modules.ini, remove the ';' next to its name to enable it.&lt;br /&gt;
#Otherwise, add the module's name to modules.ini. [[AMX Mod X]] supports generic notation, for example: &amp;lt;pre&amp;gt;mysql_amxx&amp;lt;/pre&amp;gt; ... will automatically detect the correct module to use.&lt;br /&gt;
#To see if the module is working, you can type &amp;lt;tt&amp;gt;amxx modules&amp;lt;/tt&amp;gt; in your [[server console]].&lt;br /&gt;
&lt;br /&gt;
==Removing==&lt;br /&gt;
#Remove the entry from addons\amxmodx\configs\modules.ini by deleting it or prepending a semi-colon to comment it out.&lt;br /&gt;
#Delete any associated files if you don't need them.&lt;br /&gt;
&lt;br /&gt;
==Default Modules==&lt;br /&gt;
:{|&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| Module&lt;br /&gt;
| Purpose&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| fun_amxx&lt;br /&gt;
| General functions for changing game values.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| engine_amxx&lt;br /&gt;
| More advanced functions for getting and setting values in the HL engine.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| fakemeta_amxx&lt;br /&gt;
| Expert/advanced functions for manipulating, hooking, and calling functions in the HL engine.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| *sql_amxx&lt;br /&gt;
| SQL/Database scripting functions.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| geoip_amxx&lt;br /&gt;
| Functions for finding countries by IP address.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| array_amxx&lt;br /&gt;
| Functions for somewhat-dynamic arrays.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| sockets_amxx&lt;br /&gt;
| Functions for socket (TCP/UDP) control and manipulation.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| regex_amxx&lt;br /&gt;
| Functions for regular expression support.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=CVARs=&lt;br /&gt;
The base [[CVAR]]s AMX Mod X defines are located in amxmodx/configs/amxx.cfg.  You can edit these the same way you edit the server.cfg file:&lt;br /&gt;
:{|&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| CVAR&lt;br /&gt;
| Default Setting&lt;br /&gt;
| Purpose&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_default_access&lt;br /&gt;
| &amp;quot;z&amp;quot;&lt;br /&gt;
| Sets the default access level for non-admin players.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_password_field&lt;br /&gt;
| &amp;quot;_pw&amp;quot;&lt;br /&gt;
| Name of the setinfo key which a user should store their password in.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_mode&lt;br /&gt;
| 1&lt;br /&gt;
| Changes the mode of logging into a server:&amp;lt;br /&amp;gt;&lt;br /&gt;
0 - Disable logging, players won't be checked and no access will be given.&amp;lt;br /&amp;gt;&lt;br /&gt;
1 - Normal mode which obeys flags set in accounts.&amp;lt;br /&amp;gt;&lt;br /&gt;
2 - Kick all players not on the users list.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_show_activity&lt;br /&gt;
| 2&lt;br /&gt;
| Sets the mode of admin activity on the server:&amp;lt;br /&amp;gt;&lt;br /&gt;
0 - Disabled&amp;lt;br /&amp;gt;&lt;br /&gt;
1 - Show action anonymously&amp;lt;br /&amp;gt;&lt;br /&gt;
2 - Show action with the admin's name&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_scrollmsg&lt;br /&gt;
| &amp;quot;Welcome to %hostname% -- This server is using AMX Mod X&amp;quot; 600&lt;br /&gt;
| Sets the parameters (message and frequency) for a scrolling message.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_imessage&lt;br /&gt;
| &amp;quot;Welcome to %hostname&amp;quot; &amp;quot;000255100&amp;quot; &amp;lt;br /&amp;gt;&amp;quot;This server is using AMX Mod X\nVisit http://www.amxmodx.org&amp;quot; &amp;quot;00010025&amp;quot;&lt;br /&gt;
| Adds a center-typed colored message. The last parameter is in RRRGGGBBB format (red, green, blue).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_freq_imessage&lt;br /&gt;
| 180&lt;br /&gt;
| Frequency, in seconds, of the colored center messages.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_flood_time&lt;br /&gt;
| 0.75&lt;br /&gt;
| Chat flood prevention. Sets how fast a player can chat (in seconds).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_reservation&lt;br /&gt;
| 0&lt;br /&gt;
| Sets the amount of reserved slots.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_time_display&lt;br /&gt;
| &amp;quot;ab 1200&amp;quot; &amp;quot;ab 600&amp;quot; &amp;quot;ab 300&amp;quot; &amp;quot;ab 180&amp;quot; &amp;quot;ab 60&amp;quot; &amp;quot;bcde 11&amp;quot;&lt;br /&gt;
| Sets flags for remaining time display:&amp;lt;br /&amp;gt;&lt;br /&gt;
a - Display white text on bottom&amp;lt;br /&amp;gt;&lt;br /&gt;
b - Use voice&amp;lt;br /&amp;gt;&lt;br /&gt;
c - Don't add &amp;quot;remaining&amp;quot; in voice&amp;lt;br /&amp;gt;&lt;br /&gt;
d - Don't add &amp;quot;hours/minutes/seconds&amp;quot; in voice&amp;lt;br /&amp;gt;&lt;br /&gt;
e - Show/speak if current time is less than set in parameter&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_time_voice&lt;br /&gt;
| 1&lt;br /&gt;
| Sets whether to announce &amp;quot;say thetime&amp;quot; and &amp;quot;say timeleft&amp;quot; with voice.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_vote_delay&lt;br /&gt;
| 10&lt;br /&gt;
| Sets the minimum delay in seconds between two voting sessions.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_vote_time&lt;br /&gt;
| 10&lt;br /&gt;
| Sets how long a voting sessions lasts for.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_vote_answers&lt;br /&gt;
| 1&lt;br /&gt;
| Displays who votes for which options, publically.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_voteban_ratio&lt;br /&gt;
| 0.40&lt;br /&gt;
| Ratio for a ban vote to be successful.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_votekick_ratio&lt;br /&gt;
| 0.40&lt;br /&gt;
| Ratio for a kick vote to be successful.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_votemap_ratio&lt;br /&gt;
| 0.40&lt;br /&gt;
| Ratio for a map vote to be successful.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_vote_ratio&lt;br /&gt;
| 0.40&lt;br /&gt;
| Ratio for a general vote to be successful.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_extendmap_max&lt;br /&gt;
| 90&lt;br /&gt;
| Maximum time a mapvote can be extended.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_extendmap_step&lt;br /&gt;
| 15&lt;br /&gt;
| Amount of time a map extensions adds.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_client_languages&lt;br /&gt;
| 1&lt;br /&gt;
| Enables or disables the ability for clients to choose their own language.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_debug&lt;br /&gt;
| 1&lt;br /&gt;
| Sets the debug mode for plugins:&amp;lt;br /&amp;gt;&lt;br /&gt;
0 - No debugging (warning messages for plugin errors)&amp;lt;br /&amp;gt;&lt;br /&gt;
1 - Plugins with &amp;quot;debug&amp;quot; option in plugins.ini are put into debug mode.&amp;lt;br /&amp;gt;&lt;br /&gt;
2 - All plugins are put into debug mode (full backtraces for errors).&amp;lt;br /&amp;gt;&lt;br /&gt;
Note that debug mode greatly decreases JIT performance.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_mldebug&lt;br /&gt;
| 0&lt;br /&gt;
| Logs multi-lingual translation problems.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=SQL=&lt;br /&gt;
Make sure you have mysql_amxx enabled in AMX Mod X's amxmodx/configs/modules.ini file.  &lt;br /&gt;
&lt;br /&gt;
Then, open amxmodx/configs/sql.cfg and edit the cvars accordingly:&lt;br /&gt;
&lt;br /&gt;
:{|&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot; &lt;br /&gt;
| CVAR&lt;br /&gt;
| Default Setting&lt;br /&gt;
| Purpose&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_host&lt;br /&gt;
| &amp;quot;127.0.0.1&amp;quot;&lt;br /&gt;
| IP address of SQL server.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_user&lt;br /&gt;
| &amp;quot;root&amp;quot;&lt;br /&gt;
| Username to connect to the SQL server.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_pass&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Password to connect to the SQL server.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_db&lt;br /&gt;
| &amp;quot;amx&amp;quot;&lt;br /&gt;
| Database to use on the SQL server.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_table&lt;br /&gt;
| &amp;quot;admins&amp;quot;&lt;br /&gt;
| The table to use for the admin_sql plugin.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_type&lt;br /&gt;
| &amp;quot;mysql&amp;quot;&lt;br /&gt;
| The database type to connect to.&lt;br /&gt;
|}&lt;br /&gt;
*Note: amx_sql_type as of AMXX 1.75&lt;br /&gt;
&lt;br /&gt;
=Maps=&lt;br /&gt;
&lt;br /&gt;
==Map Cycle==&lt;br /&gt;
If you use the mapsmenu plugin, you can either use &amp;quot;maps.ini&amp;quot; or &amp;quot;mapcycle.txt&amp;quot; to manage map rotations.&lt;br /&gt;
&lt;br /&gt;
Delete &amp;quot;maps.ini&amp;quot; to use mapcycle.txt, otherwise, simply add a list of map names to maps.ini like so:&lt;br /&gt;
&amp;lt;pre&amp;gt;de_dust&lt;br /&gt;
cs_assault&lt;br /&gt;
de_aztec&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et cetera. &lt;br /&gt;
&lt;br /&gt;
==Map Config Files==&lt;br /&gt;
For each map, you can also add a configuration file that will execute when the map loads. This is useful to set certain settings for 3rd party maps, say, removing the freeze time on fy_iceworld.&lt;br /&gt;
&lt;br /&gt;
To do this, simply create a folder in amxmodx/configs called &amp;quot;maps&amp;quot; and place a .cfg file named after the map with the settings in it, for example, you might have amxmodx/configs/maps/fy_iceworld.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mp_startmoney 16000&lt;br /&gt;
mp_freezetime 0&lt;br /&gt;
mp_timelimit 20&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Map Specific Plugins==&lt;br /&gt;
Each map can have a specific plugins.ini file for which it will load on map change.  &lt;br /&gt;
&lt;br /&gt;
The file is to be located at ''amxmodx/configs/maps/plugins-mapname.ini'' For example, for de_dust you would create the file '''amxmodx/configs/maps/plugins-de_dust.ini'''&lt;br /&gt;
&lt;br /&gt;
In addition, a plugin can be tagged as &amp;quot;''disabled''&amp;quot; which will prevent this plugin from being loaded.  You accomplish this the same way you tag a plugin as debug mode, by entering the word ''disabled'' after the plugin name in the file, which will prevent it from being loaded for that map.  &lt;br /&gt;
&lt;br /&gt;
For example, if you wanted the map de_dust to disable the plugin ''ham.amxx'' and enable the plugin ''pickle.amxx'' you would put this in ''amxmodx/configs/maps/plugins-de_dust.ini'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ham.amxx disabled&lt;br /&gt;
pickle.amxx&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This feature was added in [[AMX_Mod_X_1.76_Changes|AMX Mod X 1.76]]&lt;br /&gt;
&lt;br /&gt;
=Menus=&lt;br /&gt;
==Client Commands==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\clcmds.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Name&amp;quot; &amp;quot;Command&amp;quot; &amp;quot;Flags&amp;quot; &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | Name is the name that will appear on the menu.&amp;lt;br /&amp;gt;&lt;br /&gt;
Command is the format for the console command - you can use %userid% to insert the user's id.&amp;lt;br /&amp;gt;&lt;br /&gt;
Flags are one of the following:&amp;lt;br /&amp;gt;&lt;br /&gt;
  a - execute from server console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  b - execute from admin console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  c - execute on selected player.&amp;lt;br /&amp;gt;&lt;br /&gt;
  d - display menu again once done&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Slay player&amp;quot; &amp;quot;amx_slay #%userid%&amp;quot; &amp;quot;bd&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Commands==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\cmds.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Name&amp;quot; &amp;quot;Command&amp;quot; &amp;quot;Flags&amp;quot; &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | Name is the name that will appear on the menu.&amp;lt;br /&amp;gt;&lt;br /&gt;
Command is the format for the console command - you can use %userid% to insert the user's id.&amp;lt;br /&amp;gt;&lt;br /&gt;
Flags are one of the following:&amp;lt;br /&amp;gt;&lt;br /&gt;
  a - execute from server console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  b - execute from admin console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  c - execute on selected player.&amp;lt;br /&amp;gt;&lt;br /&gt;
  d - display menu again once done&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Pause&amp;quot; &amp;quot;amx_pause&amp;quot; &amp;quot;bd&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Configs==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\configs.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Name&amp;quot; &amp;quot;Command&amp;quot; &amp;quot;Flags&amp;quot; &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | Name is the name that will appear on the menu.&amp;lt;br /&amp;gt;&lt;br /&gt;
Command is the format for the console command.&lt;br /&gt;
Flags are one of the following:&amp;lt;br /&amp;gt;&lt;br /&gt;
  a - execute from server console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  b - execute from admin console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  d - display menu again once done&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;PUBLIC Settings&amp;quot; &amp;quot;servercfgfile server.cfg;exec server.cfg&amp;quot; &amp;quot;a&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==CVARs==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\cvars.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;CVAR&amp;quot; &amp;quot;Values&amp;quot; ... &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | CVAR - the CVAR's name&amp;lt;br /&amp;gt;&lt;br /&gt;
Values - list of space delimited, quotation enclosed values&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;mp_autoteambalance&amp;quot; &amp;quot;0&amp;quot; &amp;quot;1&amp;quot; &amp;quot;@&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Speech==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\speech.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Name&amp;quot; &amp;quot;Command&amp;quot; &amp;quot;Flags&amp;quot; &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | Name is the name that will appear on the menu.&amp;lt;br /&amp;gt;&lt;br /&gt;
Command is the format for the console command - you can use %userid% to insert the user's id.&amp;lt;br /&amp;gt;&lt;br /&gt;
Flags are one of the following:&amp;lt;br /&amp;gt;&lt;br /&gt;
  a - execute from server console&amp;lt;br /&amp;gt;&lt;br /&gt;
  b - execute from admin console&amp;lt;br /&amp;gt;&lt;br /&gt;
  c - execute on selected player&amp;lt;br /&amp;gt;&lt;br /&gt;
  d - display menu again once done&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Hello!&amp;quot; &amp;quot;spk \'vox/hello\'&amp;quot; &amp;quot;cd&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation (AMX Mod X)]]&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Configuring_AMX_Mod_X&amp;diff=3543</id>
		<title>Configuring AMX Mod X</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Configuring_AMX_Mod_X&amp;diff=3543"/>
		<updated>2006-12-10T07:52:08Z</updated>

		<summary type="html">&lt;p&gt;Sawce: /* Map Specific Plugins */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Admins=&lt;br /&gt;
See the section on [[Adding Admins (AMX Mod X)|Adding Admins]] for more information.&lt;br /&gt;
&lt;br /&gt;
=Plugins=&lt;br /&gt;
==Installing==&lt;br /&gt;
Often, plugins will have their own directions if they need special installation requirements.  However, this will instruct you on the basics of adding a plugin.&lt;br /&gt;
#Follow any directions the plugin author has given you. If the plugin requires extra steps or special files, make sure you have them in the proper place and order.&lt;br /&gt;
#If you are given a .sma source file instead of a .amxx, you must compile the plugin yourself.  For more information, see [[Compiling Plugins (AMX Mod X)]].&lt;br /&gt;
#Place the plugin's .amxx file in the addons/amxmodx/plugins folder.&lt;br /&gt;
#Add the plugin's name to addons\amxmodx\configs\plugins.ini. Example: &amp;lt;pre&amp;gt;myplugin.amxx&amp;lt;/pre&amp;gt;&lt;br /&gt;
#Change map or restart the server. If the plugin has any load errors, see [[Troubleshooting AMX Mod X#Plugins|Troubleshooting AMX Mod X]].&lt;br /&gt;
&lt;br /&gt;
==Removing==&lt;br /&gt;
#Remove the entry from addons\amxmodx\configs\plugins.ini by deleting it or prepending a semi-colon to comment it out.&lt;br /&gt;
#Delete any associated files.&lt;br /&gt;
&lt;br /&gt;
==Default Plugins==&lt;br /&gt;
:{|&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| Plugin&lt;br /&gt;
| Purpose&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| admin.amxx&lt;br /&gt;
| Administration Base&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| admin_sql.amxx 	&lt;br /&gt;
| Administration Base for SQL. Use only one base.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| admincmd.amxx 	&lt;br /&gt;
| Basic administration commands (such as kick/slap).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| adminhelp.amxx 	&lt;br /&gt;
| Help for admin commands.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| adminslots.amxx 	&lt;br /&gt;
| Slot reservation.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| multilingual.amxx 	&lt;br /&gt;
| Multi-Lingual client configuration.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| menufront.amxx 	&lt;br /&gt;
| Front-end for admin menus.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| cmdmenu.amxx 	&lt;br /&gt;
| Command menu for settings.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| plmenu.amxx 	&lt;br /&gt;
| Player menu commands (kick, ban, etc).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| telemenu.amxx 	&lt;br /&gt;
| Teleport Menu (fun module required).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| mapsmenu.amxx 	&lt;br /&gt;
| Maps menu (vote, changeleve, etc).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| adminchat.amxx 	&lt;br /&gt;
| Console-based chat commands.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| antiflood.amxx 	&lt;br /&gt;
| Prevents clients from flooding the say chat.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| scrollmsg.amxx 	&lt;br /&gt;
| Displays a scrolling message.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| imessage.amxx 	&lt;br /&gt;
| Displays a centered, timed information message.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| adminvote.amxx 	&lt;br /&gt;
| Voting commands.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| nextmap.amxx 	&lt;br /&gt;
| Displays next map in the mapcycle.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| mapchooser.amxx &lt;br /&gt;
| Allows players to vote for the next map.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| timeleft.amxx 	&lt;br /&gt;
| Displays time left on the current map.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| pausecfg.amxx 	&lt;br /&gt;
| Allows pausing/unpausing of plugins.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| statscfg.amxx 	&lt;br /&gt;
| Configuration of statistical plugins.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Modules=&lt;br /&gt;
Modules add additional functionality for plugins to use.&lt;br /&gt;
==Installing==&lt;br /&gt;
#Figure out what operating system your server is: Windows, Linux, or Linux using AMD64 (64bit).&lt;br /&gt;
#If the module is 3rd party, download the module corresponding to your OS.  It will end in .dll for Windows, _i386.so for Linux, or _amd64.so for AMD64.&lt;br /&gt;
#Place the file in addons/amxmodx/modules/ and follow any additional instructions.&lt;br /&gt;
#If the module is already in addons/amxmodx/configs/modules.ini, remove the ';' next to its name to enable it.&lt;br /&gt;
#Otherwise, add the module's name to modules.ini. [[AMX Mod X]] supports generic notation, for example: &amp;lt;pre&amp;gt;mysql_amxx&amp;lt;/pre&amp;gt; ... will automatically detect the correct module to use.&lt;br /&gt;
#To see if the module is working, you can type &amp;lt;tt&amp;gt;amxx modules&amp;lt;/tt&amp;gt; in your [[server console]].&lt;br /&gt;
&lt;br /&gt;
==Removing==&lt;br /&gt;
#Remove the entry from addons\amxmodx\configs\modules.ini by deleting it or prepending a semi-colon to comment it out.&lt;br /&gt;
#Delete any associated files if you don't need them.&lt;br /&gt;
&lt;br /&gt;
==Default Modules==&lt;br /&gt;
:{|&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| Module&lt;br /&gt;
| Purpose&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| fun_amxx&lt;br /&gt;
| General functions for changing game values.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| engine_amxx&lt;br /&gt;
| More advanced functions for getting and setting values in the HL engine.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| fakemeta_amxx&lt;br /&gt;
| Expert/advanced functions for manipulating, hooking, and calling functions in the HL engine.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| *sql_amxx&lt;br /&gt;
| SQL/Database scripting functions.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| geoip_amxx&lt;br /&gt;
| Functions for finding countries by IP address.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| array_amxx&lt;br /&gt;
| Functions for somewhat-dynamic arrays.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| sockets_amxx&lt;br /&gt;
| Functions for socket (TCP/UDP) control and manipulation.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| regex_amxx&lt;br /&gt;
| Functions for regular expression support.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=CVARs=&lt;br /&gt;
The base [[CVAR]]s AMX Mod X defines are located in amxmodx/configs/amxx.cfg.  You can edit these the same way you edit the server.cfg file:&lt;br /&gt;
:{|&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| CVAR&lt;br /&gt;
| Default Setting&lt;br /&gt;
| Purpose&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_default_access&lt;br /&gt;
| &amp;quot;z&amp;quot;&lt;br /&gt;
| Sets the default access level for non-admin players.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_password_field&lt;br /&gt;
| &amp;quot;_pw&amp;quot;&lt;br /&gt;
| Name of the setinfo key which a user should store their password in.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_mode&lt;br /&gt;
| 1&lt;br /&gt;
| Changes the mode of logging into a server:&amp;lt;br /&amp;gt;&lt;br /&gt;
0 - Disable logging, players won't be checked and no access will be given.&amp;lt;br /&amp;gt;&lt;br /&gt;
1 - Normal mode which obeys flags set in accounts.&amp;lt;br /&amp;gt;&lt;br /&gt;
2 - Kick all players not on the users list.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_show_activity&lt;br /&gt;
| 2&lt;br /&gt;
| Sets the mode of admin activity on the server:&amp;lt;br /&amp;gt;&lt;br /&gt;
0 - Disabled&amp;lt;br /&amp;gt;&lt;br /&gt;
1 - Show action anonymously&amp;lt;br /&amp;gt;&lt;br /&gt;
2 - Show action with the admin's name&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_scrollmsg&lt;br /&gt;
| &amp;quot;Welcome to %hostname% -- This server is using AMX Mod X&amp;quot; 600&lt;br /&gt;
| Sets the parameters (message and frequency) for a scrolling message.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_imessage&lt;br /&gt;
| &amp;quot;Welcome to %hostname&amp;quot; &amp;quot;000255100&amp;quot; &amp;lt;br /&amp;gt;&amp;quot;This server is using AMX Mod X\nVisit http://www.amxmodx.org&amp;quot; &amp;quot;00010025&amp;quot;&lt;br /&gt;
| Adds a center-typed colored message. The last parameter is in RRRGGGBBB format (red, green, blue).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_freq_imessage&lt;br /&gt;
| 180&lt;br /&gt;
| Frequency, in seconds, of the colored center messages.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_flood_time&lt;br /&gt;
| 0.75&lt;br /&gt;
| Chat flood prevention. Sets how fast a player can chat (in seconds).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_reservation&lt;br /&gt;
| 0&lt;br /&gt;
| Sets the amount of reserved slots.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_time_display&lt;br /&gt;
| &amp;quot;ab 1200&amp;quot; &amp;quot;ab 600&amp;quot; &amp;quot;ab 300&amp;quot; &amp;quot;ab 180&amp;quot; &amp;quot;ab 60&amp;quot; &amp;quot;bcde 11&amp;quot;&lt;br /&gt;
| Sets flags for remaining time display:&amp;lt;br /&amp;gt;&lt;br /&gt;
a - Display white text on bottom&amp;lt;br /&amp;gt;&lt;br /&gt;
b - Use voice&amp;lt;br /&amp;gt;&lt;br /&gt;
c - Don't add &amp;quot;remaining&amp;quot; in voice&amp;lt;br /&amp;gt;&lt;br /&gt;
d - Don't add &amp;quot;hours/minutes/seconds&amp;quot; in voice&amp;lt;br /&amp;gt;&lt;br /&gt;
e - Show/speak if current time is less than set in parameter&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_time_voice&lt;br /&gt;
| 1&lt;br /&gt;
| Sets whether to announce &amp;quot;say thetime&amp;quot; and &amp;quot;say timeleft&amp;quot; with voice.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_vote_delay&lt;br /&gt;
| 10&lt;br /&gt;
| Sets the minimum delay in seconds between two voting sessions.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_vote_time&lt;br /&gt;
| 10&lt;br /&gt;
| Sets how long a voting sessions lasts for.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_vote_answers&lt;br /&gt;
| 1&lt;br /&gt;
| Displays who votes for which options, publically.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_voteban_ratio&lt;br /&gt;
| 0.40&lt;br /&gt;
| Ratio for a ban vote to be successful.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_votekick_ratio&lt;br /&gt;
| 0.40&lt;br /&gt;
| Ratio for a kick vote to be successful.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_votemap_ratio&lt;br /&gt;
| 0.40&lt;br /&gt;
| Ratio for a map vote to be successful.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_vote_ratio&lt;br /&gt;
| 0.40&lt;br /&gt;
| Ratio for a general vote to be successful.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_extendmap_max&lt;br /&gt;
| 90&lt;br /&gt;
| Maximum time a mapvote can be extended.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_extendmap_step&lt;br /&gt;
| 15&lt;br /&gt;
| Amount of time a map extensions adds.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_client_languages&lt;br /&gt;
| 1&lt;br /&gt;
| Enables or disables the ability for clients to choose their own language.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_debug&lt;br /&gt;
| 1&lt;br /&gt;
| Sets the debug mode for plugins:&amp;lt;br /&amp;gt;&lt;br /&gt;
0 - No debugging (warning messages for plugin errors)&amp;lt;br /&amp;gt;&lt;br /&gt;
1 - Plugins with &amp;quot;debug&amp;quot; option in plugins.ini are put into debug mode.&amp;lt;br /&amp;gt;&lt;br /&gt;
2 - All plugins are put into debug mode (full backtraces for errors).&amp;lt;br /&amp;gt;&lt;br /&gt;
Note that debug mode greatly decreases JIT performance.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_mldebug&lt;br /&gt;
| 0&lt;br /&gt;
| Logs multi-lingual translation problems.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=SQL=&lt;br /&gt;
Make sure you have mysql_amxx enabled in AMX Mod X's amxmodx/configs/modules.ini file.  &lt;br /&gt;
&lt;br /&gt;
Then, open amxmodx/configs/sql.cfg and edit the cvars accordingly:&lt;br /&gt;
&lt;br /&gt;
:{|&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot; &lt;br /&gt;
| CVAR&lt;br /&gt;
| Default Setting&lt;br /&gt;
| Purpose&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_host&lt;br /&gt;
| &amp;quot;127.0.0.1&amp;quot;&lt;br /&gt;
| IP address of SQL server.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_user&lt;br /&gt;
| &amp;quot;root&amp;quot;&lt;br /&gt;
| Username to connect to the SQL server.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_pass&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Password to connect to the SQL server.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_db&lt;br /&gt;
| &amp;quot;amx&amp;quot;&lt;br /&gt;
| Database to use on the SQL server.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_table&lt;br /&gt;
| &amp;quot;admins&amp;quot;&lt;br /&gt;
| The table to use for the admin_sql plugin.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_type&lt;br /&gt;
| &amp;quot;mysql&amp;quot;&lt;br /&gt;
| The database type to connect to.&lt;br /&gt;
|}&lt;br /&gt;
*Note: amx_sql_type as of AMXX 1.75&lt;br /&gt;
&lt;br /&gt;
=Maps=&lt;br /&gt;
&lt;br /&gt;
==Map Cycle==&lt;br /&gt;
If you use the mapsmenu plugin, you can either use &amp;quot;maps.ini&amp;quot; or &amp;quot;mapcycle.txt&amp;quot; to manage map rotations.&lt;br /&gt;
&lt;br /&gt;
Delete &amp;quot;maps.ini&amp;quot; to use mapcycle.txt, otherwise, simply add a list of map names to maps.ini like so:&lt;br /&gt;
&amp;lt;pre&amp;gt;de_dust&lt;br /&gt;
cs_assault&lt;br /&gt;
de_aztec&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et cetera. &lt;br /&gt;
&lt;br /&gt;
==Map Specific Config Files==&lt;br /&gt;
For each map, you can also add a configuration file that will execute when the map loads. This is useful to set certain settings for 3rd party maps, say, removing the freeze time on fy_iceworld.&lt;br /&gt;
&lt;br /&gt;
To do this, simply create a folder in amxmodx/configs called &amp;quot;maps&amp;quot; and place a .cfg file named after the map with the settings in it, for example, you might have amxmodx/configs/maps/fy_iceworld.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mp_startmoney 16000&lt;br /&gt;
mp_freezetime 0&lt;br /&gt;
mp_timelimit 20&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Map Specific Plugins==&lt;br /&gt;
Each map can have a specific plugins.ini file for which it will load on map change.  &lt;br /&gt;
&lt;br /&gt;
The file is to be located at ''amxmodx/configs/maps/plugins-mapname.ini'' For example, for de_dust you would create the file '''amxmodx/configs/maps/plugins-de_dust.ini'''&lt;br /&gt;
&lt;br /&gt;
In addition, a plugin can be tagged as &amp;quot;''disabled''&amp;quot; which will prevent this plugin from being loaded.  You accomplish this the same way you tag a plugin as debug mode, by entering the word ''disabled'' after the plugin name in the file, which will prevent it from being loaded for that map.  &lt;br /&gt;
&lt;br /&gt;
For example, if you wanted the map de_dust to disable the plugin ''ham.amxx'' and enable the plugin ''pickle.amxx'' you would put this in ''amxmodx/configs/maps/plugins-de_dust.ini'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ham.amxx disabled&lt;br /&gt;
pickle.amxx&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This feature was added in [[AMX_Mod_X_1.76_Changes|AMX Mod X 1.76]]&lt;br /&gt;
&lt;br /&gt;
=Menus=&lt;br /&gt;
==Client Commands==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\clcmds.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Name&amp;quot; &amp;quot;Command&amp;quot; &amp;quot;Flags&amp;quot; &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | Name is the name that will appear on the menu.&amp;lt;br /&amp;gt;&lt;br /&gt;
Command is the format for the console command - you can use %userid% to insert the user's id.&amp;lt;br /&amp;gt;&lt;br /&gt;
Flags are one of the following:&amp;lt;br /&amp;gt;&lt;br /&gt;
  a - execute from server console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  b - execute from admin console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  c - execute on selected player.&amp;lt;br /&amp;gt;&lt;br /&gt;
  d - display menu again once done&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Slay player&amp;quot; &amp;quot;amx_slay #%userid%&amp;quot; &amp;quot;bd&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Commands==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\cmds.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Name&amp;quot; &amp;quot;Command&amp;quot; &amp;quot;Flags&amp;quot; &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | Name is the name that will appear on the menu.&amp;lt;br /&amp;gt;&lt;br /&gt;
Command is the format for the console command - you can use %userid% to insert the user's id.&amp;lt;br /&amp;gt;&lt;br /&gt;
Flags are one of the following:&amp;lt;br /&amp;gt;&lt;br /&gt;
  a - execute from server console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  b - execute from admin console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  c - execute on selected player.&amp;lt;br /&amp;gt;&lt;br /&gt;
  d - display menu again once done&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Pause&amp;quot; &amp;quot;amx_pause&amp;quot; &amp;quot;bd&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Configs==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\configs.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Name&amp;quot; &amp;quot;Command&amp;quot; &amp;quot;Flags&amp;quot; &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | Name is the name that will appear on the menu.&amp;lt;br /&amp;gt;&lt;br /&gt;
Command is the format for the console command.&lt;br /&gt;
Flags are one of the following:&amp;lt;br /&amp;gt;&lt;br /&gt;
  a - execute from server console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  b - execute from admin console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  d - display menu again once done&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;PUBLIC Settings&amp;quot; &amp;quot;servercfgfile server.cfg;exec server.cfg&amp;quot; &amp;quot;a&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==CVARs==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\cvars.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;CVAR&amp;quot; &amp;quot;Values&amp;quot; ... &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | CVAR - the CVAR's name&amp;lt;br /&amp;gt;&lt;br /&gt;
Values - list of space delimited, quotation enclosed values&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;mp_autoteambalance&amp;quot; &amp;quot;0&amp;quot; &amp;quot;1&amp;quot; &amp;quot;@&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Speech==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\speech.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Name&amp;quot; &amp;quot;Command&amp;quot; &amp;quot;Flags&amp;quot; &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | Name is the name that will appear on the menu.&amp;lt;br /&amp;gt;&lt;br /&gt;
Command is the format for the console command - you can use %userid% to insert the user's id.&amp;lt;br /&amp;gt;&lt;br /&gt;
Flags are one of the following:&amp;lt;br /&amp;gt;&lt;br /&gt;
  a - execute from server console&amp;lt;br /&amp;gt;&lt;br /&gt;
  b - execute from admin console&amp;lt;br /&amp;gt;&lt;br /&gt;
  c - execute on selected player&amp;lt;br /&amp;gt;&lt;br /&gt;
  d - display menu again once done&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Hello!&amp;quot; &amp;quot;spk \'vox/hello\'&amp;quot; &amp;quot;cd&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation (AMX Mod X)]]&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Configuring_AMX_Mod_X&amp;diff=3542</id>
		<title>Configuring AMX Mod X</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Configuring_AMX_Mod_X&amp;diff=3542"/>
		<updated>2006-12-10T07:47:03Z</updated>

		<summary type="html">&lt;p&gt;Sawce: /* Maps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Admins=&lt;br /&gt;
See the section on [[Adding Admins (AMX Mod X)|Adding Admins]] for more information.&lt;br /&gt;
&lt;br /&gt;
=Plugins=&lt;br /&gt;
==Installing==&lt;br /&gt;
Often, plugins will have their own directions if they need special installation requirements.  However, this will instruct you on the basics of adding a plugin.&lt;br /&gt;
#Follow any directions the plugin author has given you. If the plugin requires extra steps or special files, make sure you have them in the proper place and order.&lt;br /&gt;
#If you are given a .sma source file instead of a .amxx, you must compile the plugin yourself.  For more information, see [[Compiling Plugins (AMX Mod X)]].&lt;br /&gt;
#Place the plugin's .amxx file in the addons/amxmodx/plugins folder.&lt;br /&gt;
#Add the plugin's name to addons\amxmodx\configs\plugins.ini. Example: &amp;lt;pre&amp;gt;myplugin.amxx&amp;lt;/pre&amp;gt;&lt;br /&gt;
#Change map or restart the server. If the plugin has any load errors, see [[Troubleshooting AMX Mod X#Plugins|Troubleshooting AMX Mod X]].&lt;br /&gt;
&lt;br /&gt;
==Removing==&lt;br /&gt;
#Remove the entry from addons\amxmodx\configs\plugins.ini by deleting it or prepending a semi-colon to comment it out.&lt;br /&gt;
#Delete any associated files.&lt;br /&gt;
&lt;br /&gt;
==Default Plugins==&lt;br /&gt;
:{|&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| Plugin&lt;br /&gt;
| Purpose&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| admin.amxx&lt;br /&gt;
| Administration Base&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| admin_sql.amxx 	&lt;br /&gt;
| Administration Base for SQL. Use only one base.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| admincmd.amxx 	&lt;br /&gt;
| Basic administration commands (such as kick/slap).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| adminhelp.amxx 	&lt;br /&gt;
| Help for admin commands.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| adminslots.amxx 	&lt;br /&gt;
| Slot reservation.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| multilingual.amxx 	&lt;br /&gt;
| Multi-Lingual client configuration.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| menufront.amxx 	&lt;br /&gt;
| Front-end for admin menus.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| cmdmenu.amxx 	&lt;br /&gt;
| Command menu for settings.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| plmenu.amxx 	&lt;br /&gt;
| Player menu commands (kick, ban, etc).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| telemenu.amxx 	&lt;br /&gt;
| Teleport Menu (fun module required).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| mapsmenu.amxx 	&lt;br /&gt;
| Maps menu (vote, changeleve, etc).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| adminchat.amxx 	&lt;br /&gt;
| Console-based chat commands.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| antiflood.amxx 	&lt;br /&gt;
| Prevents clients from flooding the say chat.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| scrollmsg.amxx 	&lt;br /&gt;
| Displays a scrolling message.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| imessage.amxx 	&lt;br /&gt;
| Displays a centered, timed information message.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| adminvote.amxx 	&lt;br /&gt;
| Voting commands.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| nextmap.amxx 	&lt;br /&gt;
| Displays next map in the mapcycle.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| mapchooser.amxx &lt;br /&gt;
| Allows players to vote for the next map.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| timeleft.amxx 	&lt;br /&gt;
| Displays time left on the current map.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| pausecfg.amxx 	&lt;br /&gt;
| Allows pausing/unpausing of plugins.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| statscfg.amxx 	&lt;br /&gt;
| Configuration of statistical plugins.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Modules=&lt;br /&gt;
Modules add additional functionality for plugins to use.&lt;br /&gt;
==Installing==&lt;br /&gt;
#Figure out what operating system your server is: Windows, Linux, or Linux using AMD64 (64bit).&lt;br /&gt;
#If the module is 3rd party, download the module corresponding to your OS.  It will end in .dll for Windows, _i386.so for Linux, or _amd64.so for AMD64.&lt;br /&gt;
#Place the file in addons/amxmodx/modules/ and follow any additional instructions.&lt;br /&gt;
#If the module is already in addons/amxmodx/configs/modules.ini, remove the ';' next to its name to enable it.&lt;br /&gt;
#Otherwise, add the module's name to modules.ini. [[AMX Mod X]] supports generic notation, for example: &amp;lt;pre&amp;gt;mysql_amxx&amp;lt;/pre&amp;gt; ... will automatically detect the correct module to use.&lt;br /&gt;
#To see if the module is working, you can type &amp;lt;tt&amp;gt;amxx modules&amp;lt;/tt&amp;gt; in your [[server console]].&lt;br /&gt;
&lt;br /&gt;
==Removing==&lt;br /&gt;
#Remove the entry from addons\amxmodx\configs\modules.ini by deleting it or prepending a semi-colon to comment it out.&lt;br /&gt;
#Delete any associated files if you don't need them.&lt;br /&gt;
&lt;br /&gt;
==Default Modules==&lt;br /&gt;
:{|&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| Module&lt;br /&gt;
| Purpose&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| fun_amxx&lt;br /&gt;
| General functions for changing game values.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| engine_amxx&lt;br /&gt;
| More advanced functions for getting and setting values in the HL engine.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| fakemeta_amxx&lt;br /&gt;
| Expert/advanced functions for manipulating, hooking, and calling functions in the HL engine.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| *sql_amxx&lt;br /&gt;
| SQL/Database scripting functions.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| geoip_amxx&lt;br /&gt;
| Functions for finding countries by IP address.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| array_amxx&lt;br /&gt;
| Functions for somewhat-dynamic arrays.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| sockets_amxx&lt;br /&gt;
| Functions for socket (TCP/UDP) control and manipulation.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| regex_amxx&lt;br /&gt;
| Functions for regular expression support.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=CVARs=&lt;br /&gt;
The base [[CVAR]]s AMX Mod X defines are located in amxmodx/configs/amxx.cfg.  You can edit these the same way you edit the server.cfg file:&lt;br /&gt;
:{|&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot;&lt;br /&gt;
| CVAR&lt;br /&gt;
| Default Setting&lt;br /&gt;
| Purpose&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_default_access&lt;br /&gt;
| &amp;quot;z&amp;quot;&lt;br /&gt;
| Sets the default access level for non-admin players.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_password_field&lt;br /&gt;
| &amp;quot;_pw&amp;quot;&lt;br /&gt;
| Name of the setinfo key which a user should store their password in.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_mode&lt;br /&gt;
| 1&lt;br /&gt;
| Changes the mode of logging into a server:&amp;lt;br /&amp;gt;&lt;br /&gt;
0 - Disable logging, players won't be checked and no access will be given.&amp;lt;br /&amp;gt;&lt;br /&gt;
1 - Normal mode which obeys flags set in accounts.&amp;lt;br /&amp;gt;&lt;br /&gt;
2 - Kick all players not on the users list.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_show_activity&lt;br /&gt;
| 2&lt;br /&gt;
| Sets the mode of admin activity on the server:&amp;lt;br /&amp;gt;&lt;br /&gt;
0 - Disabled&amp;lt;br /&amp;gt;&lt;br /&gt;
1 - Show action anonymously&amp;lt;br /&amp;gt;&lt;br /&gt;
2 - Show action with the admin's name&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_scrollmsg&lt;br /&gt;
| &amp;quot;Welcome to %hostname% -- This server is using AMX Mod X&amp;quot; 600&lt;br /&gt;
| Sets the parameters (message and frequency) for a scrolling message.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_imessage&lt;br /&gt;
| &amp;quot;Welcome to %hostname&amp;quot; &amp;quot;000255100&amp;quot; &amp;lt;br /&amp;gt;&amp;quot;This server is using AMX Mod X\nVisit http://www.amxmodx.org&amp;quot; &amp;quot;00010025&amp;quot;&lt;br /&gt;
| Adds a center-typed colored message. The last parameter is in RRRGGGBBB format (red, green, blue).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_freq_imessage&lt;br /&gt;
| 180&lt;br /&gt;
| Frequency, in seconds, of the colored center messages.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_flood_time&lt;br /&gt;
| 0.75&lt;br /&gt;
| Chat flood prevention. Sets how fast a player can chat (in seconds).&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_reservation&lt;br /&gt;
| 0&lt;br /&gt;
| Sets the amount of reserved slots.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_time_display&lt;br /&gt;
| &amp;quot;ab 1200&amp;quot; &amp;quot;ab 600&amp;quot; &amp;quot;ab 300&amp;quot; &amp;quot;ab 180&amp;quot; &amp;quot;ab 60&amp;quot; &amp;quot;bcde 11&amp;quot;&lt;br /&gt;
| Sets flags for remaining time display:&amp;lt;br /&amp;gt;&lt;br /&gt;
a - Display white text on bottom&amp;lt;br /&amp;gt;&lt;br /&gt;
b - Use voice&amp;lt;br /&amp;gt;&lt;br /&gt;
c - Don't add &amp;quot;remaining&amp;quot; in voice&amp;lt;br /&amp;gt;&lt;br /&gt;
d - Don't add &amp;quot;hours/minutes/seconds&amp;quot; in voice&amp;lt;br /&amp;gt;&lt;br /&gt;
e - Show/speak if current time is less than set in parameter&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_time_voice&lt;br /&gt;
| 1&lt;br /&gt;
| Sets whether to announce &amp;quot;say thetime&amp;quot; and &amp;quot;say timeleft&amp;quot; with voice.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_vote_delay&lt;br /&gt;
| 10&lt;br /&gt;
| Sets the minimum delay in seconds between two voting sessions.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_vote_time&lt;br /&gt;
| 10&lt;br /&gt;
| Sets how long a voting sessions lasts for.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_vote_answers&lt;br /&gt;
| 1&lt;br /&gt;
| Displays who votes for which options, publically.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_voteban_ratio&lt;br /&gt;
| 0.40&lt;br /&gt;
| Ratio for a ban vote to be successful.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_votekick_ratio&lt;br /&gt;
| 0.40&lt;br /&gt;
| Ratio for a kick vote to be successful.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_votemap_ratio&lt;br /&gt;
| 0.40&lt;br /&gt;
| Ratio for a map vote to be successful.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_vote_ratio&lt;br /&gt;
| 0.40&lt;br /&gt;
| Ratio for a general vote to be successful.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_extendmap_max&lt;br /&gt;
| 90&lt;br /&gt;
| Maximum time a mapvote can be extended.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_extendmap_step&lt;br /&gt;
| 15&lt;br /&gt;
| Amount of time a map extensions adds.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_client_languages&lt;br /&gt;
| 1&lt;br /&gt;
| Enables or disables the ability for clients to choose their own language.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_debug&lt;br /&gt;
| 1&lt;br /&gt;
| Sets the debug mode for plugins:&amp;lt;br /&amp;gt;&lt;br /&gt;
0 - No debugging (warning messages for plugin errors)&amp;lt;br /&amp;gt;&lt;br /&gt;
1 - Plugins with &amp;quot;debug&amp;quot; option in plugins.ini are put into debug mode.&amp;lt;br /&amp;gt;&lt;br /&gt;
2 - All plugins are put into debug mode (full backtraces for errors).&amp;lt;br /&amp;gt;&lt;br /&gt;
Note that debug mode greatly decreases JIT performance.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_mldebug&lt;br /&gt;
| 0&lt;br /&gt;
| Logs multi-lingual translation problems.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=SQL=&lt;br /&gt;
Make sure you have mysql_amxx enabled in AMX Mod X's amxmodx/configs/modules.ini file.  &lt;br /&gt;
&lt;br /&gt;
Then, open amxmodx/configs/sql.cfg and edit the cvars accordingly:&lt;br /&gt;
&lt;br /&gt;
:{|&lt;br /&gt;
|- class=&amp;quot;t2th&amp;quot; &lt;br /&gt;
| CVAR&lt;br /&gt;
| Default Setting&lt;br /&gt;
| Purpose&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_host&lt;br /&gt;
| &amp;quot;127.0.0.1&amp;quot;&lt;br /&gt;
| IP address of SQL server.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_user&lt;br /&gt;
| &amp;quot;root&amp;quot;&lt;br /&gt;
| Username to connect to the SQL server.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_pass&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Password to connect to the SQL server.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_db&lt;br /&gt;
| &amp;quot;amx&amp;quot;&lt;br /&gt;
| Database to use on the SQL server.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_table&lt;br /&gt;
| &amp;quot;admins&amp;quot;&lt;br /&gt;
| The table to use for the admin_sql plugin.&lt;br /&gt;
|- class=&amp;quot;t2td&amp;quot;&lt;br /&gt;
| amx_sql_type&lt;br /&gt;
| &amp;quot;mysql&amp;quot;&lt;br /&gt;
| The database type to connect to.&lt;br /&gt;
|}&lt;br /&gt;
*Note: amx_sql_type as of AMXX 1.75&lt;br /&gt;
&lt;br /&gt;
=Maps=&lt;br /&gt;
&lt;br /&gt;
==Map Cycle==&lt;br /&gt;
If you use the mapsmenu plugin, you can either use &amp;quot;maps.ini&amp;quot; or &amp;quot;mapcycle.txt&amp;quot; to manage map rotations.&lt;br /&gt;
&lt;br /&gt;
Delete &amp;quot;maps.ini&amp;quot; to use mapcycle.txt, otherwise, simply add a list of map names to maps.ini like so:&lt;br /&gt;
&amp;lt;pre&amp;gt;de_dust&lt;br /&gt;
cs_assault&lt;br /&gt;
de_aztec&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et cetera. &lt;br /&gt;
&lt;br /&gt;
==Map Specific Config Files==&lt;br /&gt;
For each map, you can also add a configuration file that will execute when the map loads. This is useful to set certain settings for 3rd party maps, say, removing the freeze time on fy_iceworld.&lt;br /&gt;
&lt;br /&gt;
To do this, simply create a folder in amxmodx/configs called &amp;quot;maps&amp;quot; and place a .cfg file named after the map with the settings in it, for example, you might have amxmodx/configs/maps/fy_iceworld.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mp_startmoney 16000&lt;br /&gt;
mp_freezetime 0&lt;br /&gt;
mp_timelimit 20&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Map Specific Plugins==&lt;br /&gt;
Each map can have a specific plugins.ini file for which it will load on map change.  &lt;br /&gt;
&lt;br /&gt;
The file is to be located at ''amxmodx/configs/maps/plugins-mapname.ini'' For example, for de_dust you would create the file '''amxmodx/configs/maps/plugins-de_dust.ini'''&lt;br /&gt;
&lt;br /&gt;
In addition, a plugin can be tagged as &amp;quot;''disabled''&amp;quot; which will prevent this plugin from being loaded.  You accomplish this the same way you tag a plugin as debug mode, by entering the word ''disabled'' after the plugin name in the file, which will prevent it from being loaded for that map.  &lt;br /&gt;
&lt;br /&gt;
For example, if you wanted the map de_dust to disable the plugin ''ham.amxx'' and enable the plugin ''pickle.amxx'' you would put this in ''amxmodx/configs/maps/plugins-de_dust.ini'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ham.amxx disabled&lt;br /&gt;
pickle.amxx&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Menus=&lt;br /&gt;
==Client Commands==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\clcmds.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Name&amp;quot; &amp;quot;Command&amp;quot; &amp;quot;Flags&amp;quot; &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | Name is the name that will appear on the menu.&amp;lt;br /&amp;gt;&lt;br /&gt;
Command is the format for the console command - you can use %userid% to insert the user's id.&amp;lt;br /&amp;gt;&lt;br /&gt;
Flags are one of the following:&amp;lt;br /&amp;gt;&lt;br /&gt;
  a - execute from server console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  b - execute from admin console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  c - execute on selected player.&amp;lt;br /&amp;gt;&lt;br /&gt;
  d - display menu again once done&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Slay player&amp;quot; &amp;quot;amx_slay #%userid%&amp;quot; &amp;quot;bd&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Commands==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\cmds.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Name&amp;quot; &amp;quot;Command&amp;quot; &amp;quot;Flags&amp;quot; &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | Name is the name that will appear on the menu.&amp;lt;br /&amp;gt;&lt;br /&gt;
Command is the format for the console command - you can use %userid% to insert the user's id.&amp;lt;br /&amp;gt;&lt;br /&gt;
Flags are one of the following:&amp;lt;br /&amp;gt;&lt;br /&gt;
  a - execute from server console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  b - execute from admin console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  c - execute on selected player.&amp;lt;br /&amp;gt;&lt;br /&gt;
  d - display menu again once done&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Pause&amp;quot; &amp;quot;amx_pause&amp;quot; &amp;quot;bd&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Configs==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\configs.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Name&amp;quot; &amp;quot;Command&amp;quot; &amp;quot;Flags&amp;quot; &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | Name is the name that will appear on the menu.&amp;lt;br /&amp;gt;&lt;br /&gt;
Command is the format for the console command.&lt;br /&gt;
Flags are one of the following:&amp;lt;br /&amp;gt;&lt;br /&gt;
  a - execute from server console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  b - execute from admin console.&amp;lt;br /&amp;gt;&lt;br /&gt;
  d - display menu again once done&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;PUBLIC Settings&amp;quot; &amp;quot;servercfgfile server.cfg;exec server.cfg&amp;quot; &amp;quot;a&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==CVARs==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\cvars.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;CVAR&amp;quot; &amp;quot;Values&amp;quot; ... &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | CVAR - the CVAR's name&amp;lt;br /&amp;gt;&lt;br /&gt;
Values - list of space delimited, quotation enclosed values&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;mp_autoteambalance&amp;quot; &amp;quot;0&amp;quot; &amp;quot;1&amp;quot; &amp;quot;@&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Speech==&lt;br /&gt;
:{|&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | File:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | addons\amxmodx\configs\speech.ini&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Format: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Name&amp;quot; &amp;quot;Command&amp;quot; &amp;quot;Flags&amp;quot; &amp;quot;Access Level&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Options:&lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | Name is the name that will appear on the menu.&amp;lt;br /&amp;gt;&lt;br /&gt;
Command is the format for the console command - you can use %userid% to insert the user's id.&amp;lt;br /&amp;gt;&lt;br /&gt;
Flags are one of the following:&amp;lt;br /&amp;gt;&lt;br /&gt;
  a - execute from server console&amp;lt;br /&amp;gt;&lt;br /&gt;
  b - execute from admin console&amp;lt;br /&amp;gt;&lt;br /&gt;
  c - execute on selected player&amp;lt;br /&amp;gt;&lt;br /&gt;
  d - display menu again once done&lt;br /&gt;
|-&lt;br /&gt;
| class=&amp;quot;t2th&amp;quot; | Example: &lt;br /&gt;
| class=&amp;quot;t2td&amp;quot; | &amp;quot;Hello!&amp;quot; &amp;quot;spk \'vox/hello\'&amp;quot; &amp;quot;cd&amp;quot; &amp;quot;u&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation (AMX Mod X)]]&lt;/div&gt;</summary>
		<author><name>Sawce</name></author>
		
	</entry>
</feed>