<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wolfwiki.anime.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Major+Zeman</id>
	<title>WolfWiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wolfwiki.anime.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Major+Zeman"/>
	<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php/Special:Contributions/Major_Zeman"/>
	<updated>2026-11-08T12:37:01Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.11</generator>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2968</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2968"/>
		<updated>2009-01-16T17:29:55Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: /* Drawbacks */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently found at [http://acidrainclan.all-forum.net/ acidrainclan.all-forum.net] or at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the function returns short version of guid and should NOT be used for authentication purposes!&lt;br /&gt;
&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s IP ===&lt;br /&gt;
Anoter simple function, this one returns IP of the player in given slot.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the IP, too, can be spoofed. Use [[User:ReyalP|ReyalP]]&#039;s userinfocheck.lua or better his combinedfixes.lua mod on your server to at least lower this risk.&lt;br /&gt;
&lt;br /&gt;
 -- gets target&#039;s IP without port&lt;br /&gt;
 function getIP(target)&lt;br /&gt;
     if (target == nil) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo(target)&lt;br /&gt;
     local ip = et.Info_ValueForKey(userinfo, &amp;quot;ip&amp;quot;)&lt;br /&gt;
     -- strip port&lt;br /&gt;
     ip = string.sub(ip,string.find(ip,&amp;quot;(%d+%.%d+%.%d+%.%d+)&amp;quot;))&lt;br /&gt;
     return ip&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s ref status ===&lt;br /&gt;
Third function is used to check whether the target client is logged in as referee.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; It&#039;s not very well known fact that there are actually three levels of referee status: client can either not be referee at all, or be a referee that was voted in or made referee by another referee, and a referee that logged in using referee password. This function however only discriminates between the ordinary levels of &amp;quot;not referee&amp;quot; - &amp;quot;referee&amp;quot; (e.g. doesn&#039;t make difference between the two types of referees).&lt;br /&gt;
&lt;br /&gt;
 -- returns referee status of target&lt;br /&gt;
 function getRefStatus(target)&lt;br /&gt;
       local isref = et.Info_ValueForKey(et.trap_GetConfigstring(et.CS_PLAYERS + target), &amp;quot;ref&amp;quot;)&lt;br /&gt;
       if isref ~= &amp;quot;0&amp;quot; then&lt;br /&gt;
           return true&lt;br /&gt;
     else&lt;br /&gt;
         return false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Indent ===&lt;br /&gt;
Another simple function. This one is useful if you need to print a list of basically anything and want the text to be arranged in columns.&lt;br /&gt;
&lt;br /&gt;
 -- makes a string at least &amp;lt;length&amp;gt; characters long, adding spaces behind the original string if needed&lt;br /&gt;
 function indent(str, length)&lt;br /&gt;
     local len&lt;br /&gt;
 &lt;br /&gt;
     len = math.min(string.len(str), length)&lt;br /&gt;
     str = str .. string.rep(&amp;quot; &amp;quot;, length - len)&lt;br /&gt;
 &lt;br /&gt;
     return str&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Note that it never shortens the text so you might end up with a garbled table anyways, but if you set the length to a reasonable number (e.g. 15 for IP - it&#039;s max length IPv4 can have), you should be fine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read content of a text file on server ===&lt;br /&gt;
This function reads contents of a given file and returns an array of its lines. It can handle all line endings (win|unix|mac). As a price for that though, it will eat up any empty lines.&lt;br /&gt;
&lt;br /&gt;
 -- reads file and returns string array of rows (indexed from 1) and number of rows&lt;br /&gt;
 function readFile(filename)&lt;br /&gt;
     local fd, len&lt;br /&gt;
     local rows = {}&lt;br /&gt;
 &lt;br /&gt;
     fd, len = et.trap_FS_FOpenFile(filename, et.FS_READ)&lt;br /&gt;
 &lt;br /&gt;
     if len == -1 then&lt;br /&gt;
         return rows, 0&lt;br /&gt;
     else&lt;br /&gt;
         --read it all&lt;br /&gt;
         local filestr = et.trap_FS_Read(fd, len)&lt;br /&gt;
 &lt;br /&gt;
         local rowcount = 0&lt;br /&gt;
         for line in string.gfind(filestr, &amp;quot;[^\r\n]+&amp;quot;) do&lt;br /&gt;
             rowcount = rowcount + 1&lt;br /&gt;
             rows[rowcount] = line&lt;br /&gt;
         end&lt;br /&gt;
 &lt;br /&gt;
             et.trap_FS_FCloseFile(fd)&lt;br /&gt;
             return rows, rowcount&lt;br /&gt;
       end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and optionally a client number. If it received client number, it prints the message to that client, if it received null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in ClientCommand trap:&lt;br /&gt;
&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;re passing the command to ET&lt;br /&gt;
&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.7 &amp;lt;small&amp;gt;(changelog is inside lua script)&amp;lt;/small&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 20.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that mod and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop moving upon load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and servers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== RefMon ==&lt;br /&gt;
version: 0.2&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 8.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/refmon.lua lua] (requires [http://www.sonic.net/~rfm/et/lua/etconst.lua etconst.lua])]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Referee Monitor mod - a lua script that logs all ref commands to a separate, easy to read log.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Referee monitor writes a log record for any ref command issued by either client or server console. The log contains these columns:&lt;br /&gt;
* date and time (in server&#039;s timezone)&lt;br /&gt;
* IP of the client who issued the command (empty for server commands, note that IP can be spoofed)&lt;br /&gt;
* name of the client who issued the command (or [console])&lt;br /&gt;
* flag - for easy orientation in the log, R means the player was logged in as ref, C means console command, empty otherwise&lt;br /&gt;
* command issued&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Server console command ===&lt;br /&gt;
* &#039;&#039;&#039;/reflog [optional line number]&#039;&#039;&#039; - prints part of the log to console. The behaviour is similar to !showbans in pub - without parameter, it returns last rows in file, positive number gives you rows starting at that index, negative gives you rows starting at index (-number) from end. Number of rows returned at once is determined by PRINT_ROWS constant (20 by default).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Example log file ===&lt;br /&gt;
 2007-05-06 14:51:57  127.0.0.1       {AR}Major Zeman                 ref&lt;br /&gt;
 2007-05-06 14:52:01  127.0.0.1       {AR}Major Zeman                 ref badpassword&lt;br /&gt;
 2007-05-06 14:52:05  127.0.0.1       {AR}Major Zeman                 ref goodpassword&lt;br /&gt;
 2007-05-06 14:52:09  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
 2007-05-06 14:52:12  127.0.0.1       {AR}Major Zeman               R ref logout&lt;br /&gt;
 2007-05-06 14:52:16  127.0.0.1       {AR}Major Zeman                 ref somecommand&lt;br /&gt;
 2007-05-06 14:52:24  ---             [console]                     C ref referee 0&lt;br /&gt;
 2007-05-06 14:52:27  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
The zip contains two files:&lt;br /&gt;
* refmon.lua - script itself, needed&lt;br /&gt;
* etconst.lua - [[User:ReyalP|ReyalP]]&#039;s header file, needed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Rules ==&lt;br /&gt;
version: 0.1&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 14.9.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/rules.lua rules.lua] (you&#039;ll need to create &#039;&#039;&#039;rules.txt&#039;&#039;&#039; file yourself in the server&#039;s etpro directory)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
This simple mod just prints contents of a textfile to a client who types in &#039;&#039;&#039;/rules&#039;&#039;&#039; command&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Whenever a client issues the /rules command, the mod will print back the content of &#039;&#039;&#039;rules.txt&#039;&#039;&#039; file on server to the client&#039;s console. Note that you&#039;ll have to create the rules.txt file in the same directory where rules.lua is. The file may contain color codes. Empty lines get eaten up, so use line with space(s) instead. Any line ednigs (win|unix|mac) should get parsed correctly.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Client console command ===&lt;br /&gt;
* &#039;&#039;&#039;/rules&#039;&#039;&#039; - prints the rules file content to the client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2967</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2967"/>
		<updated>2009-01-16T17:22:34Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: /* Printing server LUA commans output to semiadmin console */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently found at [http://acidrainclan.all-forum.net/ acidrainclan.all-forum.net] or at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the function returns short version of guid and should NOT be used for authentication purposes!&lt;br /&gt;
&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s IP ===&lt;br /&gt;
Anoter simple function, this one returns IP of the player in given slot.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the IP, too, can be spoofed. Use [[User:ReyalP|ReyalP]]&#039;s userinfocheck.lua or better his combinedfixes.lua mod on your server to at least lower this risk.&lt;br /&gt;
&lt;br /&gt;
 -- gets target&#039;s IP without port&lt;br /&gt;
 function getIP(target)&lt;br /&gt;
     if (target == nil) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo(target)&lt;br /&gt;
     local ip = et.Info_ValueForKey(userinfo, &amp;quot;ip&amp;quot;)&lt;br /&gt;
     -- strip port&lt;br /&gt;
     ip = string.sub(ip,string.find(ip,&amp;quot;(%d+%.%d+%.%d+%.%d+)&amp;quot;))&lt;br /&gt;
     return ip&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s ref status ===&lt;br /&gt;
Third function is used to check whether the target client is logged in as referee.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; It&#039;s not very well known fact that there are actually three levels of referee status: client can either not be referee at all, or be a referee that was voted in or made referee by another referee, and a referee that logged in using referee password. This function however only discriminates between the ordinary levels of &amp;quot;not referee&amp;quot; - &amp;quot;referee&amp;quot; (e.g. doesn&#039;t make difference between the two types of referees).&lt;br /&gt;
&lt;br /&gt;
 -- returns referee status of target&lt;br /&gt;
 function getRefStatus(target)&lt;br /&gt;
       local isref = et.Info_ValueForKey(et.trap_GetConfigstring(et.CS_PLAYERS + target), &amp;quot;ref&amp;quot;)&lt;br /&gt;
       if isref ~= &amp;quot;0&amp;quot; then&lt;br /&gt;
           return true&lt;br /&gt;
     else&lt;br /&gt;
         return false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Indent ===&lt;br /&gt;
Another simple function. This one is useful if you need to print a list of basically anything and want the text to be arranged in columns.&lt;br /&gt;
&lt;br /&gt;
 -- makes a string at least &amp;lt;length&amp;gt; characters long, adding spaces behind the original string if needed&lt;br /&gt;
 function indent(str, length)&lt;br /&gt;
     local len&lt;br /&gt;
 &lt;br /&gt;
     len = math.min(string.len(str), length)&lt;br /&gt;
     str = str .. string.rep(&amp;quot; &amp;quot;, length - len)&lt;br /&gt;
 &lt;br /&gt;
     return str&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Note that it never shortens the text so you might end up with a garbled table anyways, but if you set the length to a reasonable number (e.g. 15 for IP - it&#039;s max length IPv4 can have), you should be fine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read content of a text file on server ===&lt;br /&gt;
This function reads contents of a given file and returns an array of its lines. It can handle all line endings (win|unix|mac). As a price for that though, it will eat up any empty lines.&lt;br /&gt;
&lt;br /&gt;
 -- reads file and returns string array of rows (indexed from 1) and number of rows&lt;br /&gt;
 function readFile(filename)&lt;br /&gt;
     local fd, len&lt;br /&gt;
     local rows = {}&lt;br /&gt;
 &lt;br /&gt;
     fd, len = et.trap_FS_FOpenFile(filename, et.FS_READ)&lt;br /&gt;
 &lt;br /&gt;
     if len == -1 then&lt;br /&gt;
         return rows, 0&lt;br /&gt;
     else&lt;br /&gt;
         --read it all&lt;br /&gt;
         local filestr = et.trap_FS_Read(fd, len)&lt;br /&gt;
 &lt;br /&gt;
         local rowcount = 0&lt;br /&gt;
         for line in string.gfind(filestr, &amp;quot;[^\r\n]+&amp;quot;) do&lt;br /&gt;
             rowcount = rowcount + 1&lt;br /&gt;
             rows[rowcount] = line&lt;br /&gt;
         end&lt;br /&gt;
 &lt;br /&gt;
             et.trap_FS_FCloseFile(fd)&lt;br /&gt;
             return rows, rowcount&lt;br /&gt;
       end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and optionally a client number. If it received client number, it prints the message to that client, if it received null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in ClientCommand trap:&lt;br /&gt;
&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;re passing the command to ET&lt;br /&gt;
&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.7 &amp;lt;small&amp;gt;(changelog is inside lua script)&amp;lt;/small&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 20.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== RefMon ==&lt;br /&gt;
version: 0.2&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 8.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/refmon.lua lua] (requires [http://www.sonic.net/~rfm/et/lua/etconst.lua etconst.lua])]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Referee Monitor mod - a lua script that logs all ref commands to a separate, easy to read log.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Referee monitor writes a log record for any ref command issued by either client or server console. The log contains these columns:&lt;br /&gt;
* date and time (in server&#039;s timezone)&lt;br /&gt;
* IP of the client who issued the command (empty for server commands, note that IP can be spoofed)&lt;br /&gt;
* name of the client who issued the command (or [console])&lt;br /&gt;
* flag - for easy orientation in the log, R means the player was logged in as ref, C means console command, empty otherwise&lt;br /&gt;
* command issued&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Server console command ===&lt;br /&gt;
* &#039;&#039;&#039;/reflog [optional line number]&#039;&#039;&#039; - prints part of the log to console. The behaviour is similar to !showbans in pub - without parameter, it returns last rows in file, positive number gives you rows starting at that index, negative gives you rows starting at index (-number) from end. Number of rows returned at once is determined by PRINT_ROWS constant (20 by default).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Example log file ===&lt;br /&gt;
 2007-05-06 14:51:57  127.0.0.1       {AR}Major Zeman                 ref&lt;br /&gt;
 2007-05-06 14:52:01  127.0.0.1       {AR}Major Zeman                 ref badpassword&lt;br /&gt;
 2007-05-06 14:52:05  127.0.0.1       {AR}Major Zeman                 ref goodpassword&lt;br /&gt;
 2007-05-06 14:52:09  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
 2007-05-06 14:52:12  127.0.0.1       {AR}Major Zeman               R ref logout&lt;br /&gt;
 2007-05-06 14:52:16  127.0.0.1       {AR}Major Zeman                 ref somecommand&lt;br /&gt;
 2007-05-06 14:52:24  ---             [console]                     C ref referee 0&lt;br /&gt;
 2007-05-06 14:52:27  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
The zip contains two files:&lt;br /&gt;
* refmon.lua - script itself, needed&lt;br /&gt;
* etconst.lua - [[User:ReyalP|ReyalP]]&#039;s header file, needed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Rules ==&lt;br /&gt;
version: 0.1&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 14.9.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/rules.lua rules.lua] (you&#039;ll need to create &#039;&#039;&#039;rules.txt&#039;&#039;&#039; file yourself in the server&#039;s etpro directory)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
This simple mod just prints contents of a textfile to a client who types in &#039;&#039;&#039;/rules&#039;&#039;&#039; command&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Whenever a client issues the /rules command, the mod will print back the content of &#039;&#039;&#039;rules.txt&#039;&#039;&#039; file on server to the client&#039;s console. Note that you&#039;ll have to create the rules.txt file in the same directory where rules.lua is. The file may contain color codes. Empty lines get eaten up, so use line with space(s) instead. Any line ednigs (win|unix|mac) should get parsed correctly.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Client console command ===&lt;br /&gt;
* &#039;&#039;&#039;/rules&#039;&#039;&#039; - prints the rules file content to the client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2966</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2966"/>
		<updated>2009-01-16T17:21:16Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: /* Print message to console */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently found at [http://acidrainclan.all-forum.net/ acidrainclan.all-forum.net] or at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the function returns short version of guid and should NOT be used for authentication purposes!&lt;br /&gt;
&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s IP ===&lt;br /&gt;
Anoter simple function, this one returns IP of the player in given slot.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the IP, too, can be spoofed. Use [[User:ReyalP|ReyalP]]&#039;s userinfocheck.lua or better his combinedfixes.lua mod on your server to at least lower this risk.&lt;br /&gt;
&lt;br /&gt;
 -- gets target&#039;s IP without port&lt;br /&gt;
 function getIP(target)&lt;br /&gt;
     if (target == nil) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo(target)&lt;br /&gt;
     local ip = et.Info_ValueForKey(userinfo, &amp;quot;ip&amp;quot;)&lt;br /&gt;
     -- strip port&lt;br /&gt;
     ip = string.sub(ip,string.find(ip,&amp;quot;(%d+%.%d+%.%d+%.%d+)&amp;quot;))&lt;br /&gt;
     return ip&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s ref status ===&lt;br /&gt;
Third function is used to check whether the target client is logged in as referee.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; It&#039;s not very well known fact that there are actually three levels of referee status: client can either not be referee at all, or be a referee that was voted in or made referee by another referee, and a referee that logged in using referee password. This function however only discriminates between the ordinary levels of &amp;quot;not referee&amp;quot; - &amp;quot;referee&amp;quot; (e.g. doesn&#039;t make difference between the two types of referees).&lt;br /&gt;
&lt;br /&gt;
 -- returns referee status of target&lt;br /&gt;
 function getRefStatus(target)&lt;br /&gt;
       local isref = et.Info_ValueForKey(et.trap_GetConfigstring(et.CS_PLAYERS + target), &amp;quot;ref&amp;quot;)&lt;br /&gt;
       if isref ~= &amp;quot;0&amp;quot; then&lt;br /&gt;
           return true&lt;br /&gt;
     else&lt;br /&gt;
         return false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Indent ===&lt;br /&gt;
Another simple function. This one is useful if you need to print a list of basically anything and want the text to be arranged in columns.&lt;br /&gt;
&lt;br /&gt;
 -- makes a string at least &amp;lt;length&amp;gt; characters long, adding spaces behind the original string if needed&lt;br /&gt;
 function indent(str, length)&lt;br /&gt;
     local len&lt;br /&gt;
 &lt;br /&gt;
     len = math.min(string.len(str), length)&lt;br /&gt;
     str = str .. string.rep(&amp;quot; &amp;quot;, length - len)&lt;br /&gt;
 &lt;br /&gt;
     return str&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Note that it never shortens the text so you might end up with a garbled table anyways, but if you set the length to a reasonable number (e.g. 15 for IP - it&#039;s max length IPv4 can have), you should be fine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read content of a text file on server ===&lt;br /&gt;
This function reads contents of a given file and returns an array of its lines. It can handle all line endings (win|unix|mac). As a price for that though, it will eat up any empty lines.&lt;br /&gt;
&lt;br /&gt;
 -- reads file and returns string array of rows (indexed from 1) and number of rows&lt;br /&gt;
 function readFile(filename)&lt;br /&gt;
     local fd, len&lt;br /&gt;
     local rows = {}&lt;br /&gt;
 &lt;br /&gt;
     fd, len = et.trap_FS_FOpenFile(filename, et.FS_READ)&lt;br /&gt;
 &lt;br /&gt;
     if len == -1 then&lt;br /&gt;
         return rows, 0&lt;br /&gt;
     else&lt;br /&gt;
         --read it all&lt;br /&gt;
         local filestr = et.trap_FS_Read(fd, len)&lt;br /&gt;
 &lt;br /&gt;
         local rowcount = 0&lt;br /&gt;
         for line in string.gfind(filestr, &amp;quot;[^\r\n]+&amp;quot;) do&lt;br /&gt;
             rowcount = rowcount + 1&lt;br /&gt;
             rows[rowcount] = line&lt;br /&gt;
         end&lt;br /&gt;
 &lt;br /&gt;
             et.trap_FS_FCloseFile(fd)&lt;br /&gt;
             return rows, rowcount&lt;br /&gt;
       end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and optionally a client number. If it received client number, it prints the message to that client, if it received null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in ClientCommand trap:&lt;br /&gt;
&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;ll passing the command to ET&lt;br /&gt;
&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.7 &amp;lt;small&amp;gt;(changelog is inside lua script)&amp;lt;/small&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 20.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== RefMon ==&lt;br /&gt;
version: 0.2&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 8.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/refmon.lua lua] (requires [http://www.sonic.net/~rfm/et/lua/etconst.lua etconst.lua])]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Referee Monitor mod - a lua script that logs all ref commands to a separate, easy to read log.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Referee monitor writes a log record for any ref command issued by either client or server console. The log contains these columns:&lt;br /&gt;
* date and time (in server&#039;s timezone)&lt;br /&gt;
* IP of the client who issued the command (empty for server commands, note that IP can be spoofed)&lt;br /&gt;
* name of the client who issued the command (or [console])&lt;br /&gt;
* flag - for easy orientation in the log, R means the player was logged in as ref, C means console command, empty otherwise&lt;br /&gt;
* command issued&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Server console command ===&lt;br /&gt;
* &#039;&#039;&#039;/reflog [optional line number]&#039;&#039;&#039; - prints part of the log to console. The behaviour is similar to !showbans in pub - without parameter, it returns last rows in file, positive number gives you rows starting at that index, negative gives you rows starting at index (-number) from end. Number of rows returned at once is determined by PRINT_ROWS constant (20 by default).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Example log file ===&lt;br /&gt;
 2007-05-06 14:51:57  127.0.0.1       {AR}Major Zeman                 ref&lt;br /&gt;
 2007-05-06 14:52:01  127.0.0.1       {AR}Major Zeman                 ref badpassword&lt;br /&gt;
 2007-05-06 14:52:05  127.0.0.1       {AR}Major Zeman                 ref goodpassword&lt;br /&gt;
 2007-05-06 14:52:09  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
 2007-05-06 14:52:12  127.0.0.1       {AR}Major Zeman               R ref logout&lt;br /&gt;
 2007-05-06 14:52:16  127.0.0.1       {AR}Major Zeman                 ref somecommand&lt;br /&gt;
 2007-05-06 14:52:24  ---             [console]                     C ref referee 0&lt;br /&gt;
 2007-05-06 14:52:27  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
The zip contains two files:&lt;br /&gt;
* refmon.lua - script itself, needed&lt;br /&gt;
* etconst.lua - [[User:ReyalP|ReyalP]]&#039;s header file, needed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Rules ==&lt;br /&gt;
version: 0.1&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 14.9.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/rules.lua rules.lua] (you&#039;ll need to create &#039;&#039;&#039;rules.txt&#039;&#039;&#039; file yourself in the server&#039;s etpro directory)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
This simple mod just prints contents of a textfile to a client who types in &#039;&#039;&#039;/rules&#039;&#039;&#039; command&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Whenever a client issues the /rules command, the mod will print back the content of &#039;&#039;&#039;rules.txt&#039;&#039;&#039; file on server to the client&#039;s console. Note that you&#039;ll have to create the rules.txt file in the same directory where rules.lua is. The file may contain color codes. Empty lines get eaten up, so use line with space(s) instead. Any line ednigs (win|unix|mac) should get parsed correctly.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Client console command ===&lt;br /&gt;
* &#039;&#039;&#039;/rules&#039;&#039;&#039; - prints the rules file content to the client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2965</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2965"/>
		<updated>2009-01-16T17:20:30Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: /* Printing server LUA commans output to semiadmin console */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently found at [http://acidrainclan.all-forum.net/ acidrainclan.all-forum.net] or at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the function returns short version of guid and should NOT be used for authentication purposes!&lt;br /&gt;
&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s IP ===&lt;br /&gt;
Anoter simple function, this one returns IP of the player in given slot.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the IP, too, can be spoofed. Use [[User:ReyalP|ReyalP]]&#039;s userinfocheck.lua or better his combinedfixes.lua mod on your server to at least lower this risk.&lt;br /&gt;
&lt;br /&gt;
 -- gets target&#039;s IP without port&lt;br /&gt;
 function getIP(target)&lt;br /&gt;
     if (target == nil) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo(target)&lt;br /&gt;
     local ip = et.Info_ValueForKey(userinfo, &amp;quot;ip&amp;quot;)&lt;br /&gt;
     -- strip port&lt;br /&gt;
     ip = string.sub(ip,string.find(ip,&amp;quot;(%d+%.%d+%.%d+%.%d+)&amp;quot;))&lt;br /&gt;
     return ip&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s ref status ===&lt;br /&gt;
Third function is used to check whether the target client is logged in as referee.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; It&#039;s not very well known fact that there are actually three levels of referee status: client can either not be referee at all, or be a referee that was voted in or made referee by another referee, and a referee that logged in using referee password. This function however only discriminates between the ordinary levels of &amp;quot;not referee&amp;quot; - &amp;quot;referee&amp;quot; (e.g. doesn&#039;t make difference between the two types of referees).&lt;br /&gt;
&lt;br /&gt;
 -- returns referee status of target&lt;br /&gt;
 function getRefStatus(target)&lt;br /&gt;
       local isref = et.Info_ValueForKey(et.trap_GetConfigstring(et.CS_PLAYERS + target), &amp;quot;ref&amp;quot;)&lt;br /&gt;
       if isref ~= &amp;quot;0&amp;quot; then&lt;br /&gt;
           return true&lt;br /&gt;
     else&lt;br /&gt;
         return false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Indent ===&lt;br /&gt;
Another simple function. This one is useful if you need to print a list of basically anything and want the text to be arranged in columns.&lt;br /&gt;
&lt;br /&gt;
 -- makes a string at least &amp;lt;length&amp;gt; characters long, adding spaces behind the original string if needed&lt;br /&gt;
 function indent(str, length)&lt;br /&gt;
     local len&lt;br /&gt;
 &lt;br /&gt;
     len = math.min(string.len(str), length)&lt;br /&gt;
     str = str .. string.rep(&amp;quot; &amp;quot;, length - len)&lt;br /&gt;
 &lt;br /&gt;
     return str&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Note that it never shortens the text so you might end up with a garbled table anyways, but if you set the length to a reasonable number (e.g. 15 for IP - it&#039;s max length IPv4 can have), you should be fine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read content of a text file on server ===&lt;br /&gt;
This function reads contents of a given file and returns an array of its lines. It can handle all line endings (win|unix|mac). As a price for that though, it will eat up any empty lines.&lt;br /&gt;
&lt;br /&gt;
 -- reads file and returns string array of rows (indexed from 1) and number of rows&lt;br /&gt;
 function readFile(filename)&lt;br /&gt;
     local fd, len&lt;br /&gt;
     local rows = {}&lt;br /&gt;
 &lt;br /&gt;
     fd, len = et.trap_FS_FOpenFile(filename, et.FS_READ)&lt;br /&gt;
 &lt;br /&gt;
     if len == -1 then&lt;br /&gt;
         return rows, 0&lt;br /&gt;
     else&lt;br /&gt;
         --read it all&lt;br /&gt;
         local filestr = et.trap_FS_Read(fd, len)&lt;br /&gt;
 &lt;br /&gt;
         local rowcount = 0&lt;br /&gt;
         for line in string.gfind(filestr, &amp;quot;[^\r\n]+&amp;quot;) do&lt;br /&gt;
             rowcount = rowcount + 1&lt;br /&gt;
             rows[rowcount] = line&lt;br /&gt;
         end&lt;br /&gt;
 &lt;br /&gt;
             et.trap_FS_FCloseFile(fd)&lt;br /&gt;
             return rows, rowcount&lt;br /&gt;
       end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in ClientCommand trap:&lt;br /&gt;
&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;ll passing the command to ET&lt;br /&gt;
&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.7 &amp;lt;small&amp;gt;(changelog is inside lua script)&amp;lt;/small&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 20.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== RefMon ==&lt;br /&gt;
version: 0.2&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 8.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/refmon.lua lua] (requires [http://www.sonic.net/~rfm/et/lua/etconst.lua etconst.lua])]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Referee Monitor mod - a lua script that logs all ref commands to a separate, easy to read log.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Referee monitor writes a log record for any ref command issued by either client or server console. The log contains these columns:&lt;br /&gt;
* date and time (in server&#039;s timezone)&lt;br /&gt;
* IP of the client who issued the command (empty for server commands, note that IP can be spoofed)&lt;br /&gt;
* name of the client who issued the command (or [console])&lt;br /&gt;
* flag - for easy orientation in the log, R means the player was logged in as ref, C means console command, empty otherwise&lt;br /&gt;
* command issued&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Server console command ===&lt;br /&gt;
* &#039;&#039;&#039;/reflog [optional line number]&#039;&#039;&#039; - prints part of the log to console. The behaviour is similar to !showbans in pub - without parameter, it returns last rows in file, positive number gives you rows starting at that index, negative gives you rows starting at index (-number) from end. Number of rows returned at once is determined by PRINT_ROWS constant (20 by default).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Example log file ===&lt;br /&gt;
 2007-05-06 14:51:57  127.0.0.1       {AR}Major Zeman                 ref&lt;br /&gt;
 2007-05-06 14:52:01  127.0.0.1       {AR}Major Zeman                 ref badpassword&lt;br /&gt;
 2007-05-06 14:52:05  127.0.0.1       {AR}Major Zeman                 ref goodpassword&lt;br /&gt;
 2007-05-06 14:52:09  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
 2007-05-06 14:52:12  127.0.0.1       {AR}Major Zeman               R ref logout&lt;br /&gt;
 2007-05-06 14:52:16  127.0.0.1       {AR}Major Zeman                 ref somecommand&lt;br /&gt;
 2007-05-06 14:52:24  ---             [console]                     C ref referee 0&lt;br /&gt;
 2007-05-06 14:52:27  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
The zip contains two files:&lt;br /&gt;
* refmon.lua - script itself, needed&lt;br /&gt;
* etconst.lua - [[User:ReyalP|ReyalP]]&#039;s header file, needed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Rules ==&lt;br /&gt;
version: 0.1&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 14.9.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/rules.lua rules.lua] (you&#039;ll need to create &#039;&#039;&#039;rules.txt&#039;&#039;&#039; file yourself in the server&#039;s etpro directory)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
This simple mod just prints contents of a textfile to a client who types in &#039;&#039;&#039;/rules&#039;&#039;&#039; command&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Whenever a client issues the /rules command, the mod will print back the content of &#039;&#039;&#039;rules.txt&#039;&#039;&#039; file on server to the client&#039;s console. Note that you&#039;ll have to create the rules.txt file in the same directory where rules.lua is. The file may contain color codes. Empty lines get eaten up, so use line with space(s) instead. Any line ednigs (win|unix|mac) should get parsed correctly.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Client console command ===&lt;br /&gt;
* &#039;&#039;&#039;/rules&#039;&#039;&#039; - prints the rules file content to the client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2964</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2964"/>
		<updated>2009-01-15T21:45:45Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently found at [http://acidrainclan.all-forum.net/ acidrainclan.all-forum.net] or at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the function returns short version of guid and should NOT be used for authentication purposes!&lt;br /&gt;
&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s IP ===&lt;br /&gt;
Anoter simple function, this one returns IP of the player in given slot.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the IP, too, can be spoofed. Use [[User:ReyalP|ReyalP]]&#039;s userinfocheck.lua or better his combinedfixes.lua mod on your server to at least lower this risk.&lt;br /&gt;
&lt;br /&gt;
 -- gets target&#039;s IP without port&lt;br /&gt;
 function getIP(target)&lt;br /&gt;
     if (target == nil) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo(target)&lt;br /&gt;
     local ip = et.Info_ValueForKey(userinfo, &amp;quot;ip&amp;quot;)&lt;br /&gt;
     -- strip port&lt;br /&gt;
     ip = string.sub(ip,string.find(ip,&amp;quot;(%d+%.%d+%.%d+%.%d+)&amp;quot;))&lt;br /&gt;
     return ip&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s ref status ===&lt;br /&gt;
Third function is used to check whether the target client is logged in as referee.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; It&#039;s not very well known fact that there are actually three levels of referee status: client can either not be referee at all, or be a referee that was voted in or made referee by another referee, and a referee that logged in using referee password. This function however only discriminates between the ordinary levels of &amp;quot;not referee&amp;quot; - &amp;quot;referee&amp;quot; (e.g. doesn&#039;t make difference between the two types of referees).&lt;br /&gt;
&lt;br /&gt;
 -- returns referee status of target&lt;br /&gt;
 function getRefStatus(target)&lt;br /&gt;
       local isref = et.Info_ValueForKey(et.trap_GetConfigstring(et.CS_PLAYERS + target), &amp;quot;ref&amp;quot;)&lt;br /&gt;
       if isref ~= &amp;quot;0&amp;quot; then&lt;br /&gt;
           return true&lt;br /&gt;
     else&lt;br /&gt;
         return false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Indent ===&lt;br /&gt;
Another simple function. This one is useful if you need to print a list of basically anything and want the text to be arranged in columns.&lt;br /&gt;
&lt;br /&gt;
 -- makes a string at least &amp;lt;length&amp;gt; characters long, adding spaces behind the original string if needed&lt;br /&gt;
 function indent(str, length)&lt;br /&gt;
     local len&lt;br /&gt;
 &lt;br /&gt;
     len = math.min(string.len(str), length)&lt;br /&gt;
     str = str .. string.rep(&amp;quot; &amp;quot;, length - len)&lt;br /&gt;
 &lt;br /&gt;
     return str&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Note that it never shortens the text so you might end up with a garbled table anyways, but if you set the length to a reasonable number (e.g. 15 for IP - it&#039;s max length IPv4 can have), you should be fine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read content of a text file on server ===&lt;br /&gt;
This function reads contents of a given file and returns an array of its lines. It can handle all line endings (win|unix|mac). As a price for that though, it will eat up any empty lines.&lt;br /&gt;
&lt;br /&gt;
 -- reads file and returns string array of rows (indexed from 1) and number of rows&lt;br /&gt;
 function readFile(filename)&lt;br /&gt;
     local fd, len&lt;br /&gt;
     local rows = {}&lt;br /&gt;
 &lt;br /&gt;
     fd, len = et.trap_FS_FOpenFile(filename, et.FS_READ)&lt;br /&gt;
 &lt;br /&gt;
     if len == -1 then&lt;br /&gt;
         return rows, 0&lt;br /&gt;
     else&lt;br /&gt;
         --read it all&lt;br /&gt;
         local filestr = et.trap_FS_Read(fd, len)&lt;br /&gt;
 &lt;br /&gt;
         local rowcount = 0&lt;br /&gt;
         for line in string.gfind(filestr, &amp;quot;[^\r\n]+&amp;quot;) do&lt;br /&gt;
             rowcount = rowcount + 1&lt;br /&gt;
             rows[rowcount] = line&lt;br /&gt;
         end&lt;br /&gt;
 &lt;br /&gt;
             et.trap_FS_FCloseFile(fd)&lt;br /&gt;
             return rows, rowcount&lt;br /&gt;
       end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in CleintCommand trap:&lt;br /&gt;
&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;ll passing the command to ET&lt;br /&gt;
&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.7 &amp;lt;small&amp;gt;(changelog is inside lua script)&amp;lt;/small&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 20.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== RefMon ==&lt;br /&gt;
version: 0.2&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 8.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/refmon.lua lua] (requires [http://www.sonic.net/~rfm/et/lua/etconst.lua etconst.lua])]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Referee Monitor mod - a lua script that logs all ref commands to a separate, easy to read log.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Referee monitor writes a log record for any ref command issued by either client or server console. The log contains these columns:&lt;br /&gt;
* date and time (in server&#039;s timezone)&lt;br /&gt;
* IP of the client who issued the command (empty for server commands, note that IP can be spoofed)&lt;br /&gt;
* name of the client who issued the command (or [console])&lt;br /&gt;
* flag - for easy orientation in the log, R means the player was logged in as ref, C means console command, empty otherwise&lt;br /&gt;
* command issued&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Server console command ===&lt;br /&gt;
* &#039;&#039;&#039;/reflog [optional line number]&#039;&#039;&#039; - prints part of the log to console. The behaviour is similar to !showbans in pub - without parameter, it returns last rows in file, positive number gives you rows starting at that index, negative gives you rows starting at index (-number) from end. Number of rows returned at once is determined by PRINT_ROWS constant (20 by default).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Example log file ===&lt;br /&gt;
 2007-05-06 14:51:57  127.0.0.1       {AR}Major Zeman                 ref&lt;br /&gt;
 2007-05-06 14:52:01  127.0.0.1       {AR}Major Zeman                 ref badpassword&lt;br /&gt;
 2007-05-06 14:52:05  127.0.0.1       {AR}Major Zeman                 ref goodpassword&lt;br /&gt;
 2007-05-06 14:52:09  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
 2007-05-06 14:52:12  127.0.0.1       {AR}Major Zeman               R ref logout&lt;br /&gt;
 2007-05-06 14:52:16  127.0.0.1       {AR}Major Zeman                 ref somecommand&lt;br /&gt;
 2007-05-06 14:52:24  ---             [console]                     C ref referee 0&lt;br /&gt;
 2007-05-06 14:52:27  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
The zip contains two files:&lt;br /&gt;
* refmon.lua - script itself, needed&lt;br /&gt;
* etconst.lua - [[User:ReyalP|ReyalP]]&#039;s header file, needed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Rules ==&lt;br /&gt;
version: 0.1&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 14.9.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/rules.lua rules.lua] (you&#039;ll need to create &#039;&#039;&#039;rules.txt&#039;&#039;&#039; file yourself in the server&#039;s etpro directory)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
This simple mod just prints contents of a textfile to a client who types in &#039;&#039;&#039;/rules&#039;&#039;&#039; command&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Whenever a client issues the /rules command, the mod will print back the content of &#039;&#039;&#039;rules.txt&#039;&#039;&#039; file on server to the client&#039;s console. Note that you&#039;ll have to create the rules.txt file in the same directory where rules.lua is. The file may contain color codes. Empty lines get eaten up, so use line with space(s) instead. Any line ednigs (win|unix|mac) should get parsed correctly.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Client console command ===&lt;br /&gt;
* &#039;&#039;&#039;/rules&#039;&#039;&#039; - prints the rules file content to the client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2963</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2963"/>
		<updated>2009-01-15T21:45:13Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently found at [http://acidrainclan.all-forum.net/] or at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the function returns short version of guid and should NOT be used for authentication purposes!&lt;br /&gt;
&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s IP ===&lt;br /&gt;
Anoter simple function, this one returns IP of the player in given slot.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the IP, too, can be spoofed. Use [[User:ReyalP|ReyalP]]&#039;s userinfocheck.lua or better his combinedfixes.lua mod on your server to at least lower this risk.&lt;br /&gt;
&lt;br /&gt;
 -- gets target&#039;s IP without port&lt;br /&gt;
 function getIP(target)&lt;br /&gt;
     if (target == nil) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo(target)&lt;br /&gt;
     local ip = et.Info_ValueForKey(userinfo, &amp;quot;ip&amp;quot;)&lt;br /&gt;
     -- strip port&lt;br /&gt;
     ip = string.sub(ip,string.find(ip,&amp;quot;(%d+%.%d+%.%d+%.%d+)&amp;quot;))&lt;br /&gt;
     return ip&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s ref status ===&lt;br /&gt;
Third function is used to check whether the target client is logged in as referee.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; It&#039;s not very well known fact that there are actually three levels of referee status: client can either not be referee at all, or be a referee that was voted in or made referee by another referee, and a referee that logged in using referee password. This function however only discriminates between the ordinary levels of &amp;quot;not referee&amp;quot; - &amp;quot;referee&amp;quot; (e.g. doesn&#039;t make difference between the two types of referees).&lt;br /&gt;
&lt;br /&gt;
 -- returns referee status of target&lt;br /&gt;
 function getRefStatus(target)&lt;br /&gt;
       local isref = et.Info_ValueForKey(et.trap_GetConfigstring(et.CS_PLAYERS + target), &amp;quot;ref&amp;quot;)&lt;br /&gt;
       if isref ~= &amp;quot;0&amp;quot; then&lt;br /&gt;
           return true&lt;br /&gt;
     else&lt;br /&gt;
         return false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Indent ===&lt;br /&gt;
Another simple function. This one is useful if you need to print a list of basically anything and want the text to be arranged in columns.&lt;br /&gt;
&lt;br /&gt;
 -- makes a string at least &amp;lt;length&amp;gt; characters long, adding spaces behind the original string if needed&lt;br /&gt;
 function indent(str, length)&lt;br /&gt;
     local len&lt;br /&gt;
 &lt;br /&gt;
     len = math.min(string.len(str), length)&lt;br /&gt;
     str = str .. string.rep(&amp;quot; &amp;quot;, length - len)&lt;br /&gt;
 &lt;br /&gt;
     return str&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Note that it never shortens the text so you might end up with a garbled table anyways, but if you set the length to a reasonable number (e.g. 15 for IP - it&#039;s max length IPv4 can have), you should be fine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read content of a text file on server ===&lt;br /&gt;
This function reads contents of a given file and returns an array of its lines. It can handle all line endings (win|unix|mac). As a price for that though, it will eat up any empty lines.&lt;br /&gt;
&lt;br /&gt;
 -- reads file and returns string array of rows (indexed from 1) and number of rows&lt;br /&gt;
 function readFile(filename)&lt;br /&gt;
     local fd, len&lt;br /&gt;
     local rows = {}&lt;br /&gt;
 &lt;br /&gt;
     fd, len = et.trap_FS_FOpenFile(filename, et.FS_READ)&lt;br /&gt;
 &lt;br /&gt;
     if len == -1 then&lt;br /&gt;
         return rows, 0&lt;br /&gt;
     else&lt;br /&gt;
         --read it all&lt;br /&gt;
         local filestr = et.trap_FS_Read(fd, len)&lt;br /&gt;
 &lt;br /&gt;
         local rowcount = 0&lt;br /&gt;
         for line in string.gfind(filestr, &amp;quot;[^\r\n]+&amp;quot;) do&lt;br /&gt;
             rowcount = rowcount + 1&lt;br /&gt;
             rows[rowcount] = line&lt;br /&gt;
         end&lt;br /&gt;
 &lt;br /&gt;
             et.trap_FS_FCloseFile(fd)&lt;br /&gt;
             return rows, rowcount&lt;br /&gt;
       end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in CleintCommand trap:&lt;br /&gt;
&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;ll passing the command to ET&lt;br /&gt;
&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.7 &amp;lt;small&amp;gt;(changelog is inside lua script)&amp;lt;/small&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 20.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== RefMon ==&lt;br /&gt;
version: 0.2&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 8.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/refmon.lua lua] (requires [http://www.sonic.net/~rfm/et/lua/etconst.lua etconst.lua])]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Referee Monitor mod - a lua script that logs all ref commands to a separate, easy to read log.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Referee monitor writes a log record for any ref command issued by either client or server console. The log contains these columns:&lt;br /&gt;
* date and time (in server&#039;s timezone)&lt;br /&gt;
* IP of the client who issued the command (empty for server commands, note that IP can be spoofed)&lt;br /&gt;
* name of the client who issued the command (or [console])&lt;br /&gt;
* flag - for easy orientation in the log, R means the player was logged in as ref, C means console command, empty otherwise&lt;br /&gt;
* command issued&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Server console command ===&lt;br /&gt;
* &#039;&#039;&#039;/reflog [optional line number]&#039;&#039;&#039; - prints part of the log to console. The behaviour is similar to !showbans in pub - without parameter, it returns last rows in file, positive number gives you rows starting at that index, negative gives you rows starting at index (-number) from end. Number of rows returned at once is determined by PRINT_ROWS constant (20 by default).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Example log file ===&lt;br /&gt;
 2007-05-06 14:51:57  127.0.0.1       {AR}Major Zeman                 ref&lt;br /&gt;
 2007-05-06 14:52:01  127.0.0.1       {AR}Major Zeman                 ref badpassword&lt;br /&gt;
 2007-05-06 14:52:05  127.0.0.1       {AR}Major Zeman                 ref goodpassword&lt;br /&gt;
 2007-05-06 14:52:09  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
 2007-05-06 14:52:12  127.0.0.1       {AR}Major Zeman               R ref logout&lt;br /&gt;
 2007-05-06 14:52:16  127.0.0.1       {AR}Major Zeman                 ref somecommand&lt;br /&gt;
 2007-05-06 14:52:24  ---             [console]                     C ref referee 0&lt;br /&gt;
 2007-05-06 14:52:27  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
The zip contains two files:&lt;br /&gt;
* refmon.lua - script itself, needed&lt;br /&gt;
* etconst.lua - [[User:ReyalP|ReyalP]]&#039;s header file, needed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Rules ==&lt;br /&gt;
version: 0.1&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 14.9.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/rules.lua rules.lua] (you&#039;ll need to create &#039;&#039;&#039;rules.txt&#039;&#039;&#039; file yourself in the server&#039;s etpro directory)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
This simple mod just prints contents of a textfile to a client who types in &#039;&#039;&#039;/rules&#039;&#039;&#039; command&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Whenever a client issues the /rules command, the mod will print back the content of &#039;&#039;&#039;rules.txt&#039;&#039;&#039; file on server to the client&#039;s console. Note that you&#039;ll have to create the rules.txt file in the same directory where rules.lua is. The file may contain color codes. Empty lines get eaten up, so use line with space(s) instead. Any line ednigs (win|unix|mac) should get parsed correctly.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Client console command ===&lt;br /&gt;
* &#039;&#039;&#039;/rules&#039;&#039;&#039; - prints the rules file content to the client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2807</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2807"/>
		<updated>2007-09-14T11:49:26Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: Rules LUA module&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently (= for about last 3 years) found at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the function returns short version of guid and should NOT be used for authentication purposes!&lt;br /&gt;
&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s IP ===&lt;br /&gt;
Anoter simple function, this one returns IP of the player in given slot.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the IP, too, can be spoofed. Use [[User:ReyalP|ReyalP]]&#039;s userinfocheck.lua or better his combinedfixes.lua mod on your server to at least lower this risk.&lt;br /&gt;
&lt;br /&gt;
 -- gets target&#039;s IP without port&lt;br /&gt;
 function getIP(target)&lt;br /&gt;
     if (target == nil) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo(target)&lt;br /&gt;
     local ip = et.Info_ValueForKey(userinfo, &amp;quot;ip&amp;quot;)&lt;br /&gt;
     -- strip port&lt;br /&gt;
     ip = string.sub(ip,string.find(ip,&amp;quot;(%d+%.%d+%.%d+%.%d+)&amp;quot;))&lt;br /&gt;
     return ip&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s ref status ===&lt;br /&gt;
Third function is used to check whether the target client is logged in as referee.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; It&#039;s not very well known fact that there are actually three levels of referee status: client can either not be referee at all, or be a referee that was voted in or made referee by another referee, and a referee that logged in using referee password. This function however only discriminates between the ordinary levels of &amp;quot;not referee&amp;quot; - &amp;quot;referee&amp;quot; (e.g. doesn&#039;t make difference between the two types of referees).&lt;br /&gt;
&lt;br /&gt;
 -- returns referee status of target&lt;br /&gt;
 function getRefStatus(target)&lt;br /&gt;
       local isref = et.Info_ValueForKey(et.trap_GetConfigstring(et.CS_PLAYERS + target), &amp;quot;ref&amp;quot;)&lt;br /&gt;
       if isref ~= &amp;quot;0&amp;quot; then&lt;br /&gt;
           return true&lt;br /&gt;
     else&lt;br /&gt;
         return false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Indent ===&lt;br /&gt;
Another simple function. This one is useful if you need to print a list of basically anything and want the text to be arranged in columns.&lt;br /&gt;
&lt;br /&gt;
 -- makes a string at least &amp;lt;length&amp;gt; characters long, adding spaces behind the original string if needed&lt;br /&gt;
 function indent(str, length)&lt;br /&gt;
     local len&lt;br /&gt;
 &lt;br /&gt;
     len = math.min(string.len(str), length)&lt;br /&gt;
     str = str .. string.rep(&amp;quot; &amp;quot;, length - len)&lt;br /&gt;
 &lt;br /&gt;
     return str&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Note that it never shortens the text so you might end up with a garbled table anyways, but if you set the length to a reasonable number (e.g. 15 for IP - it&#039;s max length IPv4 can have), you should be fine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read content of a text file on server ===&lt;br /&gt;
This function reads contents of a given file and returns an array of its lines. It can handle all line endings (win|unix|mac). As a price for that though, it will eat up any empty lines.&lt;br /&gt;
&lt;br /&gt;
 -- reads file and returns string array of rows (indexed from 1) and number of rows&lt;br /&gt;
 function readFile(filename)&lt;br /&gt;
     local fd, len&lt;br /&gt;
     local rows = {}&lt;br /&gt;
 &lt;br /&gt;
     fd, len = et.trap_FS_FOpenFile(filename, et.FS_READ)&lt;br /&gt;
 &lt;br /&gt;
     if len == -1 then&lt;br /&gt;
         return rows, 0&lt;br /&gt;
     else&lt;br /&gt;
         --read it all&lt;br /&gt;
         local filestr = et.trap_FS_Read(fd, len)&lt;br /&gt;
 &lt;br /&gt;
         local rowcount = 0&lt;br /&gt;
         for line in string.gfind(filestr, &amp;quot;[^\r\n]+&amp;quot;) do&lt;br /&gt;
             rowcount = rowcount + 1&lt;br /&gt;
             rows[rowcount] = line&lt;br /&gt;
         end&lt;br /&gt;
 &lt;br /&gt;
             et.trap_FS_FCloseFile(fd)&lt;br /&gt;
             return rows, rowcount&lt;br /&gt;
       end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in CleintCommand trap:&lt;br /&gt;
&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;ll passing the command to ET&lt;br /&gt;
&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.7 &amp;lt;small&amp;gt;(changelog is inside lua script)&amp;lt;/small&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 20.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== RefMon ==&lt;br /&gt;
version: 0.2&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 8.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/refmon.lua lua] (requires [http://www.sonic.net/~rfm/et/lua/etconst.lua etconst.lua])]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Referee Monitor mod - a lua script that logs all ref commands to a separate, easy to read log.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Referee monitor writes a log record for any ref command issued by either client or server console. The log contains these columns:&lt;br /&gt;
* date and time (in server&#039;s timezone)&lt;br /&gt;
* IP of the client who issued the command (empty for server commands, note that IP can be spoofed)&lt;br /&gt;
* name of the client who issued the command (or [console])&lt;br /&gt;
* flag - for easy orientation in the log, R means the player was logged in as ref, C means console command, empty otherwise&lt;br /&gt;
* command issued&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Server console command ===&lt;br /&gt;
* &#039;&#039;&#039;/reflog [optional line number]&#039;&#039;&#039; - prints part of the log to console. The behaviour is similar to !showbans in pub - without parameter, it returns last rows in file, positive number gives you rows starting at that index, negative gives you rows starting at index (-number) from end. Number of rows returned at once is determined by PRINT_ROWS constant (20 by default).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Example log file ===&lt;br /&gt;
 2007-05-06 14:51:57  127.0.0.1       {AR}Major Zeman                 ref&lt;br /&gt;
 2007-05-06 14:52:01  127.0.0.1       {AR}Major Zeman                 ref badpassword&lt;br /&gt;
 2007-05-06 14:52:05  127.0.0.1       {AR}Major Zeman                 ref goodpassword&lt;br /&gt;
 2007-05-06 14:52:09  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
 2007-05-06 14:52:12  127.0.0.1       {AR}Major Zeman               R ref logout&lt;br /&gt;
 2007-05-06 14:52:16  127.0.0.1       {AR}Major Zeman                 ref somecommand&lt;br /&gt;
 2007-05-06 14:52:24  ---             [console]                     C ref referee 0&lt;br /&gt;
 2007-05-06 14:52:27  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
The zip contains two files:&lt;br /&gt;
* refmon.lua - script itself, needed&lt;br /&gt;
* etconst.lua - [[User:ReyalP|ReyalP]]&#039;s header file, needed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Rules ==&lt;br /&gt;
version: 0.1&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 14.9.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/rules.lua rules.lua] (you&#039;ll need to create &#039;&#039;&#039;rules.txt&#039;&#039;&#039; file yourself in the server&#039;s etpro directory)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
This simple mod just prints contents of a textfile to a client who types in &#039;&#039;&#039;/rules&#039;&#039;&#039; command&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Whenever a client issues the /rules command, the mod will print back the content of &#039;&#039;&#039;rules.txt&#039;&#039;&#039; file on server to the client&#039;s console. Note that you&#039;ll have to create the rules.txt file in the same directory where rules.lua is. The file may contain color codes. Empty lines get eaten up, so use line with space(s) instead. Any line ednigs (win|unix|mac) should get parsed correctly.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Client console command ===&lt;br /&gt;
* &#039;&#039;&#039;/rules&#039;&#039;&#039; - prints the rules file content to the client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2806</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2806"/>
		<updated>2007-09-14T11:34:26Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: some more code fragments&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently (= for about last 3 years) found at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the function returns short version of guid and should NOT be used for authentication purposes!&lt;br /&gt;
&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s IP ===&lt;br /&gt;
Anoter simple function, this one returns IP of the player in given slot.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the IP, too, can be spoofed. Use [[User:ReyalP|ReyalP]]&#039;s userinfocheck.lua or better his combinedfixes.lua mod on your server to at least lower this risk.&lt;br /&gt;
&lt;br /&gt;
 -- gets target&#039;s IP without port&lt;br /&gt;
 function getIP(target)&lt;br /&gt;
     if (target == nil) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo(target)&lt;br /&gt;
     local ip = et.Info_ValueForKey(userinfo, &amp;quot;ip&amp;quot;)&lt;br /&gt;
     -- strip port&lt;br /&gt;
     ip = string.sub(ip,string.find(ip,&amp;quot;(%d+%.%d+%.%d+%.%d+)&amp;quot;))&lt;br /&gt;
     return ip&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get client&#039;s ref status ===&lt;br /&gt;
Third function is used to check whether the target client is logged in as referee.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; It&#039;s not very well known fact that there are actually three levels of referee status: client can either not be referee at all, or be a referee that was voted in or made referee by another referee, and a referee that logged in using referee password. This function however only discriminates between the ordinary levels of &amp;quot;not referee&amp;quot; - &amp;quot;referee&amp;quot; (e.g. doesn&#039;t make difference between the two types of referees).&lt;br /&gt;
&lt;br /&gt;
 -- returns referee status of target&lt;br /&gt;
 function getRefStatus(target)&lt;br /&gt;
       local isref = et.Info_ValueForKey(et.trap_GetConfigstring(et.CS_PLAYERS + target), &amp;quot;ref&amp;quot;)&lt;br /&gt;
       if isref ~= &amp;quot;0&amp;quot; then&lt;br /&gt;
           return true&lt;br /&gt;
     else&lt;br /&gt;
         return false&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Indent ===&lt;br /&gt;
Another simple function. This one is useful if you need to print a list of basically anything and want the text to be arranged in columns.&lt;br /&gt;
&lt;br /&gt;
 -- makes a string at least &amp;lt;length&amp;gt; characters long, adding spaces behind the original string if needed&lt;br /&gt;
 function indent(str, length)&lt;br /&gt;
     local len&lt;br /&gt;
 &lt;br /&gt;
     len = math.min(string.len(str), length)&lt;br /&gt;
     str = str .. string.rep(&amp;quot; &amp;quot;, length - len)&lt;br /&gt;
 &lt;br /&gt;
     return str&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Note that it never shortens the text so you might end up with a garbled table anyways, but if you set the length to a reasonable number (e.g. 15 for IP - it&#039;s max length IPv4 can have), you should be fine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Read content of a text file on server ===&lt;br /&gt;
This function reads contents of a given file and returns an array of its lines. It can handle all line endings (win|unix|mac). As a price for that though, it will eat up any empty lines.&lt;br /&gt;
&lt;br /&gt;
 -- reads file and returns string array of rows (indexed from 1) and number of rows&lt;br /&gt;
 function readFile(filename)&lt;br /&gt;
     local fd, len&lt;br /&gt;
     local rows = {}&lt;br /&gt;
 &lt;br /&gt;
     fd, len = et.trap_FS_FOpenFile(filename, et.FS_READ)&lt;br /&gt;
 &lt;br /&gt;
     if len == -1 then&lt;br /&gt;
         return rows, 0&lt;br /&gt;
     else&lt;br /&gt;
         --read it all&lt;br /&gt;
         local filestr = et.trap_FS_Read(fd, len)&lt;br /&gt;
 &lt;br /&gt;
         local rowcount = 0&lt;br /&gt;
         for line in string.gfind(filestr, &amp;quot;[^\r\n]+&amp;quot;) do&lt;br /&gt;
             rowcount = rowcount + 1&lt;br /&gt;
             rows[rowcount] = line&lt;br /&gt;
         end&lt;br /&gt;
 &lt;br /&gt;
             et.trap_FS_FCloseFile(fd)&lt;br /&gt;
             return rows, rowcount&lt;br /&gt;
       end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in CleintCommand trap:&lt;br /&gt;
&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;ll passing the command to ET&lt;br /&gt;
&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.7 &amp;lt;small&amp;gt;(changelog is inside lua script)&amp;lt;/small&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 20.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== RefMon ==&lt;br /&gt;
version: 0.2&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 8.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/refmon.lua lua] (requires [http://www.sonic.net/~rfm/et/lua/etconst.lua etconst.lua])]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Referee Monitor mod - a lua script that logs all ref commands to a separate, easy to read log.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Referee monitor writes a log record for any ref command issued by either client or server console. The log contains these columns:&lt;br /&gt;
* date and time (in server&#039;s timezone)&lt;br /&gt;
* IP of the client who issued the command (empty for server commands, note that IP can be spoofed)&lt;br /&gt;
* name of the client who issued the command (or [console])&lt;br /&gt;
* flag - for easy orientation in the log, R means the player was logged in as ref, C means console command, empty otherwise&lt;br /&gt;
* command issued&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Server console command ===&lt;br /&gt;
* &#039;&#039;&#039;/reflog [optional line number]&#039;&#039;&#039; - prints part of the log to console. The behaviour is similar to !showbans in pub - without parameter, it returns last rows in file, positive number gives you rows starting at that index, negative gives you rows starting at index (-number) from end. Number of rows returned at once is determined by PRINT_ROWS constant (20 by default).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Example log file ===&lt;br /&gt;
 2007-05-06 14:51:57  127.0.0.1       {AR}Major Zeman                 ref&lt;br /&gt;
 2007-05-06 14:52:01  127.0.0.1       {AR}Major Zeman                 ref badpassword&lt;br /&gt;
 2007-05-06 14:52:05  127.0.0.1       {AR}Major Zeman                 ref goodpassword&lt;br /&gt;
 2007-05-06 14:52:09  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
 2007-05-06 14:52:12  127.0.0.1       {AR}Major Zeman               R ref logout&lt;br /&gt;
 2007-05-06 14:52:16  127.0.0.1       {AR}Major Zeman                 ref somecommand&lt;br /&gt;
 2007-05-06 14:52:24  ---             [console]                     C ref referee 0&lt;br /&gt;
 2007-05-06 14:52:27  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
The zip contains two files:&lt;br /&gt;
* refmon.lua - script itself, needed&lt;br /&gt;
* etconst.lua - [[User:ReyalP|ReyalP]]&#039;s header file, needed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2757</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2757"/>
		<updated>2007-06-05T09:29:14Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently (= for about last 3 years) found at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the function returns short version of guid and should NOT be used for authentication purposes!&lt;br /&gt;
&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Indent ===&lt;br /&gt;
Another simple function. This one is useful if you need to print a list of basically anything and want the text to be arranged in columns.&lt;br /&gt;
&lt;br /&gt;
 -- makes a string at least &amp;lt;length&amp;gt; characters long, adding spaces behind the original string if needed&lt;br /&gt;
 function indent(str, length)&lt;br /&gt;
     local len&lt;br /&gt;
 &lt;br /&gt;
     len = math.min(string.len(str), length)&lt;br /&gt;
     str = str .. string.rep(&amp;quot; &amp;quot;, length - len)&lt;br /&gt;
 &lt;br /&gt;
     return str&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Note that it never shortens the text so you might end up with a garbled table anyways, but if you set the length to a reasonable number (e.g. 15 for IP - it&#039;s max length IPv4 can have), you should be fine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in CleintCommand trap:&lt;br /&gt;
&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;ll passing the command to ET&lt;br /&gt;
&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.7 &amp;lt;small&amp;gt;(changelog is inside lua script)&amp;lt;/small&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 20.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== RefMon ==&lt;br /&gt;
version: 0.2&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 8.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/refmon.lua lua] (requires [http://www.sonic.net/~rfm/et/lua/etconst.lua etconst.lua])]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Referee Monitor mod - a lua script that logs all ref commands to a separate, easy to read log.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Referee monitor writes a log record for any ref command issued by either client or server console. The log contains these columns:&lt;br /&gt;
* date and time (in server&#039;s timezone)&lt;br /&gt;
* IP of the client who issued the command (empty for server commands, note that IP can be spoofed)&lt;br /&gt;
* name of the client who issued the command (or [console])&lt;br /&gt;
* flag - for easy orientation in the log, R means the player was logged in as ref, C means console command, empty otherwise&lt;br /&gt;
* command issued&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Server console command ===&lt;br /&gt;
* &#039;&#039;&#039;/reflog [optional line number]&#039;&#039;&#039; - prints part of the log to console. The behaviour is similar to !showbans in pub - without parameter, it returns last rows in file, positive number gives you rows starting at that index, negative gives you rows starting at index (-number) from end. Number of rows returned at once is determined by PRINT_ROWS constant (20 by default).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Example log file ===&lt;br /&gt;
 2007-05-06 14:51:57  127.0.0.1       {AR}Major Zeman                 ref&lt;br /&gt;
 2007-05-06 14:52:01  127.0.0.1       {AR}Major Zeman                 ref badpassword&lt;br /&gt;
 2007-05-06 14:52:05  127.0.0.1       {AR}Major Zeman                 ref goodpassword&lt;br /&gt;
 2007-05-06 14:52:09  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
 2007-05-06 14:52:12  127.0.0.1       {AR}Major Zeman               R ref logout&lt;br /&gt;
 2007-05-06 14:52:16  127.0.0.1       {AR}Major Zeman                 ref somecommand&lt;br /&gt;
 2007-05-06 14:52:24  ---             [console]                     C ref referee 0&lt;br /&gt;
 2007-05-06 14:52:27  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
The zip contains two files:&lt;br /&gt;
* refmon.lua - script itself, needed&lt;br /&gt;
* etconst.lua - [[User:ReyalP|ReyalP]]&#039;s header file, needed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=Talk:Fieldname&amp;diff=2751</id>
		<title>Talk:Fieldname</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=Talk:Fieldname&amp;diff=2751"/>
		<updated>2007-05-24T23:04:01Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;someone feel free to make this table pretty.&lt;br /&gt;
&lt;br /&gt;
Roger that. --Rookie One 03:31, 13 November 2005 (PST)&lt;br /&gt;
&lt;br /&gt;
// Comment by Deus 13:22, 13 November 2005 (CET)&lt;br /&gt;
I liked the former one more.&lt;br /&gt;
I thought about some colorisation like red for readonly and green for r/w. maybe some mouseover stuff, or just the one tr light the next darker, to have a better viewability ?&lt;br /&gt;
// End of Deus Comment&lt;br /&gt;
&lt;br /&gt;
Alright, I&#039;ll restore the previous borders and add some colour. --Rookie One 04:33, 13 November 2005 (PST)&lt;br /&gt;
&lt;br /&gt;
That was just my suggestion. Maybe this differs from banis view of beautification :) --Deus 04:46, 13 November 2005 (PST)&lt;br /&gt;
&lt;br /&gt;
== use of color...bad! ==&lt;br /&gt;
&lt;br /&gt;
use of color to convey specific data (ro/rw) is bad. red/green is the worst possible choice too :)&amp;lt;br&amp;gt;&lt;br /&gt;
consider someone who is colorblind. check the article via http://colorfilter.wickline.org/ to see how bad this is.&lt;br /&gt;
but it looks bad even for those who aren&#039;t color blind :P&lt;br /&gt;
&lt;br /&gt;
Yeah, reyalP, I also thought it&#039;s weird to initialize the table like that, but wasn&#039;t sure. ;) --Rookie One 06:26, 17 November 2005 (PST)&lt;br /&gt;
&lt;br /&gt;
== Question ==&lt;br /&gt;
&lt;br /&gt;
Is there a article describing each fieldname?&lt;br /&gt;
: No. To understand what they do, you need to look at the ET gamecode. Some Quake3 coding articles might also help you. It would be nice if someone documented some of the more common/interesting ones, but documenting them all would be a huge task. In the future, if you are looking for something, you can see all the pages in the wiki at [[Special:Allpages]]. If you have questions about specific fields, you can try asking on the [http://bani.anime.net/banimod/forums/viewforum.php?f=17 ETPro modding forum] Also, please sign your comments with &amp;lt;nowiki&amp;gt;~~~~&amp;lt;/nowiki&amp;gt; &lt;br /&gt;
::- [[User:ReyalP|ReyalP]] 18:53, 15 May 2006 (PDT)&lt;br /&gt;
::I added descriptions of fields I *think* I know meaning of. Most times it&#039;s a wild guess based on my observations tho. Hope someone will correct my mistakes and add some more. -[[User:Major Zeman|Major Zeman]] 02:28, 20 May 2007 (PDT)&lt;br /&gt;
&lt;br /&gt;
I ve waited for a week and my account is still not activated by admin :&amp;lt;&lt;br /&gt;
&lt;br /&gt;
[[User:Kotoko|Kotoko]] 00:01, 16 May 2006 (PDT)&lt;br /&gt;
&lt;br /&gt;
== making &#039;flags&#039; writable ==&lt;br /&gt;
&lt;br /&gt;
What about making the field &#039;&#039;flags&#039;&#039; read-write? I run a trickjump server and it would be very handy if I could give people the nofatigue flag so they never go out of stamina.&lt;br /&gt;
:Maybe [[User:Nano|Nano]]&#039;s adrenaline.lua is a solution for you? (yeah I know responding to one year old commants again) -[[User:Major Zeman|Major Zeman]] 09:44, 21 May 2007 (PDT)&lt;br /&gt;
&lt;br /&gt;
== ps.velocity ==&lt;br /&gt;
Any chance of getting ps.velocity field as R/W in some next etpro release? -[[User:Major Zeman|Major Zeman]] 09:44, 21 May 2007 (PDT)&lt;br /&gt;
: Yes, this will most likely be in the next release. The lua API talk page is the place to request features BTW. -15:13, 24 May 2007 (PDT)&lt;br /&gt;
::Okay. Also thanks for putting that warning there - good idea. -[[User:Major Zeman|Major Zeman]] 16:04, 24 May 2007 (PDT)&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=Talk:Fieldname&amp;diff=2748</id>
		<title>Talk:Fieldname</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=Talk:Fieldname&amp;diff=2748"/>
		<updated>2007-05-21T16:44:33Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: ps.velocity&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;someone feel free to make this table pretty.&lt;br /&gt;
&lt;br /&gt;
Roger that. --Rookie One 03:31, 13 November 2005 (PST)&lt;br /&gt;
&lt;br /&gt;
// Comment by Deus 13:22, 13 November 2005 (CET)&lt;br /&gt;
I liked the former one more.&lt;br /&gt;
I thought about some colorisation like red for readonly and green for r/w. maybe some mouseover stuff, or just the one tr light the next darker, to have a better viewability ?&lt;br /&gt;
// End of Deus Comment&lt;br /&gt;
&lt;br /&gt;
Alright, I&#039;ll restore the previous borders and add some colour. --Rookie One 04:33, 13 November 2005 (PST)&lt;br /&gt;
&lt;br /&gt;
That was just my suggestion. Maybe this differs from banis view of beautification :) --Deus 04:46, 13 November 2005 (PST)&lt;br /&gt;
&lt;br /&gt;
== use of color...bad! ==&lt;br /&gt;
&lt;br /&gt;
use of color to convey specific data (ro/rw) is bad. red/green is the worst possible choice too :)&amp;lt;br&amp;gt;&lt;br /&gt;
consider someone who is colorblind. check the article via http://colorfilter.wickline.org/ to see how bad this is.&lt;br /&gt;
but it looks bad even for those who aren&#039;t color blind :P&lt;br /&gt;
&lt;br /&gt;
Yeah, reyalP, I also thought it&#039;s weird to initialize the table like that, but wasn&#039;t sure. ;) --Rookie One 06:26, 17 November 2005 (PST)&lt;br /&gt;
&lt;br /&gt;
== Question ==&lt;br /&gt;
&lt;br /&gt;
Is there a article describing each fieldname?&lt;br /&gt;
: No. To understand what they do, you need to look at the ET gamecode. Some Quake3 coding articles might also help you. It would be nice if someone documented some of the more common/interesting ones, but documenting them all would be a huge task. In the future, if you are looking for something, you can see all the pages in the wiki at [[Special:Allpages]]. If you have questions about specific fields, you can try asking on the [http://bani.anime.net/banimod/forums/viewforum.php?f=17 ETPro modding forum] Also, please sign your comments with &amp;lt;nowiki&amp;gt;~~~~&amp;lt;/nowiki&amp;gt; &lt;br /&gt;
::- [[User:ReyalP|ReyalP]] 18:53, 15 May 2006 (PDT)&lt;br /&gt;
::I added descriptions of fields I *think* I know meaning of. Most times it&#039;s a wild guess based on my observations tho. Hope someone will correct my mistakes and add some more. -[[User:Major Zeman|Major Zeman]] 02:28, 20 May 2007 (PDT)&lt;br /&gt;
&lt;br /&gt;
I ve waited for a week and my account is still not activated by admin :&amp;lt;&lt;br /&gt;
&lt;br /&gt;
[[User:Kotoko|Kotoko]] 00:01, 16 May 2006 (PDT)&lt;br /&gt;
&lt;br /&gt;
== making &#039;flags&#039; writable ==&lt;br /&gt;
&lt;br /&gt;
What about making the field &#039;&#039;flags&#039;&#039; read-write? I run a trickjump server and it would be very handy if I could give people the nofatigue flag so they never go out of stamina.&lt;br /&gt;
:Maybe [[User:Nano|Nano]]&#039;s adrenaline.lua is a solution for you? (yeah I know responding to one year old commants again) -[[User:Major Zeman|Major Zeman]] 09:44, 21 May 2007 (PDT)&lt;br /&gt;
&lt;br /&gt;
== ps.velocity ==&lt;br /&gt;
Any chance of getting ps.velocity field as R/W in some next etpro release? -[[User:Major Zeman|Major Zeman]] 09:44, 21 May 2007 (PDT)&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=Talk:Fieldname&amp;diff=2747</id>
		<title>Talk:Fieldname</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=Talk:Fieldname&amp;diff=2747"/>
		<updated>2007-05-20T09:28:18Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: /* Question */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;someone feel free to make this table pretty.&lt;br /&gt;
&lt;br /&gt;
Roger that. --Rookie One 03:31, 13 November 2005 (PST)&lt;br /&gt;
&lt;br /&gt;
// Comment by Deus 13:22, 13 November 2005 (CET)&lt;br /&gt;
I liked the former one more.&lt;br /&gt;
I thought about some colorisation like red for readonly and green for r/w. maybe some mouseover stuff, or just the one tr light the next darker, to have a better viewability ?&lt;br /&gt;
// End of Deus Comment&lt;br /&gt;
&lt;br /&gt;
Alright, I&#039;ll restore the previous borders and add some colour. --Rookie One 04:33, 13 November 2005 (PST)&lt;br /&gt;
&lt;br /&gt;
That was just my suggestion. Maybe this differs from banis view of beautification :) --Deus 04:46, 13 November 2005 (PST)&lt;br /&gt;
&lt;br /&gt;
== use of color...bad! ==&lt;br /&gt;
&lt;br /&gt;
use of color to convey specific data (ro/rw) is bad. red/green is the worst possible choice too :)&amp;lt;br&amp;gt;&lt;br /&gt;
consider someone who is colorblind. check the article via http://colorfilter.wickline.org/ to see how bad this is.&lt;br /&gt;
but it looks bad even for those who aren&#039;t color blind :P&lt;br /&gt;
&lt;br /&gt;
Yeah, reyalP, I also thought it&#039;s weird to initialize the table like that, but wasn&#039;t sure. ;) --Rookie One 06:26, 17 November 2005 (PST)&lt;br /&gt;
&lt;br /&gt;
== Question ==&lt;br /&gt;
&lt;br /&gt;
Is there a article describing each fieldname?&lt;br /&gt;
: No. To understand what they do, you need to look at the ET gamecode. Some Quake3 coding articles might also help you. It would be nice if someone documented some of the more common/interesting ones, but documenting them all would be a huge task. In the future, if you are looking for something, you can see all the pages in the wiki at [[Special:Allpages]]. If you have questions about specific fields, you can try asking on the [http://bani.anime.net/banimod/forums/viewforum.php?f=17 ETPro modding forum] Also, please sign your comments with &amp;lt;nowiki&amp;gt;~~~~&amp;lt;/nowiki&amp;gt; &lt;br /&gt;
::- [[User:ReyalP|ReyalP]] 18:53, 15 May 2006 (PDT)&lt;br /&gt;
::I added descriptions of fields I *think* I know meaning of. Most times it&#039;s a wild guess based on my observations tho. Hope someone will correct my mistakes and add some more. -[[User:Major Zeman|Major Zeman]] 02:28, 20 May 2007 (PDT)&lt;br /&gt;
&lt;br /&gt;
I ve waited for a week and my account is still not activated by admin :&amp;lt;&lt;br /&gt;
&lt;br /&gt;
[[User:Kotoko|Kotoko]] 00:01, 16 May 2006 (PDT)&lt;br /&gt;
&lt;br /&gt;
== making &#039;flags&#039; writable ==&lt;br /&gt;
&lt;br /&gt;
What about making the field &#039;&#039;flags&#039;&#039; read-write? I run a trickjump server and it would be very handy if I could give people the nofatigue flag so they never go out of stamina.&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=Fieldname&amp;diff=2746</id>
		<title>Fieldname</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=Fieldname&amp;diff=2746"/>
		<updated>2007-05-20T09:23:28Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: field detailed descriptions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOEDITSECTION__&lt;br /&gt;
==Entity Fieldnames==&lt;br /&gt;
List of fields supported by [[Lua Mod API#entities|et.gentity_get() and et.gentity_set()]] functions&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pitatable columns=3 headlines=&amp;quot;field;type;access&amp;quot; widths=&amp;quot;180;120;60&amp;quot; headerfontcolor=&amp;quot;#FFFFFF&amp;quot;&amp;gt;&lt;br /&gt;
activator;entity;RO;&lt;br /&gt;
chain;entity;RW;&lt;br /&gt;
classname;string;RW;&lt;br /&gt;
client.inactivityTime;integer;RW;&lt;br /&gt;
client.inactivityWarning;qboolean;RW;&lt;br /&gt;
clipmask;integer;?;&lt;br /&gt;
closespeed;float;RW;&lt;br /&gt;
count;integer;RW;&lt;br /&gt;
count2;integer;RW;&lt;br /&gt;
damage;integer;RW;&lt;br /&gt;
deathType;meansOfDeath_t;RW;&lt;br /&gt;
delay;float;RW;&lt;br /&gt;
dl_atten;integer;RW;&lt;br /&gt;
dl_color;vec3;RW;&lt;br /&gt;
dl_shader;string;RO;&lt;br /&gt;
dl_stylestring;string;RO;&lt;br /&gt;
duration;float;RW;&lt;br /&gt;
end_size;integer;RW;&lt;br /&gt;
enemy;entity;RW;&lt;br /&gt;
flags;bitflag;RO;&lt;br /&gt;
harc;float;RW;&lt;br /&gt;
health;integer;RW;&lt;br /&gt;
inuse;qboolean;RO;&lt;br /&gt;
isProp;qboolean;RO;&lt;br /&gt;
item;string;RW;&lt;br /&gt;
key;integer;RW;&lt;br /&gt;
message;string;RW;&lt;br /&gt;
methodOfDeath;integer;RW;&lt;br /&gt;
mg42BaseEnt;integer;RW;&lt;br /&gt;
missionLevel;integer;RW;&lt;br /&gt;
model;string;RO;&lt;br /&gt;
model2;string;RO;&lt;br /&gt;
nextTrain;entity;RW;&lt;br /&gt;
noise_index;integer;RW;&lt;br /&gt;
origin;vec3;RW;&lt;br /&gt;
pers.connected;connected_t;?;&lt;br /&gt;
pers.netname;string;?;&lt;br /&gt;
pers.localClient;qboolean;?;&lt;br /&gt;
pers.initialSpawn;qboolean;?; &lt;br /&gt;
pers.enterTime;integer;?;&lt;br /&gt;
pers.connectTime;integer;?; &lt;br /&gt;
pers.teamState.state;teamstatestate_t;?;&lt;br /&gt;
pers.voteCount;integer;?;&lt;br /&gt;
pers.teamVoteCount;integer;?; &lt;br /&gt;
pers.complaints;integer;?; &lt;br /&gt;
pers.complaintClient;integer;?; &lt;br /&gt;
pers.complaintEndTime;integer;?; &lt;br /&gt;
pers.lastReinforceTime;integer;?; &lt;br /&gt;
pers.applicationClient;integer;?; &lt;br /&gt;
pers.applicationEndTime;integer;?; &lt;br /&gt;
pers.invitationClient;integer;?; &lt;br /&gt;
pers.invitationEndTime;integer;?; &lt;br /&gt;
pers.propositionClient;integer;?; &lt;br /&gt;
pers.propositionClient2;integer;?; &lt;br /&gt;
pers.propositionEndTime;integer;?; &lt;br /&gt;
pers.autofireteamEndTime;integer;?; &lt;br /&gt;
pers.autofireteamCreateEndTime;integer;?; &lt;br /&gt;
pers.autofireteamJoinEndTime;integer;?; &lt;br /&gt;
pers.lastSpawnTime;integer;?;&lt;br /&gt;
pers.ready;qboolean;?;&lt;br /&gt;
prevTrain;entity;RW;&lt;br /&gt;
props_frame_state;integer;RO;&lt;br /&gt;
ps.stats;integer array;RW; &lt;br /&gt;
ps.persistant;integer array;RW;&lt;br /&gt;
ps.ping;integer;?;&lt;br /&gt;
ps.powerups;integer array;RW;&lt;br /&gt;
ps.ammo;integer array;RW; &lt;br /&gt;
ps.ammoclip;integer array;RW;&lt;br /&gt;
r.absmax;vec3;RO;&lt;br /&gt;
r.absmin;vec3;RO;&lt;br /&gt;
r.bmodel;qboolean;RO;&lt;br /&gt;
r.contents;integer;RW;&lt;br /&gt;
r.currentAngles;vec3;RW;&lt;br /&gt;
r.currentOrigin;vec3;RW;&lt;br /&gt;
r.eventTime;integer;RW;&lt;br /&gt;
r.linkcount;integer;RO;&lt;br /&gt;
r.linked;qboolean;RO;&lt;br /&gt;
r.maxs;vec3;RW;&lt;br /&gt;
r.mins;vec3;RW;&lt;br /&gt;
r.ownerNum;integer;RW;&lt;br /&gt;
r.singleClient;integer;RW;&lt;br /&gt;
r.svFlags;integer;RW;&lt;br /&gt;
r.worldflags;integer;RO;&lt;br /&gt;
radius;integer;RW;&lt;br /&gt;
random;float;RW;&lt;br /&gt;
rotate;vec3;RW;&lt;br /&gt;
s.angles;vec3;RW;&lt;br /&gt;
s.angles2;vec3;RW;&lt;br /&gt;
s.apos;trajectory;RW;&lt;br /&gt;
s.clientNum;integer;RW;&lt;br /&gt;
s.constantLight;integer;RW;&lt;br /&gt;
s.density;integer;RW;&lt;br /&gt;
s.dl_intensity;integer;RW;&lt;br /&gt;
s.dmgFlags;integer;RW;&lt;br /&gt;
s.eFlags;integer;RW;&lt;br /&gt;
s.eType;integer;?;&lt;br /&gt;
s.effect1Time;integer;RW;&lt;br /&gt;
s.effect2Time;integer;RW;&lt;br /&gt;
s.effect3Time;integer;RW;&lt;br /&gt;
s.frame;integer;RW;&lt;br /&gt;
s.groundEntityNum;integer;RO;&lt;br /&gt;
s.loopSound;integer;RW;&lt;br /&gt;
s.modelindex;integer;RW;&lt;br /&gt;
s.modelindex2;integer;RW;&lt;br /&gt;
s.number;integer;RO;&lt;br /&gt;
s.onFireEnd;integer;RW;&lt;br /&gt;
s.onFireStart;integer;RW;&lt;br /&gt;
s.origin;vec3;?;&lt;br /&gt;
s.origin2;vec3;?;&lt;br /&gt;
s.pos;trajectory;RW;&lt;br /&gt;
s.powerups;integer;RO;&lt;br /&gt;
s.solid;integer;RW;&lt;br /&gt;
s.teamNum;integer;RW;&lt;br /&gt;
s.time;integer;RW;&lt;br /&gt;
s.time2;integer;RW;&lt;br /&gt;
s.weapon;integer;RO;&lt;br /&gt;
scriptName;string;RO;&lt;br /&gt;
sess.sessionTeam;team_t;RW;&lt;br /&gt;
sess.spectatorTime;integer;RW;&lt;br /&gt;
sess.spectatorState;spectatorState_t;RW;&lt;br /&gt;
sess.spectatorClient;entity;RW;&lt;br /&gt;
sess.latchSpectatorClient;integer;RW;&lt;br /&gt;
sess.playerType;integer;RW;&lt;br /&gt;
sess.playerWeapon;integer;RW;&lt;br /&gt;
sess.playerWeapon2;integer;RW;&lt;br /&gt;
sess.spawnObjectiveIndex;integer;RW;&lt;br /&gt;
sess.latchPlayerType;integer;RW;&lt;br /&gt;
sess.latchPlayerWeapon;integer;RW;&lt;br /&gt;
sess.latchPlayerWeapon2;integer;RW;&lt;br /&gt;
sess.damage_given;integer;RW;&lt;br /&gt;
sess.damage_received;integer;RW;&lt;br /&gt;
sess.deaths;integer;RW;&lt;br /&gt;
sess.game_points;integer;RW;&lt;br /&gt;
sess.gibs;integer;RW;&lt;br /&gt;
sess.kills;integer;RW;&lt;br /&gt;
sess.medals;integer array;RW;&lt;br /&gt;
sess.muted;qboolean;RW;&lt;br /&gt;
sess.rank;integer;RW;&lt;br /&gt;
sess.referee;integer;RW;&lt;br /&gt;
sess.rounds;integer;RW;&lt;br /&gt;
sess.semiadmin;integer;RW;&lt;br /&gt;
sess.skill;integer array;RW;&lt;br /&gt;
sess.spec_invite;integer;RW;&lt;br /&gt;
sess.spec_team;integer;RW;&lt;br /&gt;
sess.suicides;integer;RW;&lt;br /&gt;
sess.team_damage;integer;RW;&lt;br /&gt;
sess.team_kills;integer;RW;&lt;br /&gt;
sess.team_received;integer;RW;&lt;br /&gt;
sess.aWeaponStats;weapon_stat_t;RW;&lt;br /&gt;
spawnflags;integer;RO;&lt;br /&gt;
spawnitem;string;RO;&lt;br /&gt;
speed;float;RW;&lt;br /&gt;
splashDamage;integer;RW;&lt;br /&gt;
splashMethodOfDeath;integer;RW;&lt;br /&gt;
splashRadius;integer;RW;&lt;br /&gt;
start_size;integer;RW;&lt;br /&gt;
tagName;string;RO;&lt;br /&gt;
tagParent;entity;RW;&lt;br /&gt;
takedamage;boolean;RW;&lt;br /&gt;
tankLink;entity;RW;&lt;br /&gt;
target;string;RW;&lt;br /&gt;
TargetAngles;vec3;RW;&lt;br /&gt;
TargetFlag;integer;RO;&lt;br /&gt;
targetname;string;RO;&lt;br /&gt;
teamchain;entity;RW;&lt;br /&gt;
teammaster;entity;RW;&lt;br /&gt;
track;string;RO;&lt;br /&gt;
varc;float;RW;&lt;br /&gt;
wait;float;RW;&lt;br /&gt;
waterlevel;integer;RO;&lt;br /&gt;
watertype;integer;RO;&lt;br /&gt;
&amp;lt;/pitatable&amp;gt;&lt;br /&gt;
:&#039;&#039;note&#039;&#039;: all the sess.* fields will return nil unless the entity is associated with client slot &amp;lt; sv_maxclients.&lt;br /&gt;
:&#039;&#039;note&#039;&#039;: all array variables need to be get or set with an additional parameter.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==ET variable types==&lt;br /&gt;
&lt;br /&gt;
===qboolean===&lt;br /&gt;
:a &#039;&#039;&#039;qboolean&#039;&#039;&#039; is a boolean value.&lt;br /&gt;
:0 is represented by the lua value false&lt;br /&gt;
:1 is represented by the lua value true&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===vec3===&lt;br /&gt;
:a &#039;&#039;&#039;vec3_t&#039;&#039;&#039; is a 3-element array of numbers (C definition: typedef float vec3_t[3];). It is usually used to store and process coordinates in 3D space.&amp;lt;br&amp;gt;&lt;br /&gt;
:In etpro-lua a vector is an array (table indexed by integers) containing 3 numbers. It can be accessed by&lt;br /&gt;
:doing:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
origin = et.gentity_get(entNum,&amp;quot;r.currentOrigin&amp;quot;) --a vec3 value&lt;br /&gt;
x,y,z = origin[1],origin[2],origin[3]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===array===&lt;br /&gt;
:The fields listed as having type &#039;&#039;&#039;array&#039;&#039;&#039; represent an entity value which is an array. Individual elements of the array are accessed by passing the desired index in the &#039;&#039;arrayindex&#039;&#039; argument to the et.gentity_get and et.gentity_set functions. Valid array indexes are integers from 0 up to some field specific maximum. The &#039;&#039;arrayindex&#039;&#039; argument is &#039;&#039;&#039;required&#039;&#039;&#039; when accessing array type fields, so only one element of an array can be accessed in a given call to the gentity_* functions.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===trajectory===&lt;br /&gt;
:a &#039;&#039;&#039;trajectory&#039;&#039;&#039; is returned as a lua table described below&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  trDuration = &amp;lt;number&amp;gt;, --- int&lt;br /&gt;
  trTime = &amp;lt;number&amp;gt;, -- int&lt;br /&gt;
  trType = &amp;lt;number&amp;gt;, -- see below for allowed values&lt;br /&gt;
  trBase = &amp;lt;vec3_t&amp;gt;, -- vec3, as described above&lt;br /&gt;
  trDelta = &amp;lt;vec3_t&amp;gt; -- also a vec3&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
: the allowed values for trType (along with the enum names and original comments from the ET source), are as follows. Note &lt;br /&gt;
: that not all values make sense for all entity types &lt;br /&gt;
&amp;lt;pitatable columns=3 headlines=&amp;quot;number;type;discription&amp;quot; widths=&amp;quot;40;160;450&amp;quot; headerfontcolor=&amp;quot;#FFFFFF&amp;quot;&amp;gt;&lt;br /&gt;
1;TR_STATIONARY;&lt;br /&gt;
2;TR_INTERPOLATE;non-parametric, but interpolate between snapshots;&lt;br /&gt;
3;TR_LINEAR;&lt;br /&gt;
4;TR_LINEAR_STOP;&lt;br /&gt;
5;TR_LINEAR_STOP_BACK;reverse movement can be different than forward;&lt;br /&gt;
6;TR_SINE;value = base + sin( time / duration ) * delta;&lt;br /&gt;
7;TR_GRAVITY;&lt;br /&gt;
8;TR_GRAVITY_LOW;&lt;br /&gt;
9;TR_GRAVITY_FLOAT;super low grav with no gravity acceleration;&lt;br /&gt;
10;TR_GRAVITY_PAUSED;has stopped, but trace to see if it should be switched back to TR_GRAVITY;&lt;br /&gt;
11;TR_ACCELERATE;&lt;br /&gt;
12;TR_DECCELERATE;&lt;br /&gt;
13;TR_SPLINE;&lt;br /&gt;
14;TR_LINEAR_PATH;&lt;br /&gt;
&amp;lt;/pitatable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===entity===&lt;br /&gt;
:The fields listed as having type &#039;&#039;&#039;enitity&#039;&#039;&#039; return an entity number or nil. Entity numbers are integers from 0 through 1023. Some of the entity numbers have special meanings:&lt;br /&gt;
:0 - (sv_privateclients - 1) are reserved for clients who connect with the private slot password&lt;br /&gt;
:0 - 63 are reserved for clients. A client&#039;s entity number is also its client number (as shown by /players for example)&lt;br /&gt;
:1022 is the &#039;&#039;&#039;worldspawn&#039;&#039;&#039; entity&lt;br /&gt;
:1023 is &#039;&#039;&#039;ENTITYNUM_NONE&#039;&#039;&#039; which is used instead of null in C under some circumstances to indicate no entity. This is needed where an entity number will be passed over the network.&lt;br /&gt;
:&#039;&#039;Note&#039;&#039;: Some other fields not listed as type &#039;entity&#039; may take an entity number value. &#039;&#039;&#039;mg42BaseEnt&#039;&#039;&#039; and &#039;&#039;&#039;s.number&#039;&#039;&#039; are examples.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===meansOfDeath===&lt;br /&gt;
:a &#039;&#039;&#039;meansOfDeath_t&#039;&#039;&#039; is a number indicating the [[etdamage|Method of Death]] Click  [[etdamage|here]] for a list with possible value&#039;s&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Field details ==&lt;br /&gt;
=== classname ===&lt;br /&gt;
Entity class name.&lt;br /&gt;
* &#039;&#039;nil&#039;&#039; if entity is not in use&lt;br /&gt;
* &#039;&#039;player&#039;&#039; for game client&lt;br /&gt;
* &#039;&#039;team_WOLF_objective&#039;&#039; for objective entity&lt;br /&gt;
etc.&lt;br /&gt;
&lt;br /&gt;
=== client.inactivityTime ===&lt;br /&gt;
Timestamp of when the client was last active. Seems to be 44000000 + server uptime in ms.&lt;br /&gt;
&lt;br /&gt;
=== damage ===&lt;br /&gt;
Probably related to damage entity deals (e.g. fire, barbed wire). 2 for player entity.&lt;br /&gt;
&lt;br /&gt;
=== health ===&lt;br /&gt;
Health of the entity (e.g. player&#039;s health for a client, damage needed to disable stationary MG for stationary MG etc.)&lt;br /&gt;
&lt;br /&gt;
=== inuse ===&lt;br /&gt;
Indicates whether the entity number is used. Specially for entity numbers reserved for clients, indicates whether client slot is used.&lt;br /&gt;
&lt;br /&gt;
=== message ===&lt;br /&gt;
Message associated with the entity (e.g. &amp;quot;Side door&amp;quot; for side door objective entity). nil for player entities.&lt;br /&gt;
&lt;br /&gt;
=== origin ===&lt;br /&gt;
* for living player and some visible entities (like tank), position in map&lt;br /&gt;
* dosen&#039;t work for spectating player&lt;br /&gt;
&lt;br /&gt;
=== s.origin ===&lt;br /&gt;
* for spectator in freelook, the spectator&#039;s position&lt;br /&gt;
&lt;br /&gt;
=== pers.netname ===&lt;br /&gt;
For player, their nickname.&lt;br /&gt;
&lt;br /&gt;
=== ps.ammo ===&lt;br /&gt;
Array. For each weapon, tells how many bullets/whatever the player has in spare clips.&lt;br /&gt;
&lt;br /&gt;
=== ps.ammoclip ===&lt;br /&gt;
Array. For each weapon, tells how many bullets/whatever the player has in current clip.&lt;br /&gt;
&lt;br /&gt;
=== sess.sessionTeam ===&lt;br /&gt;
Player&#039;s team:&lt;br /&gt;
* 1 = red&lt;br /&gt;
* 2 = blue&lt;br /&gt;
* 3 = spectator&lt;br /&gt;
&lt;br /&gt;
=== sess.spectatorState ===&lt;br /&gt;
* 1 = free spectator&lt;br /&gt;
* 2 = spectator following another player&lt;br /&gt;
&lt;br /&gt;
=== sess.spectatorClient ===&lt;br /&gt;
Entity number of player the spectator is following.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:ETPro]]&lt;br /&gt;
[[Category:Lua]]&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=Fieldname&amp;diff=2745</id>
		<title>Fieldname</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=Fieldname&amp;diff=2745"/>
		<updated>2007-05-20T07:29:59Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: I believe sess.spectatorClient returns entity rather than int&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOEDITSECTION__&lt;br /&gt;
==Entity Fieldnames==&lt;br /&gt;
List of fields supported by [[Lua Mod API#entities|et.gentity_get() and et.gentity_set()]] functions&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pitatable columns=3 headlines=&amp;quot;field;type;access&amp;quot; widths=&amp;quot;180;120;60&amp;quot; headerfontcolor=&amp;quot;#FFFFFF&amp;quot;&amp;gt;&lt;br /&gt;
activator;entity;RO;&lt;br /&gt;
chain;entity;RW;&lt;br /&gt;
classname;string;RW;&lt;br /&gt;
client.inactivityTime;integer;RW;&lt;br /&gt;
client.inactivityWarning;qboolean;RW;&lt;br /&gt;
clipmask;integer;?;&lt;br /&gt;
closespeed;float;RW;&lt;br /&gt;
count;integer;RW;&lt;br /&gt;
count2;integer;RW;&lt;br /&gt;
damage;integer;RW;&lt;br /&gt;
deathType;meansOfDeath_t;RW;&lt;br /&gt;
delay;float;RW;&lt;br /&gt;
dl_atten;integer;RW;&lt;br /&gt;
dl_color;vec3;RW;&lt;br /&gt;
dl_shader;string;RO;&lt;br /&gt;
dl_stylestring;string;RO;&lt;br /&gt;
duration;float;RW;&lt;br /&gt;
end_size;integer;RW;&lt;br /&gt;
enemy;entity;RW;&lt;br /&gt;
flags;bitflag;RO;&lt;br /&gt;
harc;float;RW;&lt;br /&gt;
health;integer;RW;&lt;br /&gt;
inuse;qboolean;RO;&lt;br /&gt;
isProp;qboolean;RO;&lt;br /&gt;
item;string;RW;&lt;br /&gt;
key;integer;RW;&lt;br /&gt;
message;string;RW;&lt;br /&gt;
methodOfDeath;integer;RW;&lt;br /&gt;
mg42BaseEnt;integer;RW;&lt;br /&gt;
missionLevel;integer;RW;&lt;br /&gt;
model;string;RO;&lt;br /&gt;
model2;string;RO;&lt;br /&gt;
nextTrain;entity;RW;&lt;br /&gt;
noise_index;integer;RW;&lt;br /&gt;
origin;vec3;RW;&lt;br /&gt;
pers.connected;connected_t;?;&lt;br /&gt;
pers.netname;string;?;&lt;br /&gt;
pers.localClient;qboolean;?;&lt;br /&gt;
pers.initialSpawn;qboolean;?; &lt;br /&gt;
pers.enterTime;integer;?;&lt;br /&gt;
pers.connectTime;integer;?; &lt;br /&gt;
pers.teamState.state;teamstatestate_t;?;&lt;br /&gt;
pers.voteCount;integer;?;&lt;br /&gt;
pers.teamVoteCount;integer;?; &lt;br /&gt;
pers.complaints;integer;?; &lt;br /&gt;
pers.complaintClient;integer;?; &lt;br /&gt;
pers.complaintEndTime;integer;?; &lt;br /&gt;
pers.lastReinforceTime;integer;?; &lt;br /&gt;
pers.applicationClient;integer;?; &lt;br /&gt;
pers.applicationEndTime;integer;?; &lt;br /&gt;
pers.invitationClient;integer;?; &lt;br /&gt;
pers.invitationEndTime;integer;?; &lt;br /&gt;
pers.propositionClient;integer;?; &lt;br /&gt;
pers.propositionClient2;integer;?; &lt;br /&gt;
pers.propositionEndTime;integer;?; &lt;br /&gt;
pers.autofireteamEndTime;integer;?; &lt;br /&gt;
pers.autofireteamCreateEndTime;integer;?; &lt;br /&gt;
pers.autofireteamJoinEndTime;integer;?; &lt;br /&gt;
pers.lastSpawnTime;integer;?;&lt;br /&gt;
pers.ready;qboolean;?;&lt;br /&gt;
prevTrain;entity;RW;&lt;br /&gt;
props_frame_state;integer;RO;&lt;br /&gt;
ps.stats;integer array;RW; &lt;br /&gt;
ps.persistant;integer array;RW;&lt;br /&gt;
ps.ping;integer;?;&lt;br /&gt;
ps.powerups;integer array;RW;&lt;br /&gt;
ps.ammo;integer array;RW; &lt;br /&gt;
ps.ammoclip;integer array;RW;&lt;br /&gt;
r.absmax;vec3;RO;&lt;br /&gt;
r.absmin;vec3;RO;&lt;br /&gt;
r.bmodel;qboolean;RO;&lt;br /&gt;
r.contents;integer;RW;&lt;br /&gt;
r.currentAngles;vec3;RW;&lt;br /&gt;
r.currentOrigin;vec3;RW;&lt;br /&gt;
r.eventTime;integer;RW;&lt;br /&gt;
r.linkcount;integer;RO;&lt;br /&gt;
r.linked;qboolean;RO;&lt;br /&gt;
r.maxs;vec3;RW;&lt;br /&gt;
r.mins;vec3;RW;&lt;br /&gt;
r.ownerNum;integer;RW;&lt;br /&gt;
r.singleClient;integer;RW;&lt;br /&gt;
r.svFlags;integer;RW;&lt;br /&gt;
r.worldflags;integer;RO;&lt;br /&gt;
radius;integer;RW;&lt;br /&gt;
random;float;RW;&lt;br /&gt;
rotate;vec3;RW;&lt;br /&gt;
s.angles;vec3;RW;&lt;br /&gt;
s.angles2;vec3;RW;&lt;br /&gt;
s.apos;trajectory;RW;&lt;br /&gt;
s.clientNum;integer;RW;&lt;br /&gt;
s.constantLight;integer;RW;&lt;br /&gt;
s.density;integer;RW;&lt;br /&gt;
s.dl_intensity;integer;RW;&lt;br /&gt;
s.dmgFlags;integer;RW;&lt;br /&gt;
s.eFlags;integer;RW;&lt;br /&gt;
s.eType;integer;?;&lt;br /&gt;
s.effect1Time;integer;RW;&lt;br /&gt;
s.effect2Time;integer;RW;&lt;br /&gt;
s.effect3Time;integer;RW;&lt;br /&gt;
s.frame;integer;RW;&lt;br /&gt;
s.groundEntityNum;integer;RO;&lt;br /&gt;
s.loopSound;integer;RW;&lt;br /&gt;
s.modelindex;integer;RW;&lt;br /&gt;
s.modelindex2;integer;RW;&lt;br /&gt;
s.number;integer;RO;&lt;br /&gt;
s.onFireEnd;integer;RW;&lt;br /&gt;
s.onFireStart;integer;RW;&lt;br /&gt;
s.origin;vec3;?;&lt;br /&gt;
s.origin2;vec3;?;&lt;br /&gt;
s.pos;trajectory;RW;&lt;br /&gt;
s.powerups;integer;RO;&lt;br /&gt;
s.solid;integer;RW;&lt;br /&gt;
s.teamNum;integer;RW;&lt;br /&gt;
s.time;integer;RW;&lt;br /&gt;
s.time2;integer;RW;&lt;br /&gt;
s.weapon;integer;RO;&lt;br /&gt;
scriptName;string;RO;&lt;br /&gt;
sess.sessionTeam;team_t;RW;&lt;br /&gt;
sess.spectatorTime;integer;RW;&lt;br /&gt;
sess.spectatorState;spectatorState_t;RW;&lt;br /&gt;
sess.spectatorClient;entity;RW;&lt;br /&gt;
sess.latchSpectatorClient;integer;RW;&lt;br /&gt;
sess.playerType;integer;RW;&lt;br /&gt;
sess.playerWeapon;integer;RW;&lt;br /&gt;
sess.playerWeapon2;integer;RW;&lt;br /&gt;
sess.spawnObjectiveIndex;integer;RW;&lt;br /&gt;
sess.latchPlayerType;integer;RW;&lt;br /&gt;
sess.latchPlayerWeapon;integer;RW;&lt;br /&gt;
sess.latchPlayerWeapon2;integer;RW;&lt;br /&gt;
sess.damage_given;integer;RW;&lt;br /&gt;
sess.damage_received;integer;RW;&lt;br /&gt;
sess.deaths;integer;RW;&lt;br /&gt;
sess.game_points;integer;RW;&lt;br /&gt;
sess.gibs;integer;RW;&lt;br /&gt;
sess.kills;integer;RW;&lt;br /&gt;
sess.medals;integer array;RW;&lt;br /&gt;
sess.muted;qboolean;RW;&lt;br /&gt;
sess.rank;integer;RW;&lt;br /&gt;
sess.referee;integer;RW;&lt;br /&gt;
sess.rounds;integer;RW;&lt;br /&gt;
sess.semiadmin;integer;RW;&lt;br /&gt;
sess.skill;integer array;RW;&lt;br /&gt;
sess.spec_invite;integer;RW;&lt;br /&gt;
sess.spec_team;integer;RW;&lt;br /&gt;
sess.suicides;integer;RW;&lt;br /&gt;
sess.team_damage;integer;RW;&lt;br /&gt;
sess.team_kills;integer;RW;&lt;br /&gt;
sess.team_received;integer;RW;&lt;br /&gt;
sess.aWeaponStats;weapon_stat_t;RW;&lt;br /&gt;
spawnflags;integer;RO;&lt;br /&gt;
spawnitem;string;RO;&lt;br /&gt;
speed;float;RW;&lt;br /&gt;
splashDamage;integer;RW;&lt;br /&gt;
splashMethodOfDeath;integer;RW;&lt;br /&gt;
splashRadius;integer;RW;&lt;br /&gt;
start_size;integer;RW;&lt;br /&gt;
tagName;string;RO;&lt;br /&gt;
tagParent;entity;RW;&lt;br /&gt;
takedamage;boolean;RW;&lt;br /&gt;
tankLink;entity;RW;&lt;br /&gt;
target;string;RW;&lt;br /&gt;
TargetAngles;vec3;RW;&lt;br /&gt;
TargetFlag;integer;RO;&lt;br /&gt;
targetname;string;RO;&lt;br /&gt;
teamchain;entity;RW;&lt;br /&gt;
teammaster;entity;RW;&lt;br /&gt;
track;string;RO;&lt;br /&gt;
varc;float;RW;&lt;br /&gt;
wait;float;RW;&lt;br /&gt;
waterlevel;integer;RO;&lt;br /&gt;
watertype;integer;RO;&lt;br /&gt;
&amp;lt;/pitatable&amp;gt;&lt;br /&gt;
:&#039;&#039;note&#039;&#039;: all the sess.* fields will return nil unless the entity is associated with client slot &amp;lt; sv_maxclients.&lt;br /&gt;
:&#039;&#039;note&#039;&#039;: all array variables need to be get or set with an additional parameter.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==ET variable types==&lt;br /&gt;
&lt;br /&gt;
===qboolean===&lt;br /&gt;
:a &#039;&#039;&#039;qboolean&#039;&#039;&#039; is a boolean value.&lt;br /&gt;
:0 is represented by the lua value false&lt;br /&gt;
:1 is represented by the lua value true&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===vec3===&lt;br /&gt;
:a &#039;&#039;&#039;vec3_t&#039;&#039;&#039; is a 3-element array of numbers (C definition: typedef float vec3_t[3];). It is usually used to store and process coordinates in 3D space.&amp;lt;br&amp;gt;&lt;br /&gt;
:In etpro-lua a vector is an array (table indexed by integers) containing 3 numbers. It can be accessed by&lt;br /&gt;
:doing:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
origin = et.gentity_get(entNum,&amp;quot;r.currentOrigin&amp;quot;) --a vec3 value&lt;br /&gt;
x,y,z = origin[1],origin[2],origin[3]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===array===&lt;br /&gt;
:The fields listed as having type &#039;&#039;&#039;array&#039;&#039;&#039; represent an entity value which is an array. Individual elements of the array are accessed by passing the desired index in the &#039;&#039;arrayindex&#039;&#039; argument to the et.gentity_get and et.gentity_set functions. Valid array indexes are integers from 0 up to some field specific maximum. The &#039;&#039;arrayindex&#039;&#039; argument is &#039;&#039;&#039;required&#039;&#039;&#039; when accessing array type fields, so only one element of an array can be accessed in a given call to the gentity_* functions.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===trajectory===&lt;br /&gt;
:a &#039;&#039;&#039;trajectory&#039;&#039;&#039; is returned as a lua table described below&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  trDuration = &amp;lt;number&amp;gt;, --- int&lt;br /&gt;
  trTime = &amp;lt;number&amp;gt;, -- int&lt;br /&gt;
  trType = &amp;lt;number&amp;gt;, -- see below for allowed values&lt;br /&gt;
  trBase = &amp;lt;vec3_t&amp;gt;, -- vec3, as described above&lt;br /&gt;
  trDelta = &amp;lt;vec3_t&amp;gt; -- also a vec3&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
: the allowed values for trType (along with the enum names and original comments from the ET source), are as follows. Note &lt;br /&gt;
: that not all values make sense for all entity types &lt;br /&gt;
&amp;lt;pitatable columns=3 headlines=&amp;quot;number;type;discription&amp;quot; widths=&amp;quot;40;160;450&amp;quot; headerfontcolor=&amp;quot;#FFFFFF&amp;quot;&amp;gt;&lt;br /&gt;
1;TR_STATIONARY;&lt;br /&gt;
2;TR_INTERPOLATE;non-parametric, but interpolate between snapshots;&lt;br /&gt;
3;TR_LINEAR;&lt;br /&gt;
4;TR_LINEAR_STOP;&lt;br /&gt;
5;TR_LINEAR_STOP_BACK;reverse movement can be different than forward;&lt;br /&gt;
6;TR_SINE;value = base + sin( time / duration ) * delta;&lt;br /&gt;
7;TR_GRAVITY;&lt;br /&gt;
8;TR_GRAVITY_LOW;&lt;br /&gt;
9;TR_GRAVITY_FLOAT;super low grav with no gravity acceleration;&lt;br /&gt;
10;TR_GRAVITY_PAUSED;has stopped, but trace to see if it should be switched back to TR_GRAVITY;&lt;br /&gt;
11;TR_ACCELERATE;&lt;br /&gt;
12;TR_DECCELERATE;&lt;br /&gt;
13;TR_SPLINE;&lt;br /&gt;
14;TR_LINEAR_PATH;&lt;br /&gt;
&amp;lt;/pitatable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===entity===&lt;br /&gt;
:The fields listed as having type &#039;&#039;&#039;enitity&#039;&#039;&#039; return an entity number or nil. Entity numbers are integers from 0 through 1023. Some of the entity numbers have special meanings:&lt;br /&gt;
:0 - (sv_privateclients - 1) are reserved for clients who connect with the private slot password&lt;br /&gt;
:0 - 63 are reserved for clients. A client&#039;s entity number is also its client number (as shown by /players for example)&lt;br /&gt;
:1022 is the &#039;&#039;&#039;worldspawn&#039;&#039;&#039; entity&lt;br /&gt;
:1023 is &#039;&#039;&#039;ENTITYNUM_NONE&#039;&#039;&#039; which is used instead of null in C under some circumstances to indicate no entity. This is needed where an entity number will be passed over the network.&lt;br /&gt;
:&#039;&#039;Note&#039;&#039;: Some other fields not listed as type &#039;entity&#039; may take an entity number value. &#039;&#039;&#039;mg42BaseEnt&#039;&#039;&#039; and &#039;&#039;&#039;s.number&#039;&#039;&#039; are examples.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===meansOfDeath===&lt;br /&gt;
:a &#039;&#039;&#039;meansOfDeath_t&#039;&#039;&#039; is a number indicating the [[etdamage|Method of Death]] Click  [[etdamage|here]] for a list with possible value&#039;s&lt;br /&gt;
&lt;br /&gt;
[[Category:ETPro]]&lt;br /&gt;
[[Category:Lua]]&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=Fieldname&amp;diff=2744</id>
		<title>Fieldname</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=Fieldname&amp;diff=2744"/>
		<updated>2007-05-18T22:10:28Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: added to Lua category&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOEDITSECTION__&lt;br /&gt;
==Entity Fieldnames==&lt;br /&gt;
List of fields supported by [[Lua Mod API#entities|et.gentity_get() and et.gentity_set()]] functions&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pitatable columns=3 headlines=&amp;quot;field;type;access&amp;quot; widths=&amp;quot;180;120;60&amp;quot; headerfontcolor=&amp;quot;#FFFFFF&amp;quot;&amp;gt;&lt;br /&gt;
activator;entity;RO;&lt;br /&gt;
chain;entity;RW;&lt;br /&gt;
classname;string;RW;&lt;br /&gt;
client.inactivityTime;integer;RW;&lt;br /&gt;
client.inactivityWarning;qboolean;RW;&lt;br /&gt;
clipmask;integer;?;&lt;br /&gt;
closespeed;float;RW;&lt;br /&gt;
count;integer;RW;&lt;br /&gt;
count2;integer;RW;&lt;br /&gt;
damage;integer;RW;&lt;br /&gt;
deathType;meansOfDeath_t;RW;&lt;br /&gt;
delay;float;RW;&lt;br /&gt;
dl_atten;integer;RW;&lt;br /&gt;
dl_color;vec3;RW;&lt;br /&gt;
dl_shader;string;RO;&lt;br /&gt;
dl_stylestring;string;RO;&lt;br /&gt;
duration;float;RW;&lt;br /&gt;
end_size;integer;RW;&lt;br /&gt;
enemy;entity;RW;&lt;br /&gt;
flags;bitflag;RO;&lt;br /&gt;
harc;float;RW;&lt;br /&gt;
health;integer;RW;&lt;br /&gt;
inuse;qboolean;RO;&lt;br /&gt;
isProp;qboolean;RO;&lt;br /&gt;
item;string;RW;&lt;br /&gt;
key;integer;RW;&lt;br /&gt;
message;string;RW;&lt;br /&gt;
methodOfDeath;integer;RW;&lt;br /&gt;
mg42BaseEnt;integer;RW;&lt;br /&gt;
missionLevel;integer;RW;&lt;br /&gt;
model;string;RO;&lt;br /&gt;
model2;string;RO;&lt;br /&gt;
nextTrain;entity;RW;&lt;br /&gt;
noise_index;integer;RW;&lt;br /&gt;
origin;vec3;RW;&lt;br /&gt;
pers.connected;connected_t;?;&lt;br /&gt;
pers.netname;string;?;&lt;br /&gt;
pers.localClient;qboolean;?;&lt;br /&gt;
pers.initialSpawn;qboolean;?; &lt;br /&gt;
pers.enterTime;integer;?;&lt;br /&gt;
pers.connectTime;integer;?; &lt;br /&gt;
pers.teamState.state;teamstatestate_t;?;&lt;br /&gt;
pers.voteCount;integer;?;&lt;br /&gt;
pers.teamVoteCount;integer;?; &lt;br /&gt;
pers.complaints;integer;?; &lt;br /&gt;
pers.complaintClient;integer;?; &lt;br /&gt;
pers.complaintEndTime;integer;?; &lt;br /&gt;
pers.lastReinforceTime;integer;?; &lt;br /&gt;
pers.applicationClient;integer;?; &lt;br /&gt;
pers.applicationEndTime;integer;?; &lt;br /&gt;
pers.invitationClient;integer;?; &lt;br /&gt;
pers.invitationEndTime;integer;?; &lt;br /&gt;
pers.propositionClient;integer;?; &lt;br /&gt;
pers.propositionClient2;integer;?; &lt;br /&gt;
pers.propositionEndTime;integer;?; &lt;br /&gt;
pers.autofireteamEndTime;integer;?; &lt;br /&gt;
pers.autofireteamCreateEndTime;integer;?; &lt;br /&gt;
pers.autofireteamJoinEndTime;integer;?; &lt;br /&gt;
pers.lastSpawnTime;integer;?;&lt;br /&gt;
pers.ready;qboolean;?;&lt;br /&gt;
prevTrain;entity;RW;&lt;br /&gt;
props_frame_state;integer;RO;&lt;br /&gt;
ps.stats;integer array;RW; &lt;br /&gt;
ps.persistant;integer array;RW;&lt;br /&gt;
ps.ping;integer;?;&lt;br /&gt;
ps.powerups;integer array;RW;&lt;br /&gt;
ps.ammo;integer array;RW; &lt;br /&gt;
ps.ammoclip;integer array;RW;&lt;br /&gt;
r.absmax;vec3;RO;&lt;br /&gt;
r.absmin;vec3;RO;&lt;br /&gt;
r.bmodel;qboolean;RO;&lt;br /&gt;
r.contents;integer;RW;&lt;br /&gt;
r.currentAngles;vec3;RW;&lt;br /&gt;
r.currentOrigin;vec3;RW;&lt;br /&gt;
r.eventTime;integer;RW;&lt;br /&gt;
r.linkcount;integer;RO;&lt;br /&gt;
r.linked;qboolean;RO;&lt;br /&gt;
r.maxs;vec3;RW;&lt;br /&gt;
r.mins;vec3;RW;&lt;br /&gt;
r.ownerNum;integer;RW;&lt;br /&gt;
r.singleClient;integer;RW;&lt;br /&gt;
r.svFlags;integer;RW;&lt;br /&gt;
r.worldflags;integer;RO;&lt;br /&gt;
radius;integer;RW;&lt;br /&gt;
random;float;RW;&lt;br /&gt;
rotate;vec3;RW;&lt;br /&gt;
s.angles;vec3;RW;&lt;br /&gt;
s.angles2;vec3;RW;&lt;br /&gt;
s.apos;trajectory;RW;&lt;br /&gt;
s.clientNum;integer;RW;&lt;br /&gt;
s.constantLight;integer;RW;&lt;br /&gt;
s.density;integer;RW;&lt;br /&gt;
s.dl_intensity;integer;RW;&lt;br /&gt;
s.dmgFlags;integer;RW;&lt;br /&gt;
s.eFlags;integer;RW;&lt;br /&gt;
s.eType;integer;?;&lt;br /&gt;
s.effect1Time;integer;RW;&lt;br /&gt;
s.effect2Time;integer;RW;&lt;br /&gt;
s.effect3Time;integer;RW;&lt;br /&gt;
s.frame;integer;RW;&lt;br /&gt;
s.groundEntityNum;integer;RO;&lt;br /&gt;
s.loopSound;integer;RW;&lt;br /&gt;
s.modelindex;integer;RW;&lt;br /&gt;
s.modelindex2;integer;RW;&lt;br /&gt;
s.number;integer;RO;&lt;br /&gt;
s.onFireEnd;integer;RW;&lt;br /&gt;
s.onFireStart;integer;RW;&lt;br /&gt;
s.origin;vec3;?;&lt;br /&gt;
s.origin2;vec3;?;&lt;br /&gt;
s.pos;trajectory;RW;&lt;br /&gt;
s.powerups;integer;RO;&lt;br /&gt;
s.solid;integer;RW;&lt;br /&gt;
s.teamNum;integer;RW;&lt;br /&gt;
s.time;integer;RW;&lt;br /&gt;
s.time2;integer;RW;&lt;br /&gt;
s.weapon;integer;RO;&lt;br /&gt;
scriptName;string;RO;&lt;br /&gt;
sess.sessionTeam;team_t;RW;&lt;br /&gt;
sess.spectatorTime;integer;RW;&lt;br /&gt;
sess.spectatorState;spectatorState_t;RW;&lt;br /&gt;
sess.spectatorClient;integer;RW;&lt;br /&gt;
sess.latchSpectatorClient;integer;RW;&lt;br /&gt;
sess.playerType;integer;RW;&lt;br /&gt;
sess.playerWeapon;integer;RW;&lt;br /&gt;
sess.playerWeapon2;integer;RW;&lt;br /&gt;
sess.spawnObjectiveIndex;integer;RW;&lt;br /&gt;
sess.latchPlayerType;integer;RW;&lt;br /&gt;
sess.latchPlayerWeapon;integer;RW;&lt;br /&gt;
sess.latchPlayerWeapon2;integer;RW;&lt;br /&gt;
sess.damage_given;integer;RW;&lt;br /&gt;
sess.damage_received;integer;RW;&lt;br /&gt;
sess.deaths;integer;RW;&lt;br /&gt;
sess.game_points;integer;RW;&lt;br /&gt;
sess.gibs;integer;RW;&lt;br /&gt;
sess.kills;integer;RW;&lt;br /&gt;
sess.medals;integer array;RW;&lt;br /&gt;
sess.muted;qboolean;RW;&lt;br /&gt;
sess.rank;integer;RW;&lt;br /&gt;
sess.referee;integer;RW;&lt;br /&gt;
sess.rounds;integer;RW;&lt;br /&gt;
sess.semiadmin;integer;RW;&lt;br /&gt;
sess.skill;integer array;RW;&lt;br /&gt;
sess.spec_invite;integer;RW;&lt;br /&gt;
sess.spec_team;integer;RW;&lt;br /&gt;
sess.suicides;integer;RW;&lt;br /&gt;
sess.team_damage;integer;RW;&lt;br /&gt;
sess.team_kills;integer;RW;&lt;br /&gt;
sess.team_received;integer;RW;&lt;br /&gt;
sess.aWeaponStats;weapon_stat_t;RW;&lt;br /&gt;
spawnflags;integer;RO;&lt;br /&gt;
spawnitem;string;RO;&lt;br /&gt;
speed;float;RW;&lt;br /&gt;
splashDamage;integer;RW;&lt;br /&gt;
splashMethodOfDeath;integer;RW;&lt;br /&gt;
splashRadius;integer;RW;&lt;br /&gt;
start_size;integer;RW;&lt;br /&gt;
tagName;string;RO;&lt;br /&gt;
tagParent;entity;RW;&lt;br /&gt;
takedamage;boolean;RW;&lt;br /&gt;
tankLink;entity;RW;&lt;br /&gt;
target;string;RW;&lt;br /&gt;
TargetAngles;vec3;RW;&lt;br /&gt;
TargetFlag;integer;RO;&lt;br /&gt;
targetname;string;RO;&lt;br /&gt;
teamchain;entity;RW;&lt;br /&gt;
teammaster;entity;RW;&lt;br /&gt;
track;string;RO;&lt;br /&gt;
varc;float;RW;&lt;br /&gt;
wait;float;RW;&lt;br /&gt;
waterlevel;integer;RO;&lt;br /&gt;
watertype;integer;RO;&lt;br /&gt;
&amp;lt;/pitatable&amp;gt;&lt;br /&gt;
:&#039;&#039;note&#039;&#039;: all the sess.* fields will return nil unless the entity is associated with client slot &amp;lt; sv_maxclients.&lt;br /&gt;
:&#039;&#039;note&#039;&#039;: all array variables need to be get or set with an additional parameter.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==ET variable types==&lt;br /&gt;
&lt;br /&gt;
===qboolean===&lt;br /&gt;
:a &#039;&#039;&#039;qboolean&#039;&#039;&#039; is a boolean value.&lt;br /&gt;
:0 is represented by the lua value false&lt;br /&gt;
:1 is represented by the lua value true&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===vec3===&lt;br /&gt;
:a &#039;&#039;&#039;vec3_t&#039;&#039;&#039; is a 3-element array of numbers (C definition: typedef float vec3_t[3];). It is usually used to store and process coordinates in 3D space.&amp;lt;br&amp;gt;&lt;br /&gt;
:In etpro-lua a vector is an array (table indexed by integers) containing 3 numbers. It can be accessed by&lt;br /&gt;
:doing:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
origin = et.gentity_get(entNum,&amp;quot;r.currentOrigin&amp;quot;) --a vec3 value&lt;br /&gt;
x,y,z = origin[1],origin[2],origin[3]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===array===&lt;br /&gt;
:The fields listed as having type &#039;&#039;&#039;array&#039;&#039;&#039; represent an entity value which is an array. Individual elements of the array are accessed by passing the desired index in the &#039;&#039;arrayindex&#039;&#039; argument to the et.gentity_get and et.gentity_set functions. Valid array indexes are integers from 0 up to some field specific maximum. The &#039;&#039;arrayindex&#039;&#039; argument is &#039;&#039;&#039;required&#039;&#039;&#039; when accessing array type fields, so only one element of an array can be accessed in a given call to the gentity_* functions.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===trajectory===&lt;br /&gt;
:a &#039;&#039;&#039;trajectory&#039;&#039;&#039; is returned as a lua table described below&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  trDuration = &amp;lt;number&amp;gt;, --- int&lt;br /&gt;
  trTime = &amp;lt;number&amp;gt;, -- int&lt;br /&gt;
  trType = &amp;lt;number&amp;gt;, -- see below for allowed values&lt;br /&gt;
  trBase = &amp;lt;vec3_t&amp;gt;, -- vec3, as described above&lt;br /&gt;
  trDelta = &amp;lt;vec3_t&amp;gt; -- also a vec3&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
: the allowed values for trType (along with the enum names and original comments from the ET source), are as follows. Note &lt;br /&gt;
: that not all values make sense for all entity types &lt;br /&gt;
&amp;lt;pitatable columns=3 headlines=&amp;quot;number;type;discription&amp;quot; widths=&amp;quot;40;160;450&amp;quot; headerfontcolor=&amp;quot;#FFFFFF&amp;quot;&amp;gt;&lt;br /&gt;
1;TR_STATIONARY;&lt;br /&gt;
2;TR_INTERPOLATE;non-parametric, but interpolate between snapshots;&lt;br /&gt;
3;TR_LINEAR;&lt;br /&gt;
4;TR_LINEAR_STOP;&lt;br /&gt;
5;TR_LINEAR_STOP_BACK;reverse movement can be different than forward;&lt;br /&gt;
6;TR_SINE;value = base + sin( time / duration ) * delta;&lt;br /&gt;
7;TR_GRAVITY;&lt;br /&gt;
8;TR_GRAVITY_LOW;&lt;br /&gt;
9;TR_GRAVITY_FLOAT;super low grav with no gravity acceleration;&lt;br /&gt;
10;TR_GRAVITY_PAUSED;has stopped, but trace to see if it should be switched back to TR_GRAVITY;&lt;br /&gt;
11;TR_ACCELERATE;&lt;br /&gt;
12;TR_DECCELERATE;&lt;br /&gt;
13;TR_SPLINE;&lt;br /&gt;
14;TR_LINEAR_PATH;&lt;br /&gt;
&amp;lt;/pitatable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===entity===&lt;br /&gt;
:The fields listed as having type &#039;&#039;&#039;enitity&#039;&#039;&#039; return an entity number or nil. Entity numbers are integers from 0 through 1023. Some of the entity numbers have special meanings:&lt;br /&gt;
:0 - (sv_privateclients - 1) are reserved for clients who connect with the private slot password&lt;br /&gt;
:0 - 63 are reserved for clients. A client&#039;s entity number is also its client number (as shown by /players for example)&lt;br /&gt;
:1022 is the &#039;&#039;&#039;worldspawn&#039;&#039;&#039; entity&lt;br /&gt;
:1023 is &#039;&#039;&#039;ENTITYNUM_NONE&#039;&#039;&#039; which is used instead of null in C under some circumstances to indicate no entity. This is needed where an entity number will be passed over the network.&lt;br /&gt;
:&#039;&#039;Note&#039;&#039;: Some other fields not listed as type &#039;entity&#039; may take an entity number value. &#039;&#039;&#039;mg42BaseEnt&#039;&#039;&#039; and &#039;&#039;&#039;s.number&#039;&#039;&#039; are examples.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===meansOfDeath===&lt;br /&gt;
:a &#039;&#039;&#039;meansOfDeath_t&#039;&#039;&#039; is a number indicating the [[etdamage|Method of Death]] Click  [[etdamage|here]] for a list with possible value&#039;s&lt;br /&gt;
&lt;br /&gt;
[[Category:ETPro]]&lt;br /&gt;
[[Category:Lua]]&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2740</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2740"/>
		<updated>2007-05-07T22:53:14Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: RefMon v0.2&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently (= for about last 3 years) found at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the function returns short version of guid and should NOT be used for authentication purposes!&lt;br /&gt;
&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Indent ===&lt;br /&gt;
Another simple function. This one is useful if you need to print a list of basically anything and want the text to be arranged in columns.&lt;br /&gt;
&lt;br /&gt;
 -- makes a string at least &amp;lt;length&amp;gt; characters long, adding spaces behind the original string if needed&lt;br /&gt;
 function indent(str, length)&lt;br /&gt;
     local len&lt;br /&gt;
 &lt;br /&gt;
     len = math.min(string.len(str), length)&lt;br /&gt;
     str = str .. string.rep(&amp;quot; &amp;quot;, length - len)&lt;br /&gt;
 &lt;br /&gt;
     return str&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Note that it never shortens the text so you might end up with a garbled table anyways, but if you set the length to a reasonable number (e.g. 15 for IP - it&#039;s max length IPv4 can have), you should be fine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in CleintCommand trap:&lt;br /&gt;
&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;ll passing the command to ET&lt;br /&gt;
&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.6&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 6.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== RefMon ==&lt;br /&gt;
version: 0.2&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 8.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/refmon.lua lua] (requires [http://www.sonic.net/~rfm/et/lua/etconst.lua etconst.lua])]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Referee Monitor mod - a lua script that logs all ref commands to a separate, easy to read log.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Referee monitor writes a log record for any ref command issued by either client or server console. The log contains these columns:&lt;br /&gt;
* date and time (in server&#039;s timezone)&lt;br /&gt;
* IP of the client who issued the command (empty for server commands, note that IP can be spoofed)&lt;br /&gt;
* name of the client who issued the command (or [console])&lt;br /&gt;
* flag - for easy orientation in the log, R means the player was logged in as ref, C means console command, empty otherwise&lt;br /&gt;
* command issued&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Server console command ===&lt;br /&gt;
* &#039;&#039;&#039;/reflog [optional line number]&#039;&#039;&#039; - prints part of the log to console. The behaviour is similar to !showbans in pub - without parameter, it returns last rows in file, positive number gives you rows starting at that index, negative gives you rows starting at index (-number) from end. Number of rows returned at once is determined by PRINT_ROWS constant (20 by default).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Example log file ===&lt;br /&gt;
 2007-05-06 14:51:57  127.0.0.1       {AR}Major Zeman                 ref&lt;br /&gt;
 2007-05-06 14:52:01  127.0.0.1       {AR}Major Zeman                 ref badpassword&lt;br /&gt;
 2007-05-06 14:52:05  127.0.0.1       {AR}Major Zeman                 ref goodpassword&lt;br /&gt;
 2007-05-06 14:52:09  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
 2007-05-06 14:52:12  127.0.0.1       {AR}Major Zeman               R ref logout&lt;br /&gt;
 2007-05-06 14:52:16  127.0.0.1       {AR}Major Zeman                 ref somecommand&lt;br /&gt;
 2007-05-06 14:52:24  ---             [console]                     C ref referee 0&lt;br /&gt;
 2007-05-06 14:52:27  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
The zip contains two files:&lt;br /&gt;
* refmon.lua - script itself, needed&lt;br /&gt;
* etconst.lua - [[User:ReyalP|ReyalP]]&#039;s header file, needed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=Configstring&amp;diff=2738</id>
		<title>Configstring</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=Configstring&amp;diff=2738"/>
		<updated>2007-05-06T22:34:46Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: ref key&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOEDITSECTION__&lt;br /&gt;
&lt;br /&gt;
Configstrings can be accessed with &amp;lt;code&amp;gt;[[Lua_Mod_API#configstrings|et.trap_GetConfigstring]]&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[[Lua_Mod_API#configstrings|et.trap_SetConfigstring]]&amp;lt;/code&amp;gt; and the [[Lua_Mod_API#string_utility_functions|String utility functions]].&lt;br /&gt;
&lt;br /&gt;
==What are Configstrings==&lt;br /&gt;
* Configstrings are strings that are set on the server, and automatically sent to each client.&lt;br /&gt;
* Configstrings are often, but not always, in the from of an infostring (a backslash delimited set of key\value pairs)&lt;br /&gt;
* Each configstring is identified by a number, which is usually given refered to by a name #defined in the ET gamecode.&lt;br /&gt;
* A group of related configstrings (such as CS_PLAYERS) usually only have a symbolic name for the first value, with a number (entity number in the case of CS_PLAYERS) added to to get a particular value.&lt;br /&gt;
* Most configstrings have a specific meaning to the gamecode. You can use the etmain SDK find out what they do, but beware that etpro does not do things exactly the same as etmain.&lt;br /&gt;
* A list of configstring numbers and names can be found in [http://www.collectivecomputing.com/~reed/et/lua/etconst.lua etconst.lua]&lt;br /&gt;
&lt;br /&gt;
==User Configstring==&lt;br /&gt;
A user Configstring gets written in the log file with a line starting with &#039;&#039;UserInfoChanged&#039;&#039; which mustn&#039;t be mistaken for one with &#039;&#039;Userinfo&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To access a user&#039;s Configstring you can&#039;t just use &amp;lt;code&amp;gt;et.trap_GetConfigstring(slotNumber)&amp;lt;/code&amp;gt; but must use &amp;lt;code&amp;gt;et.trap_GetConfigstring(et.CS_PLAYERS + slotNumber)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pitatable columns=3 headlines=&amp;quot;key;name;description&amp;quot; widths=&amp;quot;40;220;450&amp;quot; headerfontcolor=&amp;quot;#FFFFFF&amp;quot;&amp;gt;&lt;br /&gt;
n;Nick;&lt;br /&gt;
t;Team;1=Axis, 2=Allies, 3=Spectators&lt;br /&gt;
c;Class;0=Soldier, 1=Medic, 2=Engineer, 3=FieldOps, 4=CovertOps&lt;br /&gt;
r;Rank;&lt;br /&gt;
m;Medals;&lt;br /&gt;
s;Skills;&lt;br /&gt;
dn;Disguised name;&lt;br /&gt;
dr;Disguised rank;&lt;br /&gt;
w;Weapon&lt;br /&gt;
lw;Latched weapon;Weapon on next spawn&lt;br /&gt;
sw;Latched secondary weapon;Secondary weapon on next spawn&lt;br /&gt;
ref;Referee;Referee status (0=not ref, 1=ref)&lt;br /&gt;
p;Privilege level;0=Peon, referee (vote), referee (password), semiadmin, rconauth - etpro only&lt;br /&gt;
ss;Stat Saver; Stats restored by stat saver;etpro only&lt;br /&gt;
sc;Shoutcaster;etpro only&lt;br /&gt;
tv;ETTV slave;etpro only&lt;br /&gt;
&amp;lt;/pitatable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==LUA Example==&lt;br /&gt;
 et.CS_PLAYERS = &amp;lt;span style=&amp;quot;color: darkblue;&amp;quot;&amp;gt;689&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: green;&amp;quot;&amp;gt;-- get the name of client #3 using configstrings&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: darkred;&amp;quot;&amp;gt;local&amp;lt;/span&amp;gt; cs = et.trap_GetConfigstring(et.CS_PLAYERS + &amp;lt;span style=&amp;quot;color: darkblue;&amp;quot;&amp;gt;3&amp;lt;/span&amp;gt;)&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: darkred;&amp;quot;&amp;gt;local&amp;lt;/span&amp;gt; name = et.Info_ValueForKey(cs, &amp;lt;span style=&amp;quot;color: darkblue;&amp;quot;&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/span&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
&amp;lt;code&amp;gt;et.CS_PLAYERS = 689&amp;lt;/code&amp;gt; for those of you that don&#039;t use [[User:ReyalP|etconst.lua]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;Source:  http://bani.anime.net/banimod/forums/viewtopic.php?t=5412&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:ETPro]]&lt;br /&gt;
[[Category:Lua]]&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User_talk:ReyalP&amp;diff=2737</id>
		<title>User talk:ReyalP</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User_talk:ReyalP&amp;diff=2737"/>
		<updated>2007-05-06T22:31:00Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: /* unref? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;in your etconst it says at top :&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;-- [23:10] &amp;lt;|Rain|&amp;gt; 2 became CS_ETPRO_INFO instead of CS_MUSIC, because I needed the version info before any more configstrings were parsed&lt;br /&gt;
-- [23:10] &amp;lt;|Rain|&amp;gt; and CS_MUSIC moved up to 53&amp;lt;code&amp;gt;&amp;lt;br&amp;gt;but u still got CS_MUSIC at 2 --2good&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:yup. Since I had no idea what you&#039;d do with either of those config strings, I just left things as I got them found them in the etmain sdk. [[User:ReyalP|ReyalP]]&lt;br /&gt;
&lt;br /&gt;
three [[User:ReyalP|ReyalP]] or [[User:ReyalP|ReyalP]] 13:25, 16 November 2005 (PST) four ?&lt;br /&gt;
&lt;br /&gt;
thats nice but oh well ok i dont care i dont use it myself its a lityle this i made out of my debuglib that was a print function that works like a printf you add variables and dont care but it is since it will check each variable first [[User:=FF=im2good4u|=FF=Im2good4u]] 13:45, 16 November 2005 (PST)&lt;br /&gt;
&lt;br /&gt;
== autoref.lua ==&lt;br /&gt;
&lt;br /&gt;
I &amp;lt;font color=red&amp;gt;&#039;&#039;&#039;&amp;lt;3&#039;&#039;&#039;&amp;lt;/font&amp;gt; this module.  Thanks.  --[[User:Ouroboro|ouroboro]] 16:50, 12 June 2006 (PDT)&lt;br /&gt;
&lt;br /&gt;
== unref? ==&lt;br /&gt;
&lt;br /&gt;
Hi, don&#039;t you know about any way, rcon or lua, how to unref a client that has reffed themselves with password? You can&#039;t unref them from ref, neither through /rcon ref unreferee [num].&lt;br /&gt;
&lt;br /&gt;
I tired with lua, I can make the client think they got reffed/unreffed using configstrings (keys &amp;quot;ref&amp;quot; and &amp;quot;p&amp;quot;), but the server still sees no change in the client status. - [[User:Major Zeman|Major Zeman]] 07:00, 6 May 2007 (PDT)&lt;br /&gt;
:kick them and change the ref pass ?&lt;br /&gt;
:you could also try changing sess.referee - [[User:ReyalP|ReyalP]] 15:02, 6 May 2007 (PDT)&lt;br /&gt;
::lol, that&#039;s basically the &amp;quot;solution&amp;quot; I took. I think I tried sess.referee too, I might try to put it all together later. Thanks anyways :) - [[User:Major Zeman|Major Zeman]] 15:30, 6 May 2007 (PDT)&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User_talk:ReyalP&amp;diff=2736</id>
		<title>User talk:ReyalP</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User_talk:ReyalP&amp;diff=2736"/>
		<updated>2007-05-06T22:30:33Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: /* unref? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;in your etconst it says at top :&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;-- [23:10] &amp;lt;|Rain|&amp;gt; 2 became CS_ETPRO_INFO instead of CS_MUSIC, because I needed the version info before any more configstrings were parsed&lt;br /&gt;
-- [23:10] &amp;lt;|Rain|&amp;gt; and CS_MUSIC moved up to 53&amp;lt;code&amp;gt;&amp;lt;br&amp;gt;but u still got CS_MUSIC at 2 --2good&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:yup. Since I had no idea what you&#039;d do with either of those config strings, I just left things as I got them found them in the etmain sdk. [[User:ReyalP|ReyalP]]&lt;br /&gt;
&lt;br /&gt;
three [[User:ReyalP|ReyalP]] or [[User:ReyalP|ReyalP]] 13:25, 16 November 2005 (PST) four ?&lt;br /&gt;
&lt;br /&gt;
thats nice but oh well ok i dont care i dont use it myself its a lityle this i made out of my debuglib that was a print function that works like a printf you add variables and dont care but it is since it will check each variable first [[User:=FF=im2good4u|=FF=Im2good4u]] 13:45, 16 November 2005 (PST)&lt;br /&gt;
&lt;br /&gt;
== autoref.lua ==&lt;br /&gt;
&lt;br /&gt;
I &amp;lt;font color=red&amp;gt;&#039;&#039;&#039;&amp;lt;3&#039;&#039;&#039;&amp;lt;/font&amp;gt; this module.  Thanks.  --[[User:Ouroboro|ouroboro]] 16:50, 12 June 2006 (PDT)&lt;br /&gt;
&lt;br /&gt;
== unref? ==&lt;br /&gt;
&lt;br /&gt;
Hi, don&#039;t you know about any way, rcon or lua, how to unref a client that has reffed themselves with password? You can&#039;t unref them from ref, neither through /rcon ref unreferee [num].&lt;br /&gt;
&lt;br /&gt;
I tired with lua, I can make the client think they got reffed/unreffed using configstrings (keys &amp;quot;ref&amp;quot; and &amp;quot;p&amp;quot;), but the server still sees no change in the client status.&lt;br /&gt;
:- [[User:Major Zeman|Major Zeman]] 07:00, 6 May 2007 (PDT)&lt;br /&gt;
:kick them and change the ref pass ?&lt;br /&gt;
:you could also try changing sess.referee - [[User:ReyalP|ReyalP]] 15:02, 6 May 2007 (PDT)&lt;br /&gt;
:lol, that&#039;s basically the &amp;quot;solution&amp;quot; I took. I think I tried sess.referee too, I might try to put it all together later. Thanks anyways :) - [[User:Major Zeman|Major Zeman]] 15:30, 6 May 2007 (PDT)&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User_talk:ReyalP&amp;diff=2734</id>
		<title>User talk:ReyalP</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User_talk:ReyalP&amp;diff=2734"/>
		<updated>2007-05-06T14:00:43Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: unref?&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;in your etconst it says at top :&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;-- [23:10] &amp;lt;|Rain|&amp;gt; 2 became CS_ETPRO_INFO instead of CS_MUSIC, because I needed the version info before any more configstrings were parsed&lt;br /&gt;
-- [23:10] &amp;lt;|Rain|&amp;gt; and CS_MUSIC moved up to 53&amp;lt;code&amp;gt;&amp;lt;br&amp;gt;but u still got CS_MUSIC at 2 --2good&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:yup. Since I had no idea what you&#039;d do with either of those config strings, I just left things as I got them found them in the etmain sdk. [[User:ReyalP|ReyalP]]&lt;br /&gt;
&lt;br /&gt;
three [[User:ReyalP|ReyalP]] or [[User:ReyalP|ReyalP]] 13:25, 16 November 2005 (PST) four ?&lt;br /&gt;
&lt;br /&gt;
thats nice but oh well ok i dont care i dont use it myself its a lityle this i made out of my debuglib that was a print function that works like a printf you add variables and dont care but it is since it will check each variable first [[User:=FF=im2good4u|=FF=Im2good4u]] 13:45, 16 November 2005 (PST)&lt;br /&gt;
&lt;br /&gt;
== autoref.lua ==&lt;br /&gt;
&lt;br /&gt;
I &amp;lt;font color=red&amp;gt;&#039;&#039;&#039;&amp;lt;3&#039;&#039;&#039;&amp;lt;/font&amp;gt; this module.  Thanks.  --[[User:Ouroboro|ouroboro]] 16:50, 12 June 2006 (PDT)&lt;br /&gt;
&lt;br /&gt;
== unref? ==&lt;br /&gt;
&lt;br /&gt;
Hi, don&#039;t you know about any way, rcon or lua, how to unref a client that has reffed themselves with password? You can&#039;t unref them from ref, neither through /rcon ref unreferee [num].&lt;br /&gt;
&lt;br /&gt;
I tired with lua, I can make the client think they got reffed/unreffed using configstrings (keys &amp;quot;ref&amp;quot; and &amp;quot;p&amp;quot;), but the server still sees no change in the client status.&lt;br /&gt;
:- [[User:Major Zeman|Major Zeman]] 07:00, 6 May 2007 (PDT)&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2733</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2733"/>
		<updated>2007-05-06T13:54:12Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently (= for about last 3 years) found at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the function returns short version of guid and should NOT be used for authentication purposes!&lt;br /&gt;
&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Indent ===&lt;br /&gt;
Another simple function. This one is useful if you need to print a list of basically anything and want the text to be arranged in columns.&lt;br /&gt;
&lt;br /&gt;
 -- makes a string at least &amp;lt;length&amp;gt; characters long, adding spaces behind the original string if needed&lt;br /&gt;
 function indent(str, length)&lt;br /&gt;
     local len&lt;br /&gt;
 &lt;br /&gt;
     len = math.min(string.len(str), length)&lt;br /&gt;
     str = str .. string.rep(&amp;quot; &amp;quot;, length - len)&lt;br /&gt;
 &lt;br /&gt;
     return str&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Note that it never shortens the text so you might end up with a garbled table anyways, but if you set the length to a reasonable number (e.g. 15 for IP - it&#039;s max length IPv4 can have), you should be fine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in CleintCommand trap:&lt;br /&gt;
&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;ll passing the command to ET&lt;br /&gt;
&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.6&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 6.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== RefMon ==&lt;br /&gt;
version: 0.1&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 6.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/refmon.lua lua] (requires [http://www.sonic.net/~rfm/et/lua/etconst.lua etconst.lua])]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Referee Monitor mod - a lua script that logs all ref commands to a separate, easy to read log.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Referee monitor writes a log record for any ref command issued by either client or server console. The log contains these columns:&lt;br /&gt;
* date and time (in server&#039;s timezone)&lt;br /&gt;
* IP of the client who issued the command (empty for server commands, note that IP can be spoofed)&lt;br /&gt;
* name of the client who issued the command (or [console])&lt;br /&gt;
* flag - for easy orientation in the log, R means the player was logged in as ref, C means console command, empty otherwise&lt;br /&gt;
* command issued&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Example log file ===&lt;br /&gt;
 Date                 IP              NAME                            COMMAND&lt;br /&gt;
 2007-05-06 14:51:57  127.0.0.1       {AR}Major Zeman                 ref&lt;br /&gt;
 2007-05-06 14:52:01  127.0.0.1       {AR}Major Zeman                 ref badpassword&lt;br /&gt;
 2007-05-06 14:52:05  127.0.0.1       {AR}Major Zeman                 ref goodpassword&lt;br /&gt;
 2007-05-06 14:52:09  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
 2007-05-06 14:52:12  127.0.0.1       {AR}Major Zeman               R ref logout&lt;br /&gt;
 2007-05-06 14:52:16  127.0.0.1       {AR}Major Zeman                 ref somecommand&lt;br /&gt;
 2007-05-06 14:52:24  ---             [console]                     C ref referee 0&lt;br /&gt;
 2007-05-06 14:52:27  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
The zip contains three files: refmon.lua, refmon.log and etconst.lua.&lt;br /&gt;
* refmon.lua - script itself, needed&lt;br /&gt;
* etconst.lua - [[User:ReyalP|ReyalP]]&#039;s header file, needed&lt;br /&gt;
* refmon.log - default log file, not needed (copy it if you want the log columns to have a header on first row of the log)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2732</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2732"/>
		<updated>2007-05-06T13:53:09Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: link didnt work&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently (= for about last 3 years) found at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the function returns short version of guid and should NOT be used for authentication purposes!&lt;br /&gt;
&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Indent ===&lt;br /&gt;
Another simple function. This one is useful if you need to print a list of basically anything and want the text to be arranged in columns.&lt;br /&gt;
&lt;br /&gt;
 -- makes a string at least &amp;lt;length&amp;gt; characters long, adding spaces behind the original string if needed&lt;br /&gt;
 function indent(str, length)&lt;br /&gt;
     local len&lt;br /&gt;
 &lt;br /&gt;
     len = math.min(string.len(str), length)&lt;br /&gt;
     str = str .. string.rep(&amp;quot; &amp;quot;, length - len)&lt;br /&gt;
 &lt;br /&gt;
     return str&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Note that it never shortens the text so you might end up with a garbled table anyways, but if you set the length to a reasonable number (e.g. 15 for IP - it&#039;s max length IPv4 can have), you should be fine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in CleintCommand trap:&lt;br /&gt;
&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;ll passing the command to ET&lt;br /&gt;
&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.6&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 6.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== RefMon ==&lt;br /&gt;
version: 0.1&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 6.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/refmon.lua lua] (requires [http://www.sonic.net/~rfm/et/lua/etconst.lua etconst.lua])]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Referee Monitor mod - a lua script that logs all ref commands to a separate, easy to read log.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Referee monitor writes a log record for any ref command issued by either client or server console. The log contains these columns:&lt;br /&gt;
* date and time (in server&#039;s timezone)&lt;br /&gt;
* IP of the client who issued the command (empty for server commands, note that IP can be spoofed)&lt;br /&gt;
* name of the client who issued the command (or [console])&lt;br /&gt;
* flag - for easy orientation in the log, R means the player was logged in as ref, C means console command, empty otherwise&lt;br /&gt;
* command issued&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Example log file ===&lt;br /&gt;
 Date                 IP              NAME                            COMMAND&lt;br /&gt;
 2007-05-06 14:51:57  127.0.0.1       {AR}Major Zeman                 ref&lt;br /&gt;
 2007-05-06 14:52:01  127.0.0.1       {AR}Major Zeman                 ref badpassword&lt;br /&gt;
 2007-05-06 14:52:05  127.0.0.1       {AR}Major Zeman                 ref goodpassword&lt;br /&gt;
 2007-05-06 14:52:09  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
 2007-05-06 14:52:12  127.0.0.1       {AR}Major Zeman               R ref logout&lt;br /&gt;
 2007-05-06 14:52:16  127.0.0.1       {AR}Major Zeman                 ref somecommand&lt;br /&gt;
 2007-05-06 14:52:24  ---             [console]                     C ref referee 0&lt;br /&gt;
 2007-05-06 14:52:27  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
The zip contains three files: refmon.lua, refmon.log and etconst.lua.&lt;br /&gt;
* refmon.lua - script itself, needed&lt;br /&gt;
* etconst.lua - [[User:ReyalP|ReyalP]]&#039;s header file, needed&lt;br /&gt;
* refmon.log - default log file, not needed (copy it if you want the log columns to have a header on first row of the log)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2731</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2731"/>
		<updated>2007-05-06T13:50:19Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: refmon&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently (= for about last 3 years) found at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the function returns short version of guid and should NOT be used for authentication purposes!&lt;br /&gt;
&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Indent ===&lt;br /&gt;
Another simple function. This one is useful if you need to print a list of basically anything and want the text to be arranged in columns.&lt;br /&gt;
&lt;br /&gt;
 -- makes a string at least &amp;lt;length&amp;gt; characters long, adding spaces behind the original string if needed&lt;br /&gt;
 function indent(str, length)&lt;br /&gt;
     local len&lt;br /&gt;
 &lt;br /&gt;
     len = math.min(string.len(str), length)&lt;br /&gt;
     str = str .. string.rep(&amp;quot; &amp;quot;, length - len)&lt;br /&gt;
 &lt;br /&gt;
     return str&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Note that it never shortens the text so you might end up with a garbled table anyways, but if you set the length to a reasonable number (e.g. 15 for IP - it&#039;s max length IPv4 can have), you should be fine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in CleintCommand trap:&lt;br /&gt;
&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;ll passing the command to ET&lt;br /&gt;
&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.6&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 6.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== RefMon ==&lt;br /&gt;
version: 0.1&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 6.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/refmon.lua lua] (requires [http://www.sonic.net/~rfm/et/lua/etconst.lua etconst.lua])]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Referee Monitor mod - a lua script that logs all ref commands to a separate, easy to read log.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function ===&lt;br /&gt;
Referee monitor writes a log record for any ref command issued by either client or server console. The log contains these columns:&lt;br /&gt;
* date and time (in server&#039;s timezone)&lt;br /&gt;
* IP of the client who issued the command (empty for server commands, note that IP can be spoofed)&lt;br /&gt;
* name of the client who issued the command (or [console])&lt;br /&gt;
* flag - for easy orientation in the log, R means the player was logged in as ref, C means console command, empty otherwise&lt;br /&gt;
* command issued&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Example log file ===&lt;br /&gt;
 Date                 IP              NAME                            COMMAND&lt;br /&gt;
 2007-05-06 14:51:57  127.0.0.1       {AR}Major Zeman                 ref&lt;br /&gt;
 2007-05-06 14:52:01  127.0.0.1       {AR}Major Zeman                 ref badpassword&lt;br /&gt;
 2007-05-06 14:52:05  127.0.0.1       {AR}Major Zeman                 ref goodpassword&lt;br /&gt;
 2007-05-06 14:52:09  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
 2007-05-06 14:52:12  127.0.0.1       {AR}Major Zeman               R ref logout&lt;br /&gt;
 2007-05-06 14:52:16  127.0.0.1       {AR}Major Zeman                 ref somecommand&lt;br /&gt;
 2007-05-06 14:52:24  ---             [console]                     C ref referee 0&lt;br /&gt;
 2007-05-06 14:52:27  127.0.0.1       {AR}Major Zeman               R ref somecommand&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
The zip contains three files: refmon.lua, refmon.log and etconst.lua.&lt;br /&gt;
* refmon.lua - script itself, needed&lt;br /&gt;
* etconst.lua - [User:ReyalP ReyalP]&#039;s header file, needed&lt;br /&gt;
* refmon.log - default log file, not needed (copy it if you want the log columns to have a header on first row of the log)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2730</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2730"/>
		<updated>2007-05-06T13:19:37Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: indent&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently (= for about last 3 years) found at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the function returns short version of guid and should NOT be used for authentication purposes!&lt;br /&gt;
&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Indent ===&lt;br /&gt;
Another simple function. This one is useful if you need to print a list of basically anything and want the text to be arranged in columns.&lt;br /&gt;
&lt;br /&gt;
 -- makes a string at least &amp;lt;length&amp;gt; characters long, adding spaces behind the original string if needed&lt;br /&gt;
 function indent(str, length)&lt;br /&gt;
     local len&lt;br /&gt;
 &lt;br /&gt;
     len = math.min(string.len(str), length)&lt;br /&gt;
     str = str .. string.rep(&amp;quot; &amp;quot;, length - len)&lt;br /&gt;
 &lt;br /&gt;
     return str&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Note that it never shortens the text so you might end up with a garbled table anyways, but if you set the length to a reasonable number (e.g. 15 for IP - it&#039;s max length IPv4 can have), you should be fine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in CleintCommand trap:&lt;br /&gt;
&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;ll passing the command to ET&lt;br /&gt;
&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.6&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 6.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2729</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2729"/>
		<updated>2007-05-06T13:08:19Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: new version of TJmod_mz (minor changes only)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently (= for about last 3 years) found at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the function returns short version of guid and should NOT be used for authentication purposes!&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in CleintCommand trap:&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;ll passing the command to ET&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.6&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 6.5.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2728</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2728"/>
		<updated>2007-05-06T12:58:16Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: added a check to printmsg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently (= for about last 3 years) found at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the function returns short version of guid and should NOT be used for authentication purposes!&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- replace &amp;quot;s in message with &#039;s&lt;br /&gt;
     local dummy&lt;br /&gt;
     message, dummy = string.gsub(message, &amp;quot;\&amp;quot;&amp;quot;, &amp;quot;&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in CleintCommand trap:&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;ll passing the command to ET&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.5&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 25.3.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2724</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2724"/>
		<updated>2007-04-23T06:52:02Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: guid - note&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently (= for about last 3 years) found at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the function returns short version of guid and should NOT be used for authentication purposes!&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in CleintCommand trap:&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;ll passing the command to ET&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.5&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 25.3.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User_talk:Major_Zeman&amp;diff=2723</id>
		<title>User talk:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User_talk:Major_Zeman&amp;diff=2723"/>
		<updated>2007-04-23T06:49:32Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Just a quick note: the cl_guid in userinfo is pretty easy to spoof. -[[User:ReyalP|ReyalP]] 15:18, 20 April 2007 (PDT)&lt;br /&gt;
&lt;br /&gt;
:- Is that the etpro one or the pb&#039;s one? Thought it was pb&#039;s one :S (fortunately I don&#039;t use it for anything important) Any suggestions what would be better there? Anyways, thanks for the warning --[[User:Major Zeman|Major Zeman]] 15:28, 20 April 2007 (PDT)&lt;br /&gt;
:: cl_guid is the pb GUID. If you are just using it for stats restore or something like that, it&#039;s not an issue. If you are using it for authentication, you should be aware of this. You could get it from sending PB commands (which get it internally rather than from userinfo AFAIK) to the console and reading it back from the log file, but this is a serious pain. It is also still possible to spoof, although much harder. Even if you are using it for authentication, to steal someone elses ID would require knowing their full PB GUID, which isn&#039;t normally visible to other players. Of course, server logs and PB screenshots can leak this information out. -[[User:ReyalP|ReyalP]] 18:32, 20 April 2007 (PDT)&lt;br /&gt;
:::- Thanks, I see where&#039;s the problem now. --[[User:Major Zeman|Major Zeman]] 23:49, 22 April 2007 (PDT)&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User_talk:Major_Zeman&amp;diff=2721</id>
		<title>User talk:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User_talk:Major_Zeman&amp;diff=2721"/>
		<updated>2007-04-20T22:29:33Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Just a quick note: the cl_guid in userinfo is pretty easy to spoof. -[[User:ReyalP|ReyalP]] 15:18, 20 April 2007 (PDT)&lt;br /&gt;
&lt;br /&gt;
:- Is that the etpro one or the pb&#039;s one? Thought it was pb&#039;s one :S (fortunately I don&#039;t use it for anything important) Any suggestions what would be better there? Anyways, thanks for the warning --[[User:Major Zeman|Major Zeman]] 15:28, 20 April 2007 (PDT)&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User_talk:Major_Zeman&amp;diff=2720</id>
		<title>User talk:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User_talk:Major_Zeman&amp;diff=2720"/>
		<updated>2007-04-20T22:28:33Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Just a quick note: the cl_guid in userinfo is pretty easy to spoof. -[[User:ReyalP|ReyalP]] 15:18, 20 April 2007 (PDT)&lt;br /&gt;
- Is that the etpro one or the pb&#039;s one? Thought it was pb&#039;s one :S (fortunately I don&#039;t use it for anything important) Any suggestions what would be better there? Anyways, thanks for the warning --[[User:Major Zeman|Major Zeman]] 15:28, 20 April 2007 (PDT)&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2718</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2718"/>
		<updated>2007-04-20T14:23:53Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: added to cathegory ETPro:Mods&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently (= for about last 3 years) found at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in CleintCommand trap:&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;ll passing the command to ET&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.5&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 25.3.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:ETPro:Mods]]&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2717</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2717"/>
		<updated>2007-04-20T14:21:37Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: semiadmin console output&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently (= for about last 3 years) found at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Printing server LUA commans output to semiadmin console ===&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039; - it works, but it&#039;s a very dirty trick.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there&#039;s no normal way to print output of semiadmin commands back to the semiadmin&#039;s console. I found a trick that allows you to get around this limitation at least for LUA custom commands. It&#039;s quite complex tho, and as I wrote, very nasty. Here it goes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* first we need to declare a global variable (yeah trouble starts here) - it will actually store client number of last client who ran a /semiadmin or /sa command&lt;br /&gt;
 -- a terrible hack to enable console output back to semiadmin&lt;br /&gt;
 lastcallerID = nil&lt;br /&gt;
&lt;br /&gt;
* now we&#039;ll alter the printmsg function shown above a bit (yeah another advantage of that function heh)&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         &amp;lt;b&amp;gt;if lastcallerID then&lt;br /&gt;
             et.trap_SendServerCommand(lastcallerID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
         else&lt;br /&gt;
             et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
         end&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* fortunately, /sa and /semiadmin are ordinary commands and can be intercepted in CleintCommand trap:&lt;br /&gt;
 function et_ClientCommand( clientNum, command )&lt;br /&gt;
     -- lowercase&lt;br /&gt;
     command = string.lower(command)&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;b&amp;gt;-- hack - console output to semiadmin&lt;br /&gt;
     if (command == &amp;quot;sa&amp;quot;) or (command == &amp;quot;semiadmin&amp;quot;) then&lt;br /&gt;
         lastcallerID = clientNum&lt;br /&gt;
     end&amp;lt;/b&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
     ...&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
* now we are basically set, all that remains is to clean up the mess after the party :S&lt;br /&gt;
* we need to erase the client ID from the variable so it won&#039;t affect someone else&#039;s calls; the second setting is after a command was executed already, the first one is for case no custom command was executed and we&#039;ll passing the command to ET&lt;br /&gt;
 function et_ConsoleCommand()&lt;br /&gt;
     if (string.lower(et.trap_Argv(0))==&amp;quot;...&amp;quot;)&lt;br /&gt;
         ... -- all custom console commands go here&lt;br /&gt;
     else&lt;br /&gt;
        &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
        return 0&amp;lt;/b&amp;gt;&lt;br /&gt;
     end&lt;br /&gt;
     &lt;br /&gt;
     &amp;lt;b&amp;gt;lastcallerID = nil   -- hack to allow console output to semiadmin&lt;br /&gt;
     return 1&amp;lt;/b&amp;gt;&lt;br /&gt;
 end&lt;br /&gt;
* and finally, we need to make sure semiadmin calling disallowed command will be handled correctly, too - for that I used console print trap as I haven&#039;t found any other way to detect that situation:&lt;br /&gt;
 function et_Print(text)&lt;br /&gt;
     if string.find(string.lower(et.Q_CleanStr( text )), &amp;quot;) invalid command [&amp;quot;, 1, true) then&lt;br /&gt;
         lastcallerID = nil&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.5&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 25.3.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2716</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2716"/>
		<updated>2007-04-20T13:56:45Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: getPlayerID function&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently (= for about last 3 years) found at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player ID from name ===&lt;br /&gt;
This is an altered version of function posted on etpro forums by Im2good4u and Deus. I added some more parameter checks, error prints (using the above function, so it can be used both for server and client commands), made it accept slot numbers and partial name matches too.&lt;br /&gt;
 -- returns clientslot for given name, or nil if no match found (accepts first (partial) match)&lt;br /&gt;
 -- added color stripping&lt;br /&gt;
 -- if clientID is filled, reports errors to clientID; else prints them to server console&lt;br /&gt;
 function getPlayerId(name, clientID)&lt;br /&gt;
     local i&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s nil, return nil and throw error&lt;br /&gt;
     if (name == &amp;quot;&amp;quot;) then&lt;br /&gt;
         printmsg(&amp;quot;Not enough parameters.&amp;quot;, clientID)&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- if it&#039;s a number, interpret as slot number&lt;br /&gt;
     local clientnum = tonumber(name)&lt;br /&gt;
     if clientnum then&lt;br /&gt;
         if (clientnum &amp;lt;= tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) and et.gentity_get(clientnum,&amp;quot;inuse&amp;quot;) then&lt;br /&gt;
             return clientnum&lt;br /&gt;
         else&lt;br /&gt;
             printmsg(&amp;quot;Slot &amp;quot;..clientnum..&amp;quot; not in use.&amp;quot;, clientID)&lt;br /&gt;
             return nil&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     -- exact match first&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if et.Q_CleanStr( playeri ) == et.Q_CleanStr( name ) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
     -- partial match&lt;br /&gt;
     for i=0,et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;),1 do&lt;br /&gt;
         playeri = et.gentity_get(i,&amp;quot;pers.netname&amp;quot;)&lt;br /&gt;
         if playeri then&lt;br /&gt;
             if (string.find(string.lower(et.Q_CleanStr( playeri )), string.lower(et.Q_CleanStr( name )), 1, true)) then&lt;br /&gt;
                 return i&lt;br /&gt;
             end&lt;br /&gt;
         end&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     printmsg(&amp;quot;No name match found for &#039;&amp;quot;..name..&amp;quot;&#039;.&amp;quot;, clientID)&lt;br /&gt;
     return nil&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.5&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 25.3.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2715</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2715"/>
		<updated>2007-04-20T13:48:14Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: 2 more code fragments&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently (= for about last 3 years) found at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Get GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s Position ===&lt;br /&gt;
This one was actually quite hard to make for me, involved some research in meanings of different items in entity info.&lt;br /&gt;
&lt;br /&gt;
As long as the player is on one of the teams and alive, it&#039;s easy:&lt;br /&gt;
 et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
However, when you count in spectators too, it becomes much more complex. Spectator&#039;s position isn&#039;t stored in &amp;quot;origin&amp;quot; but in &amp;quot;s.origin&amp;quot;. And the trickiest part is when spectator choses to follow other player - his entity stops moving at all and his position is given by the position of player they&#039;re spectating. All together:&lt;br /&gt;
 -- get client&#039;s position&lt;br /&gt;
 function playerpos(clientID)&lt;br /&gt;
     if et.gentity_get(clientID, &amp;quot;sess.sessionTeam&amp;quot;) == 3 then&lt;br /&gt;
         -- spectator&lt;br /&gt;
         if et.gentity_get(clientID, &amp;quot;sess.spectatorState&amp;quot;) == 2 then&lt;br /&gt;
             -- spectator thats following someone&lt;br /&gt;
             local spectatedID = et.gentity_get(clientID, &amp;quot;sess.spectatorClient&amp;quot;)&lt;br /&gt;
             return et.gentity_get(spectatedID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
         else -- spectatorstate == 1&lt;br /&gt;
             -- free spectator&lt;br /&gt;
             return et.gentity_get(clientID, &amp;quot;s.origin&amp;quot;)&lt;br /&gt;
         end&lt;br /&gt;
     else&lt;br /&gt;
         -- regular player&lt;br /&gt;
         return et.gentity_get(clientID, &amp;quot;origin&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Print message to console ===&lt;br /&gt;
This is actually a very useful little function. First, it lets you ignore the differences between printing text to a client&#039;s console and into server console, and second, it makes implementation of other functions easier.&lt;br /&gt;
&lt;br /&gt;
 -- print message to either client&#039;s console or (if clientID == nil) to server console&lt;br /&gt;
 function printmsg(message, clientID)&lt;br /&gt;
     if not message then&lt;br /&gt;
         return&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     if clientID then&lt;br /&gt;
         et.trap_SendServerCommand(clientID, &amp;quot;print \&amp;quot;&amp;quot;.. message ..&amp;quot;^7\n\&amp;quot;&amp;quot;)&lt;br /&gt;
     else&lt;br /&gt;
         et.G_Print(message ..&amp;quot;^7\n&amp;quot;)&lt;br /&gt;
     end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The way it works is it gets a message and eventually client number. If it got client number, it prints the message to that client, if it got null as client number, it prints to server console. Combined with the way LUA handles function call parameters, the use looks like this: printmsg(&amp;quot;Hello&amp;quot;, 2) prints &amp;quot;Hello&amp;quot; into console of client #2; printmsg(&amp;quot;Hello&amp;quot;) prints &amp;quot;Hello&amp;quot; into server console.&lt;br /&gt;
&lt;br /&gt;
The second reason why I found it useful is, you can easily make functions that can be called through both server and client console and need to print some output - just give them clientID parameter, when calling it from server console put clientID = null and let the printmsg function handle it. Example of such function is the next one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.5&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 25.3.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User_talk:Major_Zeman&amp;diff=2714</id>
		<title>User talk:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User_talk:Major_Zeman&amp;diff=2714"/>
		<updated>2007-04-20T13:28:34Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: Im just stupid - moved to user page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2713</id>
		<title>User:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User:Major_Zeman&amp;diff=2713"/>
		<updated>2007-04-20T13:28:15Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: init&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently (= for about last 3 years) found at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== get GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.5&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 25.3.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples here&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
	<entry>
		<id>https://wolfwiki.anime.net/index.php?title=User_talk:Major_Zeman&amp;diff=2712</id>
		<title>User talk:Major Zeman</title>
		<link rel="alternate" type="text/html" href="https://wolfwiki.anime.net/index.php?title=User_talk:Major_Zeman&amp;diff=2712"/>
		<updated>2007-04-20T13:22:15Z</updated>

		<summary type="html">&lt;p&gt;Major Zeman: init&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table witdh=&amp;quot;100%&amp;quot; height=&amp;quot;70px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td width=&amp;quot;100px&amp;quot; align=&amp;quot;center&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;http://forums.acidrainclan.com/uploads/MajorZeman/2006-04-26_152247_avatar_zeman.jpg&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;center&amp;quot;&amp;gt;Major Zeman can be currently (= for about last 3 years) found at [http://forums.acidrainclan.com forums.acidrainclan.com].&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LUA Code fragments ==&lt;br /&gt;
During my first adventure into the world of LUA+ETPro, I ran into several problems. Here are a few functions/code fragments that I think are worth mentioning or could be useful to someone in future:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== get GUID ===&lt;br /&gt;
A simple function that gives you guid of the player in given slot. The function performs some checks and converts the guid to uppercase for exact matches.&lt;br /&gt;
 -- gets user&#039;s guid&lt;br /&gt;
 -- returns nil if not applicable to entity number&lt;br /&gt;
 function getguid(targetID)&lt;br /&gt;
     if (targetID == nil) or (targetID &amp;gt; tonumber(et.trap_Cvar_Get(&amp;quot;sv_maxclients&amp;quot;))) or (not et.gentity_get(targetID,&amp;quot;inuse&amp;quot;)) then&lt;br /&gt;
         return nil&lt;br /&gt;
     end&lt;br /&gt;
 &lt;br /&gt;
     local userinfo = et.trap_GetUserinfo( targetID )&lt;br /&gt;
     local guid = et.Info_ValueForKey( userinfo, &amp;quot;cl_guid&amp;quot; )&lt;br /&gt;
     -- upcase for exact matches&lt;br /&gt;
     guid = string.upper(guid)&lt;br /&gt;
 &lt;br /&gt;
     return guid&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MZ&#039;s TJ mod ==&lt;br /&gt;
version: 1.5&amp;lt;br /&amp;gt;&lt;br /&gt;
released: 25.3.2007&amp;lt;br /&amp;gt;&lt;br /&gt;
[[http://etdl.phpnet.us/ download zip] | [http://etdl.phpnet.us/TJmod_mz.lua lua]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Yet another /save /load mod - this one should be useful for learning and teaching how to trickjump, for &#039;&#039;pro TJ servers&#039;&#039; it&#039;s probably rather useless.&lt;br /&gt;
&lt;br /&gt;
The mod is based on Kyoko&#039;s HSP_TJmod, with fragments of code (sometimes big fragments eh) from ==FF==im2good4u, Furion and robably also from ReyalP. Feengur&#039;s ZeN mod was a source of inspiration for me, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Key features (as found in Kyoko&#039;s TJmod) ===&lt;br /&gt;
* &#039;&#039;&#039;/save&#039;&#039;&#039; and &#039;&#039;&#039;/load&#039;&#039;&#039; - stores your possition on map for each team separately and allows you to teleport back&lt;br /&gt;
* &#039;&#039;&#039;/gotohell&#039;&#039;&#039; - server console command, gibs player&lt;br /&gt;
* &#039;&#039;&#039;/goto&#039;&#039;&#039; and &#039;&#039;&#039;/iwant&#039;&#039;&#039; - server console commands, teleport one person to another&lt;br /&gt;
* &#039;&#039;&#039;/goback&#039;&#039;&#039; - if the person was teleported using /iwant, this server console command moves them back to original location&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New features (differences from original mod) ===&lt;br /&gt;
* some code cleanup and formating, parameter checks blah blah blah etc.&lt;br /&gt;
* &#039;&#039;&#039;/save2&#039;&#039;&#039; and &#039;&#039;&#039;/load2&#039;&#039;&#039; - second save slot. This one is common for both teams and you can /save2 and /load2 also as spectator&lt;br /&gt;
* easy jump skipping using /save2 as spectator (here you&#039;ll have to decide whether this mod is good or bad for your server)&lt;br /&gt;
* some more administrative commands: &#039;&#039;&#039;/rmsaves&#039;&#039;&#039;, &#039;&#039;&#039;/sdisable&#039;&#039;&#039;, &#039;&#039;&#039;/senable&#039;&#039;&#039; (inspired by ZeN)&lt;br /&gt;
* all commands allow &#039;&#039;partial name match&#039;&#039; as player identification in parameters (altered code from im2good4u)&lt;br /&gt;
* saves and /sdisable are persistent across player&#039;s reconnects (as long as the script is not reloaded by loading other map etc. the saves persist - &#039;&#039;the save slots are indexed by guid not player slot&#039;&#039;)&lt;br /&gt;
* /iwant and /goback print explanatory script to target&lt;br /&gt;
* /gotohell (and alias &#039;&#039;&#039;/gib&#039;&#039;&#039;) play a sound (again a bit of code from im2good4u) and print a message to everyone&lt;br /&gt;
* &#039;&#039;&#039;/disarm&#039;&#039;&#039; command strips a player off all weapons except syringes, knife, binocs and pliers (maybe some more but no shooting weapons) - either for current life or permanently (again altered im2good4u&#039;s code)&lt;br /&gt;
* &#039;&#039;&#039;/dist&#039;&#039;&#039; gives you distance from others - rather useless but fun command that I found has one practical use after all - you can see who specs you&lt;br /&gt;
* &#039;&#039;&#039;/realsay&#039;&#039;&#039; and &#039;&#039;&#039;/realvsay&#039;&#039;&#039; - sends message only to players close to you - this sounds pretty weird but it&#039;s useful if you want to explain a trickjump in one room and don&#039;t want to confuse those at other jumps&lt;br /&gt;
* &#039;&#039;&#039;/TJplayers&#039;&#039;&#039; server console command gives admins overview of info held about the connected players&lt;br /&gt;
* &#039;&#039;&#039;/TJhelp&#039;&#039;&#039; gives overview of client commands, &#039;&#039;&#039;/rcon TJhelp&#039;&#039;&#039; gives help for server console commands&lt;br /&gt;
* all server commands behave properly and print their output back to caller&#039;s console even if used through SemiAdmin command (found a workaround :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Drawbacks ===&lt;br /&gt;
* &#039;&#039;no support for etadmin&#039;&#039; - never worked with that and don&#039;t know how it works&lt;br /&gt;
* tried to make users stop on load and failed just like all before me did :D&lt;br /&gt;
* the workaround to print output back to semiadmin is a bit messy and uses et_Print callback (possible server performance decrease)&lt;br /&gt;
* &#039;&#039;not good for pro TJ servers and seevers without active admins&#039;&#039; - you can really skip jumps easily and eventually end maps in no time&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Thank you ===&lt;br /&gt;
Kyoko / Kotoko&amp;lt;br /&amp;gt;&lt;br /&gt;
im2good4u&amp;lt;br /&amp;gt;&lt;br /&gt;
Furion&amp;lt;br /&amp;gt;&lt;br /&gt;
ReyalP&amp;lt;br /&amp;gt;&lt;br /&gt;
Feengur&amp;lt;br /&amp;gt;&lt;br /&gt;
All the guys who wrote LUA API description and code examples on http://wolfwiki.anime.net/&lt;/div&gt;</summary>
		<author><name>Major Zeman</name></author>
	</entry>
</feed>