<html>
<head>
<title>ETPub Lua API Documentation</title>
<style type="text/css">
dt {
        font-weight: bold;
}

body {
    font: x-small sans-serif;
    color: black;
}

h1, h2, h3, h4, h5, h6 {
    color: black;
    background: none;
    font-weight: normal;
    margin: 0;
    padding-top: .5em;
    padding-bottom: .17em;
    border-bottom: 1px solid #aaa;
}
h1 { font-size: 188%; }
h2 { font-size: 150%; }

h3, h4, h5, h6 {
    border-bottom: none;
    font-weight: bold;
}
h3 { font-size: 132%; }
h4 { font-size: 116%; }
h5 { font-size: 100%; }
h6 {
	font-size: 80%;
	color: #2f6fab;
	margin-left: .5em;
	margin-top: 20px;
}

b {
	font-weight: normal;
	color: #b00;
}

i.diff {
	border-bottom: 1px dashed #b00;
}

pre {
	font-size: 9pt;
	margin-top: 0;
    padding: 1em;
    border: 1px dashed #2f6fab;
    color: black;
    background-color: #f9f9f9;
    line-height: 1.1em;
	margin-bottom: 20px;
}

table.border {
	margin-top: 0;
	padding: 1em;
	border: 1px dashed #2f6fab;
	color: black;
	background-color: #f9f9f9;
	line-height: 1.1em;
	margin-bottom: 20px;
}

.list th {
	font-family: monospace;
	font-size: 9pt;
	color: white;
	padding: 0px 10px;
	text-align: left;
}

.list td {
	font-family: monospace;
	font-size: 9pt;
	padding: 0px 10px;
	color: black;
}
</style>
</head>
<body>
<h2>ETPUB LUA API DOCUMENTATION</h2>
<p>etpub's Lua API is aiming to be fully compatible to etpro's Lua API. Differences between etpub's and etpro's Lua API are described in this documentation.</p>
<p><b>*</b><i class="diff">Marks differences between etpub's and etpro's Lua API</i></p>

<a name="commands"></a><h2>LUA RESOURCES</h2>

<ul>
	<li>The Programming Language Lua: <a href="http://www.lua.org/">http://www.lua.org/</a></li>
	<li>etpro's Lua API documentation: <a href="http://wolfwiki.anime.net/index.php/Lua_Mod_API">http://wolfwiki.anime.net/index.php/Lua_Mod_API</a></li>
</ul>

<a name="commands"></a><h2>COMMANDS</h2>

<a name="client_commands"></a><h3>Client Commands</h3>
<a name="lua_status"></a><p><strong>lua_status</strong></p>
<dl>
	<dd>Lists all currently loaded lua modules.</dd>
	<dd>&nbsp;</dd>
	<dd><i>Lua modules cannot override this client command.</i></dd>
</dl>

<a name="server_commands"></a><h3>Server Commands</h3>
<a name="lua_status2"></a><p><strong>lua_status</strong></p>
<dl>
	<dd>Lists all currently loaded lua modules.</dd>
</dl>

<a name="cvars"></a><h2>CVARS</h2>

<a name="server_cvars"></a><h3>Server Cvars</h3>
<a name="lua_modules"></a><p><strong>lua_modules</strong></p>
<dl>
	<dd>Space separated list of lua modules for ETPub to load. Modules will be run in the order listed.</dd>
	<dd>&nbsp;</dd>
	<dd><i>Default is "" (Disabled)</i></dd>
</dl>

<a name="lua_allowedmodules"></a><p><strong>lua_allowedModules</strong></p>
<dl>
	<dd>If set, only lua modules with the matching sha1 signatures listed in this cvar will be allowed to load.</dd>
	<dd>&nbsp;</dd>
	<dd><i>Default is "" (Disabled)</i></dd>
</dl>

<p>Changing either cvar will cause all currently loaded modules to quit and be unloaded until the next <i>map_restart</i>, <i>reset_match</i> or map change.</p>

<a name="et_library_calls"></a><h2>ET LIBRARY CALLS</h2>

<a name="clients"></a><h3>Clients</h3>
<p><p><b>*</b><i class="diff"><strong>clientnum</strong> = et.G_ClientNumberFromString( <strong>string</strong> )</i></p>
<dl>
	<dd>Searches for one partial match with <strong>string</strong>. If one is found the <strong>clientnum</strong> is returned. If there is none or more than one match <strong>-1</strong> is returned.</dd>
	<dd><h6>LUA CODE EXAMPLE</h6><pre>-- get number from client with partial name match 'ETPla'
clientnum = et.G_ClientNumberFromString("ETPla")</pre></dd>
</dl>

<a name="et_filesystem"></a><h3>ET Filesystem</h3>
<p><strong>fd</strong>, <strong>len</strong> = et.trap_FS_FOpenFile( <strong>filename</strong>, <strong>mode</strong> )</p>
<dl>
	<dd>Attempts to open the file <strong>filename</strong> with the access mode <strong>mode</strong> (see <a href="#predefined_constants">et.FS_* constants</a>). Returns the filedescriptor <strong>fd</strong> and file length <strong>len</strong>. On error, <strong>len</strong> returns -1.</dd>
	<dd><h6>LUA CODE EXAMPLE</h6><pre>fd, len = et.trap_FS_FOpenFile("mymodule.log", et.FS_READ)</pre></dd>
</dl>
<p><strong>filedata</strong> = et.trap_FS_Read( <strong>fd</strong>, <strong>count</strong> )</p>
<dl>
	<dd>Reads <strong>count</strong> bytes from filedescriptor <strong>fd</strong>.</dd>
	<dd><h6>LUA CODE EXAMPLE</h6><pre>fd, len = et.trap_FS_FOpenFile("mymodule.log", et.FS_READ)

if len ~= -1 then
	filedata = et.trap_FS_Read(fd, len)
end

et.trap_FS_FCloseFile(fd)</pre></dd>
</dl>
<p><strong>count</strong> = et.trap_FS_Write( <strong>filedata</strong>, <strong>count</strong>, <strong>fd</strong> )</p>
<dl>
	<dd>Attempts to write <strong>count</strong> bytes of <strong>filedata</strong> to filedescriptor <strong>fd</strong>. Returns number of bytes (<strong>count</strong>) successfully written.</dd>
	<dd><h6>LUA CODE EXAMPLE</h6><pre>fd, len = et.trap_FS_FOpenFile("mymodule.log", et.FS_APPEND)
content = "MODEVENT: X Y: Player X does something with player Y.\n"

if len ~= -1 then
	count = et.trap_FS_Write(content, string.len(content), fd)
end

et.trap_FS_FCloseFile(fd)</pre></dd>
</dl>
<p>et.trap_FS_Rename( <strong>oldname</strong>, <strong>newname</strong> )</p>
<dl>
	<dd>Renames file <strong>oldname</strong> to <strong>newname</strong>.</dd>
	<dd><h6>LUA CODE EXAMPLE</h6><pre>et.trap_FS_Rename("mymodule.log", "mymodule.bak")</pre></dd>
</dl>
<p>et.trap_FS_FCloseFile( <strong>fd</strong> )</p>
<dl>
	<dd>Closes filedescriptor <strong>fd</strong>.</dd>
	<dd><h6>LUA CODE EXAMPLE</h6><pre>fd, len = et.trap_FS_FOpenFile("mymodule.log", et.FS_READ)

-- read file content here

et.trap_FS_FCloseFile(fd)</pre></dd>
</dl>

<a name="sound"></a><h3>Sound</h3>
<p><p><b>*</b><i class="diff">et.G_ClientSound( <strong>clientnum</strong>, <strong>soundindex</strong> )</i></p>
<dl>
	<dd>Plays the sound <strong>soundindex</strong> for the client with <strong>clientnum</strong> only.</dd>
	<dd><h6>LUA CODE EXAMPLE</h6><pre>-- play a sound for client #3 only
soundindex = et.G_SoundIndex("sound/world/alarm_01.wav")
et.G_ClientSound(3, soundindex)</pre></dd>
</dl>

<a name="miscellaneous"></a><h3>Miscellaneous</h3>
<p><strong>milliseconds</strong> = et.trap_Milliseconds()</p>
<dl>
	<dd>Returns a number (<strong>milliseconds</strong>) indicating the current server time in milliseconds.</dd>
	<dd><h6>LUA CODE EXAMPLE</h6><pre>milliseconds = et.trap_Milliseconds()</pre></dd>
</dl>
<p>et.G_Damage( <strong>target</strong>, <strong>inflictor</strong>, <strong>attacker</strong>, <strong>damage</strong>, <strong>dflags</strong>, <strong>mod</strong> )</p>
<dl>
	<dd>Does amount of <strong>damage</strong> on <strong>target</strong> inflicted by <strong>inflictor</strong> and cased by <strong>attacker</strong>.</dd>
	<dd>&nbsp;</dd>
	<dd>- <strong>target</strong>, <strong>inflictor</strong> and <strong>attacker</strong> are entity numbers.</dd>
	<dd>- <strong>dflags</strong> is a bitflag number to decide how the damage is inflicted.</dd>
	<dd>- <strong>mod</strong> is a number from 0 up to <b>*</b><i class="diff">69</i> to set the type of damage.</dd>
	<dd>&nbsp;</dd>
	<dd>Damage flags are bitflags with the following available bits.</dd>
	<dd><h6>DFLAGS AVAILABLE BITS</h6>
	<table class="border">
	<tr><td>
		<table border='0' class="list">
			<tr bgcolor='#888888'><th width="50">Bit</th><th width="200">Type</th><th>Description</th></tr>
			<tr><td>1</td><td>DAMAGE_RADIUS</td><td>damage was indirect</td></tr>
			<tr bgcolor="#d7d7d7"><td>2</td><td>DAMAGE_HALF_KNOCKBACK</td><td>do less knockback</td></tr>
			<tr><td>8</td><td>DAMAGE_NO_KNOCKBACK</td><td>do not affect velocity, just view angles</td></tr>
			<tr bgcolor="#d7d7d7"><td>16</td><td>DAMAGE_NO_TEAM_PROTECTION</td><td>armor, shields, invulnerability, and godmode have no effect</td></tr>
			<tr><td>32</td><td>DAMAGE_NO_PROTECTION</td><td>armor, shields, invulnerability, and godmode have no effect</td></tr>
			<tr bgcolor="#d7d7d7"><td>64</td><td>DAMAGE_DISTANCEFALLOFF</td><td>distance falloff</td></tr>
		</table>
		</td></tr>
	</table>
	</dd>
	<dd><h6>LUA CODE EXAMPLE</h6><pre>-- do 50 damage with no protection (dflags = 32) on client #0
-- with MOD_UNKNOWN (mod = 0) as &lt;world&gt; entity (inflictor, attacker = 1022)
et.G_Damage(0, 1022, 1022, 50, 32, 0)</pre></dd>
</dl>

<p><b>*</b><i class="diff"><strong>flooding</strong> = et.ClientIsFlooding( <strong>clientnum</strong> )</i></p>
<dl>
	<dd>Checks if client <strong>clientnum</strong> is <strong>flooding</strong> (1) or not (0).</dd>
	<dd>&nbsp;</dd>
	<dd>Note: There will be done no update to the flood protect behaviour on running this library call. ETPub only checks on <i>callvote</i>, <i>say</i>, <i>m</i>, <i>mt</i>, <i>ma</i>, <i>say_team</i>, <i>vsay</i>, <i>vsay_team</i>, <i>say_buddy</i>, <i>vsay_buddy</i>, <i>fireteam</i>, <i>rconAuth</i>, <i>ready</i>, <i>say_teamnl</i>, <i>specinvite</i>, <i>readyteam</i> client commands for flooding.</dd>
	<dd><h6>LUA CODE EXAMPLE</h6><pre>if et.ClientIsFlooding(clientnum) == 1 then
	-- client is flooding, do something
end</pre></dd>
</dl>
<p><b>*</b><i class="diff">et.G_AddSkillPoints( <strong>ent</strong>, <strong>skill</strong>, <strong>points</strong> )</i></p>
<dl>
	<dd>Note: To remove skill points you can also use negative <strong>points</strong> values.</dd>
	<dd><h6>LUA CODE EXAMPLE</h6><pre>-- add 100.5 points to heavy weapons skill (skill = 5) of client #0
et.G_AddSkillPoints(0, 5, 100.5)</pre></dd>
</dl>
<p><b>*</b><i class="diff">et.G_LoseSkillPoints( <strong>ent</strong>, <strong>skill</strong>, <strong>points</strong> )</i></p>
<dl>
	<dd><h6>LUA CODE EXAMPLE</h6><pre>-- remove 100.5 points from heavy weapons skill (skill = 5) of client #0
et.G_LoseSkillPoints(0, 5, 100.5)</pre></dd>
</dl>

<a name="entities"></a><h3>Entities</h3>
<p><strong>(variable)</strong> = et.gentity_get ( <strong>entnum</strong>, <strong>fieldname</strong><i>, <strong>arrayindex</strong></i> )</p>
<dl>
	<dd>Gets the value of <strong>fieldname</strong> from entity <strong>entnum</strong> out of the g_entity struct. For NULL entities, <i>nil</i> is returned.</dd>
	<dd><i><strong>arrayindex</strong></i> is used to specify which element of an array entity field to get. It is required when accessing array type fields. Entity field array indexes start at 0.</dd>
</dl>
<p>et.gentity_set( <strong>entnum</strong>, <strong>fieldname</strong><i>, <strong>arrayindex</strong></i>, <strong>value</strong> )</p>
<dl>
	<dd>Sets the value of <strong>fieldname</strong> from entity <strong>entnum</strong> in the g_entity struct to <strong>value</strong>.</dd>
	<dd><i><strong>arrayindex</strong></i> is used to specify which element of an array entity field to set.</dd>
</dl>

<a name="shrubbot"></a><h3>Shrubbot</h3>
<p><b>*</b><i class="diff"><strong>permission</strong> = et.G_shrubbot_permission( <strong>ent</strong>, <strong>flag</strong> )</i></p>
<dl>
	<dd>Checks if client <strong>ent</strong> has <strong>permission</strong> (1) for <strong>flag</strong> or not (0).</dd>
	<dd>&nbsp;</dd>
	<dd>Note: Use <i>nil</i> or <i>-1</i> to check permission for console (Console always returns 1!).</dd>
	<dd><h6>LUA CODE EXAMPLE</h6><pre>-- check if client #1 has permission for flag "C"
if et.G_shrubbot_permission(1, "C") == 1 then
	-- client has permission, do something
end</pre></dd>
</dl>
<p><b>*</b><i class="diff"><strong>level</strong> = et.G_shrubbot_level( <strong>ent</strong> )</i></p>
<dl>
	<dd>Returns the <strong>level</strong> for client <strong>ent</strong>.</dd>
	<dd>&nbsp;</dd>
	<dd>Note: Use <i>nil</i> or <i>-1</i> to get the level for console.</dd>
	<dd><h6>LUA CODE EXAMPLE</h6><pre>-- get shrubbot level for client #2
level = et.G_shrubbot_level(2)</pre></dd>
</dl>

<a name="callbacks"></a><h2>CALLBACKS</h2>

<a name="qagame_execution"></a><h3>qagame Execution</h3>

<a name="client_management"></a><h3>Client Management</h3>
<p>et_ClientSpawn( <strong>clientNum</strong>, <strong>revived</strong>, <b>*</b><i class="diff"><strong>teamChange</strong></i>, <b>*</b><i class="diff"><strong>restoreHealth</strong></i> )</p>
<!--<dl>
	<dd>Called when a client is spawned. <b>clientNum</b> is the client slot id. <b>revived</b> is 1 if the client was spawned by being revived.</dd>
</dl>-->

<a name="commands"></a><h3>Commands</h3>
<p><strong>intercepted</strong> = et_ClientCommand( <strong>clientNum</strong>, <strong>command</strong> )</p>
<!--<dl>
	<dd>Called when a command is received from a client. <b>clientNum</b> is the client slot id. <b>command</b> is the command. The mod should return 1 if the command was intercepted by the mod, and 0 if the command was ignored by the mod and should be passed through to the server (and other mods in the chain).</dd>
	<dd>The actual command can be accessed through the <a href="#argument_handling" title="">argument handling</a> functions, as seen in the <a href="/index.php/ETPro:Lua_Sample_Code" title="ETPro:Lua Sample Code">ETPro:Lua Sample Code</a>.</dd>
</dl>-->
<p><strong>intercepted</strong> = et_ConsoleCommand( <b>*</b><i class="diff"><strong>command</strong></i> )</p>
<!--<dl>
	<dd>Called when a command is entered on the server console. The mod should return 1 if the command was intercepted by the mod, and 0 if the command was ignored by the mod and should be passed through to the server (and other mods in the chain).</dd>
	<dd>The actual command can be accessed through the <a href="#argument_handling" title="">argument handling</a> functions, as seen in the <a href="/index.php/ETPro:Lua_Sample_Code" title="ETPro:Lua Sample Code">ETPro:Lua Sample Code</a>.</dd>
</dl>-->

<a name="miscellaneous2"></a><h3>Miscellaneous</h3>
<p>(<strong>customObit</strong>) = et_Obituary( <strong>victim</strong>, <strong>killer</strong>, <strong>meansOfDeath</strong> )</p>
<dl>
	<dd>Called whenever a player is killed. <b>*</b><i class="diff">Modules should return a string (<strong>customObit</strong>) to override the default obituary or <strong>nil</strong> to leave it as it is.</i></dd>
	<dd><h6>LUA CODE EXAMPLE</h6><pre>function et_Obituary(victim, killer, meansOfDeath)
	if victim == killer and meansOfDeath == 26 then
		customObit = "%s ^7had an ^1EXPLOSIVE ^7relationship with his dynamite."
		return string.format(customObit, et.gentity_get(victim, "pers.netname"))
	end
end</pre></dd>
</dl>

<a name="predefined_constants"></a><h2>PREDEFINED CONSTANTS</h2>
<p><b>*</b><i class="diff">et.CS_PLAYERS</i><br />
et.EXEC_NOW<br />
et.EXEC_INSERT<br />
et.EXEC_APPEND<br />
et.FS_READ<br />
et.FS_WRITE<br />
et.FS_APPEND<br />
et.FS_APPEND_SYNC<br />
et.SAY_ALL<br />
et.SAY_TEAM<br />
et.SAY_BUDDY<br />
et.SAY_TEAMNL<br />
<br />
et.HOSTARCH</p>
<dl>
	<dd>Set to WIN32 or UNIX depending on the host architecture qagame is running on.</dd>
</dl>
<p><b>*</b><i class="diff">LUA_PATH</i></p>
<dl>
	<dd>Set to <i>fs_homepath/fs_game/?.lua;fs_homepath/fs_game/lualibs/?.lua</i> in order to ease use of the <a href="http://www.lua.org/pil/8.1.html" title="http://www.lua.org/pil/8.1.html" rel="nofollow" target="_blank">require</a> function. Depending on the configuration <i>fs_basepath/fs_game/?.lua;fs_basepath/fs_game/lualibs/?.lua</i> will be added to the LUA_PATH.</dd>
</dl>
<p><b>*</b><i class="diff">LUA_CPATH</i></p>
<dl>
	<dd>Set to <i>fs_homepath/fs_game/lualibs/?.(so|dll)</i> in order to ease use of the <a href="http://www.lua.org/pil/8.1.html" title="http://www.lua.org/pil/8.1.html" rel="nofollow" target="_blank">require</a> function. Depending on the configuration <i>fs_basepath/fs_game/lualibs/?.(so|dll)</i> will be added to the LUA_CPATH.</dd>
</dl>
<p><b>*</b><i class="diff">LUA_DIRSEP</i></p>
<dl>
	<dd>Set to \ or / depending on the host architecture qagame is running on.</dd>
</dl>

<a name="config"></a><h2>CONFIG</h2>

<p>&nbsp;</p>

<a name="et_variable_types"></a><h2>ET VARIABLE TYPES</h2>

<a name="vec3"></a><h3>vec3</h3>
<dl>
	<dd>A <strong>vec3</strong> is a 3-element array of numbers. It is usually used to store and
	process coordinates in 3D space. In lua a vector is an array (table indexed by integers)
	containing 3 numbers. It can be accessed by doing:</dd>
	<dd><h6>LUA CODE EXAMPLE</h6><pre>origin = et.gentity_get(entNum, "origin")
x, y, z = origin[1], origin[2], origin[3]</pre></dd>
</dl>

<a name="trajectory"></a><h3>trajectory</h3>
<dl>
	<dd>A