<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://wiki.minegoboom.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=BaK</id>
		<title>ASSS Wiki - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://wiki.minegoboom.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=BaK"/>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php/Special:Contributions/BaK"/>
		<updated>2026-05-05T16:04:09Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.28.2</generator>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Writing_Advanced_Modules_In_C&amp;diff=6154</id>
		<title>Writing Advanced Modules In C</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Writing_Advanced_Modules_In_C&amp;diff=6154"/>
				<updated>2010-12-29T21:33:36Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: /* Passing Multiple Arguments To Commands */ fixed a bug, a memory leak, and made it cross platform&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial explains how to write advanced modules in C. It is assumed you know how to code and are familiar with how the ASSS code works.&lt;br /&gt;
&lt;br /&gt;
This tutorial is a continuation of [[Writing Modules In C]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Some useful references:&lt;br /&gt;
&lt;br /&gt;
http://qnxcs.unomaha.edu/help/product/neutrino/lib_ref/summary.html&lt;br /&gt;
&lt;br /&gt;
http://www.cplusplus.com/reference/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Passing Data To Timers ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
typedef struct ThisIsData&lt;br /&gt;
{&lt;br /&gt;
	Player *p;&lt;br /&gt;
	int number;&lt;br /&gt;
} ThisIsData;&lt;br /&gt;
&lt;br /&gt;
local int timerfunc(void *vp) //vp is void pointer, just an address that can point anywhere&lt;br /&gt;
{&lt;br /&gt;
	ThisIsData *tid=(ThisIsData*)vp; //we know it points to our data&lt;br /&gt;
	&lt;br /&gt;
	if(tid-&amp;gt;number == 10)&lt;br /&gt;
	{&lt;br /&gt;
		//if it worked anything in here will work too&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	//return 1 if you want timer to run again, or 0 if you want it to be removed&lt;br /&gt;
	int returnValue = 0;&lt;br /&gt;
&lt;br /&gt;
	if (returnValue == 0)&lt;br /&gt;
		afree(tid); // free the data we have previously allocated&lt;br /&gt;
&lt;br /&gt;
	return returnValue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
anotherfunction()&lt;br /&gt;
{&lt;br /&gt;
	ThisIsData *tid=amalloc(sizeof(ThisIsData)); //we must allocate memory because anything in this function is destroyed when it ends&lt;br /&gt;
&lt;br /&gt;
	tid-&amp;gt;number=10&lt;br /&gt;
&lt;br /&gt;
	//now set timer to activate in 1000 centiseconds, then repeat every 100.&lt;br /&gt;
	//we are also sending the address of the memory we just allocated.&lt;br /&gt;
	ml-&amp;gt;SetTimer(timerfunc,1000,100,tid,0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Passing Multiple Arguments To Commands ==&lt;br /&gt;
&lt;br /&gt;
Since the words are read one by one, then checked against the whole list, they can be in any order!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// define macros for comparing strings that work for both linux and windows&lt;br /&gt;
#ifdef WIN32&lt;br /&gt;
	#define STRCASECMP stricmp&lt;br /&gt;
	#define STRNCASECMP strnicmp&lt;br /&gt;
#else&lt;br /&gt;
	#define STRCASECMP strcasecmp&lt;br /&gt;
	#define STRNCASECMP strncasecmp&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
local void examplecommand(const char *command, const char *params, Player *p, const Target *t)&lt;br /&gt;
{&lt;br /&gt;
	char *sentence=strdup(params); //strdup clones a string because strtok replaces &amp;quot; &amp;quot; with a \0&lt;br /&gt;
	char *word=strtok(sentence,&amp;quot; &amp;quot;); //strtok reads everything until first \0 into word&lt;br /&gt;
	&lt;br /&gt;
	while(word) //while word != null&lt;br /&gt;
	{&lt;br /&gt;
		if(!STRNCASECMP(word,&amp;quot;a=&amp;quot;,2)) //STRNCASECMP is a case insensitive comparison that returns 0 if the same, with a number&lt;br /&gt;
		{&lt;br /&gt;
			//do stuff if first 2 letters of word are 'a' then '='&lt;br /&gt;
&lt;br /&gt;
			word+=2; //like move start of word 2 letters forward&lt;br /&gt;
			int check=atoi(word); //then read a number&lt;br /&gt;
		}&lt;br /&gt;
		else if(!STRNCASECMP(word,&amp;quot;bc=&amp;quot;,3))&lt;br /&gt;
		{&lt;br /&gt;
			//do stuff if first 3 letters of word are 'b' then 'c' then '='&lt;br /&gt;
&lt;br /&gt;
			word+=3; //make sure you move it 3 letters and not 2&lt;br /&gt;
			int check=atoi(word); //then read a number&lt;br /&gt;
		}&lt;br /&gt;
		else if(!STRCASECMP(word,&amp;quot;-de&amp;quot;)) //thats STRCASECMPwith no N, it checks the whole thing&lt;br /&gt;
		{&lt;br /&gt;
			//do stuff if word is &amp;quot;-de&amp;quot;&lt;br /&gt;
		}&lt;br /&gt;
		word=strtok(NULL,&amp;quot; &amp;quot;); //advance to next word, or set word to null if none left&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	afree(sentence); // since we allocated a string with strdup, we must free the associated memory manually&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Creating Callbacks ==&lt;br /&gt;
&lt;br /&gt;
Write me!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//example code goes here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Creating Interfaces ==&lt;br /&gt;
&lt;br /&gt;
Cover overwriting existing interfaces to replace old modules.&lt;br /&gt;
Write me!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//example code goes here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sending Packets To Players ==&lt;br /&gt;
&lt;br /&gt;
Cover position packets, weapon packets, clientset stuff, etc.&lt;br /&gt;
Write me!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//example code goes here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Using Advisors ==&lt;br /&gt;
&lt;br /&gt;
Write me!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//example code goes here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Creating Advisors ==&lt;br /&gt;
&lt;br /&gt;
Write me!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//example code goes here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Module]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Writing_Advanced_Modules_In_C&amp;diff=6153</id>
		<title>Writing Advanced Modules In C</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Writing_Advanced_Modules_In_C&amp;diff=6153"/>
				<updated>2010-12-29T21:25:06Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: /* Passing Data To Timers */ let's not have memory leaks in sample code&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial explains how to write advanced modules in C. It is assumed you know how to code and are familiar with how the ASSS code works.&lt;br /&gt;
&lt;br /&gt;
This tutorial is a continuation of [[Writing Modules In C]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Some useful references:&lt;br /&gt;
&lt;br /&gt;
http://qnxcs.unomaha.edu/help/product/neutrino/lib_ref/summary.html&lt;br /&gt;
&lt;br /&gt;
http://www.cplusplus.com/reference/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Passing Data To Timers ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
typedef struct ThisIsData&lt;br /&gt;
{&lt;br /&gt;
	Player *p;&lt;br /&gt;
	int number;&lt;br /&gt;
} ThisIsData;&lt;br /&gt;
&lt;br /&gt;
local int timerfunc(void *vp) //vp is void pointer, just an address that can point anywhere&lt;br /&gt;
{&lt;br /&gt;
	ThisIsData *tid=(ThisIsData*)vp; //we know it points to our data&lt;br /&gt;
	&lt;br /&gt;
	if(tid-&amp;gt;number == 10)&lt;br /&gt;
	{&lt;br /&gt;
		//if it worked anything in here will work too&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	//return 1 if you want timer to run again, or 0 if you want it to be removed&lt;br /&gt;
	int returnValue = 0;&lt;br /&gt;
&lt;br /&gt;
	if (returnValue == 0)&lt;br /&gt;
		afree(tid); // free the data we have previously allocated&lt;br /&gt;
&lt;br /&gt;
	return returnValue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
anotherfunction()&lt;br /&gt;
{&lt;br /&gt;
	ThisIsData *tid=amalloc(sizeof(ThisIsData)); //we must allocate memory because anything in this function is destroyed when it ends&lt;br /&gt;
&lt;br /&gt;
	tid-&amp;gt;number=10&lt;br /&gt;
&lt;br /&gt;
	//now set timer to activate in 1000 centiseconds, then repeat every 100.&lt;br /&gt;
	//we are also sending the address of the memory we just allocated.&lt;br /&gt;
	ml-&amp;gt;SetTimer(timerfunc,1000,100,tid,0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Passing Multiple Arguments To Commands ==&lt;br /&gt;
&lt;br /&gt;
Since the words are read one by one, then checked against the whole list, they can be in any order!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
local void examplecommand(const char *command, const char *params, Player *p, const Target *t)&lt;br /&gt;
{&lt;br /&gt;
	char *sentence=strdup(params); //strdup clones a string because strtok replaces &amp;quot; &amp;quot; with a \0&lt;br /&gt;
	char *word=strtok(params,&amp;quot; &amp;quot;); //strtok reads everything until first \0 into word&lt;br /&gt;
	&lt;br /&gt;
	while(word) //while word != null&lt;br /&gt;
	{&lt;br /&gt;
		if(!strnicmp(word,&amp;quot;a=&amp;quot;,2)) //strnicmp is a case insensitive comparison that returns 0 if the same, with a number&lt;br /&gt;
		{&lt;br /&gt;
			//do stuff if first 2 letters of word are 'a' then '='&lt;br /&gt;
&lt;br /&gt;
			word+=2; //like move start of word 2 letters forward&lt;br /&gt;
			int check=atoi(word); //then read a number&lt;br /&gt;
		}&lt;br /&gt;
		else if(!strnicmp(word,&amp;quot;bc=&amp;quot;,3))&lt;br /&gt;
		{&lt;br /&gt;
			//do stuff if first 3 letters of word are 'b' then 'c' then '='&lt;br /&gt;
&lt;br /&gt;
			word+=3; //make sure you move it 3 letters and not 2&lt;br /&gt;
			int check=atoi(word); //then read a number&lt;br /&gt;
		}&lt;br /&gt;
		else if(!stricmp(word,&amp;quot;-de&amp;quot;)) //thats stricmp with no N, it checks the whole thing&lt;br /&gt;
		{&lt;br /&gt;
			//do stuff if word is &amp;quot;-de&amp;quot;&lt;br /&gt;
		}&lt;br /&gt;
		word=strtok(NULL,&amp;quot; &amp;quot;); //advance to next word, or set word to null if none left&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Creating Callbacks ==&lt;br /&gt;
&lt;br /&gt;
Write me!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//example code goes here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Creating Interfaces ==&lt;br /&gt;
&lt;br /&gt;
Cover overwriting existing interfaces to replace old modules.&lt;br /&gt;
Write me!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//example code goes here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sending Packets To Players ==&lt;br /&gt;
&lt;br /&gt;
Cover position packets, weapon packets, clientset stuff, etc.&lt;br /&gt;
Write me!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//example code goes here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Using Advisors ==&lt;br /&gt;
&lt;br /&gt;
Write me!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//example code goes here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Creating Advisors ==&lt;br /&gt;
&lt;br /&gt;
Write me!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//example code goes here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Module]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Payday_Loans_-_How_to_Get_a_Bad-_Credit_personal_Loan&amp;diff=6152</id>
		<title>Payday Loans - How to Get a Bad- Credit personal Loan</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Payday_Loans_-_How_to_Get_a_Bad-_Credit_personal_Loan&amp;diff=6152"/>
				<updated>2010-12-29T21:13:41Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: Payday Loans - How to Get a Bad- Credit personal Loan moved to Spam page del me: spam page, i dont know how to delete&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Spam page del me]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=MERVBot_Tutorial&amp;diff=6048</id>
		<title>MERVBot Tutorial</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=MERVBot_Tutorial&amp;diff=6048"/>
				<updated>2009-08-01T07:25:40Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: /* File stream input */ typo in comment&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is based on the ever-popular MERVBot Tutorial by Underlord. It has since been updated to reflect new changes with MervBot. To see examples of how to use this instruction, see [[MERVBot Example Code]].&lt;br /&gt;
&lt;br /&gt;
This tutorial also assumes that you have a basic knowledge of C++. If you don't, check out cplusplus.com's great [http://www.cplusplus.com/doc documentation].&lt;br /&gt;
&lt;br /&gt;
==Setting up a MERVBot (plugin)==&lt;br /&gt;
&lt;br /&gt;
[http://mervbot.com MERVBot download site]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Obtaining MERVBot===&lt;br /&gt;
&lt;br /&gt;
* Download the [http://mervbot.com/files/MERVBot.rar latest build].&lt;br /&gt;
* Unrar MERVBot.rar into a new folder. (example c:\program files\continuum\mervbot)&lt;br /&gt;
* Unzip src.zip into &amp;amp;quot;src&amp;amp;quot; subfolder of that new folder (example c:\program files\continuum\mervbot\src)&lt;br /&gt;
&lt;br /&gt;
===Preparing to write a plugin===&lt;br /&gt;
&lt;br /&gt;
''Note:'' if you only want to execute someone's premade plugin (.dll), skip to [[MERVBot Tutorial#Run your bot dll|step 4]], otherwise continue to learn how to make your own bot&lt;br /&gt;
&lt;br /&gt;
Download [http://catid.sscontinuum.com/files/Tutorial.rar DLL-plugin Tutorial] and unzip Tutorial.zip (containing spawn.h, spawn.cpp, and command.cpp) into a &amp;amp;quot;tutorial&amp;amp;quot; subfolder of that new folder. (example c:\program files\continuum\mervbot\src\tutorial).&lt;br /&gt;
&lt;br /&gt;
''File descriptions:''&lt;br /&gt;
* spawn.h = declare/initialize globals&lt;br /&gt;
* command.cpp = code for commands coming into bot (ie /!help, /!play, etc)&lt;br /&gt;
* spawn.cpp = code that interacts with bot spawns&lt;br /&gt;
&lt;br /&gt;
===Microsoft Visual c++===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Start Visual Studios 6.0.&lt;br /&gt;
&amp;lt;li&amp;gt;Click the Drop Down Menu labeled &amp;amp;quot;File&amp;amp;quot; at the top left of your screen.&lt;br /&gt;
&amp;lt;li&amp;gt;Click &amp;amp;quot;New&amp;amp;quot;.&lt;br /&gt;
&amp;lt;li&amp;gt;On the next screen that comes up, choose from the Project tab, then Win32 Dynamic-Link Library&lt;br /&gt;
&amp;lt;li&amp;gt;Select the &amp;amp;quot;/src&amp;amp;quot; folder as the base folder (example c:\program files\continuum\mervbot\src)&lt;br /&gt;
&amp;lt;li&amp;gt;Name your project &amp;amp;quot;mybot&amp;amp;quot;. This will make a &amp;amp;quot;mybot&amp;amp;quot; subfolder in your &amp;amp;quot;src&amp;amp;quot; folder. Click OK. (example creates c:\program files\continuum\mervbot\src\mybot)&lt;br /&gt;
&amp;lt;li&amp;gt;Choose to create an &amp;amp;quot;Empty DLL project&amp;amp;quot;.&lt;br /&gt;
&amp;lt;li&amp;gt;Click &amp;amp;quot;Finish&amp;amp;quot;.&lt;br /&gt;
&amp;lt;li&amp;gt;Click the Drop Down Menu labbled &amp;amp;quot;Project&amp;amp;quot;.&lt;br /&gt;
&amp;lt;li&amp;gt;Click &amp;amp;quot;Add To Project Files&amp;amp;quot;&lt;br /&gt;
&amp;lt;li&amp;gt;Copy only spawn.h, spawn.cpp, and command.cpp from the &amp;amp;quot;tutorial&amp;amp;quot; folder into the this new folder. (example from c:\program files\continuum\mervbot\src\tutorial to c:\program files\continuum\mervbot\src\mybot)&lt;br /&gt;
&amp;lt;li&amp;gt;Click the Drop Down Menu labelled &amp;amp;quot;Build&amp;amp;quot;.&lt;br /&gt;
&amp;lt;li&amp;gt;Click &amp;amp;quot;Build (dll name)&amp;amp;quot; - where (dll name) is &amp;amp;quot;mybot&amp;amp;quot;&lt;br /&gt;
&amp;lt;li&amp;gt;Go into your &amp;amp;quot;mybot&amp;amp;quot; folder and look for a folder named &amp;amp;quot;Debug&amp;amp;quot;&lt;br /&gt;
(example c:\program files\continuum\mervbot\src\mybot\debug)&lt;br /&gt;
&amp;lt;li&amp;gt;Your new DLL will be in that folder. (example mybot.dll)&lt;br /&gt;
&amp;lt;li&amp;gt;Copy mybot.dll to your base folder that has mervbot.exe in it (example c:\program files\continuum\mervbot)&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Run your bot dll===&lt;br /&gt;
&lt;br /&gt;
To run your bot you need your DLL (mybot.dll), Commands.txt, MERVBot.exe, MERVBot.ini, Operators.txt, Spawns.txt, and zlib.dll all in one folder (example c:\program files\continuum\mervbot).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Edit spawns.txt. '''Read every word of spawns.txt to find out what needs to go in there.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
''Example:''&lt;br /&gt;
&amp;lt;pre&amp;gt;2v2-Bot-League : botpw : 2v2a : 2v2league : staffpw&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''Note:'' The bot will attempt to create the name if it doesn't exist already.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Edit MERVBot.ini&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;[Login]&lt;br /&gt;
Zone=216.33.98.254:21000	// your zone IP:PORT available from zone.dat in Continuum dir&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Edit operators.txt. '''Read every word of operators.txt to find out what needs to go in there.'''&amp;lt;br /&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
''Example:''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
4:my_name:&lt;br /&gt;
4:another_sysop:&lt;br /&gt;
3:other_person:&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Make sure the bot is on vip.txt or has smod+ access, then run MERVBot.exe.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;You can now edit your plugin code by opening &amp;amp;quot;mybot.dsw&amp;amp;quot; (example c:\program files\continuum\mervbot\src\mybot\mybot.dsw) in Microsoft Visual C++. Edit the spawn.h, spawn.cpp, and command.cpp to create your plugin, then build, copy your updated DLL to your MERVBot.exe folder and then execute the bot. Use the tutorial to get ideas on how to implement certain types of features into the bot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Player Commands - (command.cpp)==&lt;br /&gt;
&lt;br /&gt;
This section describes how to implement player commands into your plugin. Commands are sent to the botInfo::gotCommand function in command.cpp.&lt;br /&gt;
&lt;br /&gt;
Example (makes bot reply to !test with &amp;quot;hi&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void botInfo::gotCommand(Player *p, Command *c) {&lt;br /&gt;
	switch (p-&amp;gt;access)&lt;br /&gt;
	{&lt;br /&gt;
        case OP_Moderator:&lt;br /&gt;
                {&lt;br /&gt;
                     // handle moderator-operator commands here.&lt;br /&gt;
                }&lt;br /&gt;
	case OP_Player: //appropriate staff rank here.&lt;br /&gt;
		{&lt;br /&gt;
			if (c-&amp;gt;check(&amp;quot;test&amp;quot;)) //replace &amp;quot;test&amp;quot; with whatever command you want&lt;br /&gt;
			{&lt;br /&gt;
				//put your command code here&lt;br /&gt;
				sendPrivate(p,&amp;quot;hi&amp;quot;); //example&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===How to have commands with numerical parameters===&lt;br /&gt;
Example (!test #):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	if (c-&amp;gt;check(&amp;quot;test&amp;quot;)) { // reads in test #, default to 1 if invalid number input&lt;br /&gt;
		int temp = 1;&lt;br /&gt;
&lt;br /&gt;
		if (isNumeric(c-&amp;gt;final))&lt;br /&gt;
			temp = atoi(c-&amp;gt;final);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===How to have player name as input===&lt;br /&gt;
Example (!rank player):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	if (c-&amp;gt;check(&amp;quot;rank&amp;quot;))&lt;br /&gt;
	{&lt;br /&gt;
		String player_name = c-&amp;gt;final;&lt;br /&gt;
&lt;br /&gt;
		if (player_name.IsEmpty()) // default name to self if invalid name&lt;br /&gt;
			player_name = p-&amp;gt;name;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===How to have multi-parameter input===&lt;br /&gt;
&lt;br /&gt;
Use the CRT function sscanf() to scan the string for the values.&lt;br /&gt;
&lt;br /&gt;
Example (!squads squadA vs squadB ''or'' !squads teamA:squadA:teamB:squadB):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
else if (c-&amp;gt;check(&amp;quot;squads&amp;quot;))&lt;br /&gt;
{&lt;br /&gt;
	char squadA[20], squadB[20];&lt;br /&gt;
	int teamA, teamB;&lt;br /&gt;
&lt;br /&gt;
	strncpy(squadA, &amp;quot;&amp;quot;, 20);&lt;br /&gt;
	strncpy(squadB, &amp;quot;&amp;quot;, 20);&lt;br /&gt;
&lt;br /&gt;
	int n_found;&lt;br /&gt;
&lt;br /&gt;
	//Note: %[A-Za-z ] is equivalent to %s, but allows an internal space.&lt;br /&gt;
&lt;br /&gt;
	//scan the string for the two squads separated by &amp;quot; vs &amp;quot;&lt;br /&gt;
	n_found = sscanf(c-&amp;gt;final, &amp;quot;%[A-Za-z ] vs %[A-Za-z ]&amp;quot;, squadA, squadB);&lt;br /&gt;
&lt;br /&gt;
	//if that fails, scan the string for freqA:squadA:freqB:squadB&lt;br /&gt;
	if (n_found &amp;lt; 2)&lt;br /&gt;
		sscanf(c-&amp;gt;final, &amp;quot;%d:%[A-Za-z ]:%d:%[A-Za-z ]&amp;quot;, &amp;amp;teamA, squadA, &amp;amp;teamB, squadB);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Help Menu===&lt;br /&gt;
When a player sends !help to the bot, MERVBot calls botInfo::gotHelp() in each plugin loaded.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void botInfo::gotHelp(Player *p, Command *c)&lt;br /&gt;
{&lt;br /&gt;
	if (!*c-&amp;gt;final)&lt;br /&gt;
	{&lt;br /&gt;
	sendPrivate(p, &amp;quot;4v4 Bot General Commands:&amp;quot;);&lt;br /&gt;
	sendPrivate(p, &amp;quot;------------------------&amp;quot;);&lt;br /&gt;
	sendPrivate(p, &amp;quot;!caps - get captain names&amp;quot;);&lt;br /&gt;
	sendPrivate(p, &amp;quot;!roster &amp;lt;squad&amp;gt; - get roster of a squad&amp;quot;);&lt;br /&gt;
	sendPrivate(p, &amp;quot;!schedule- get current schedule&amp;quot;);&lt;br /&gt;
	sendPrivate(p, &amp;quot;!score - get current score&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Event Calls==&lt;br /&gt;
&lt;br /&gt;
MERVBot is event based, so when making a bot you need to decide what will happen at certain events. Normal plugins need to consider what happens when bot enters arena, player enters arena, player leaves arena, player events like kill, shipchange, teamchange, spec, move then any other relevant events to your bot. Just worry about events that are relevant to the tasks your bot is doing.&lt;br /&gt;
&lt;br /&gt;
MERVBot sends events to botInfo::gotEvent() in spawn.cpp. Each supported event is already present and categorized in gotEvent(), along with the paramters that MERVBot sends with the event. When a plugin wants the bot to do something, it sends tell(event) to the bot.&lt;br /&gt;
&lt;br /&gt;
See dllcore.h for a list of current events and their descriptions. Dllcore.h also contains functions (like makeFollowing) to make events to send back to the bot via tell().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;tell(makeFollowing(false));&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==The Messaging System==&lt;br /&gt;
&lt;br /&gt;
Private message - void sendPrivate(Player *player, char *msg);&lt;br /&gt;
&lt;br /&gt;
''Examples:''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sendPrivate(p,&amp;quot;hi&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
String s=&amp;quot;test&amp;quot;;&lt;br /&gt;
sendPrivate(p,s);&lt;br /&gt;
&lt;br /&gt;
String s=&amp;quot;test&amp;quot;;&lt;br /&gt;
s += &amp;quot;ing&amp;quot;;&lt;br /&gt;
sendPrivate(p,s);&lt;br /&gt;
&lt;br /&gt;
char captain1[20];&lt;br /&gt;
char captain2[20];&lt;br /&gt;
strncpy(captain1,&amp;quot;&amp;quot;,20);&lt;br /&gt;
strncpy(captain2,&amp;quot;&amp;quot;,20);&lt;br /&gt;
sendPrivate(p,(String) captain1 + &amp;quot; and &amp;quot; + (String) captain2 + &amp;quot; are the captains.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Team message - void sendTeamPrivate(Uint16 team, char *msg);&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Examples: &amp;lt;br /&amp;gt;&lt;br /&gt;
a) sendTeamPrivate(8025,&amp;amp;quot;hi spec freq&amp;amp;quot;);&amp;lt;br /&amp;gt;&lt;br /&gt;
b) Uint16 test=0; sendTeamPrivate(test,&amp;amp;quot;hi freq 0&amp;amp;quot;);&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Public message - void sendPublic(char *msg);&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Example: sendPublic(&amp;amp;quot;*arena &amp;amp;quot; + (String) p-&amp;amp;gt;name + &amp;amp;quot; is now a captain&amp;amp;quot;);&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
Chat channel message - void sendChannel(char *msg);&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Example: sendChannel(&amp;amp;quot;hi chat channel&amp;amp;quot;);&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
Remote private message - void sendRemotePrivate(char *name, char *msg);&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Example: sendRemotePrivate(&amp;amp;quot;Player01&amp;amp;quot;, &amp;amp;quot;hi&amp;amp;quot;);&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: to have bot print several lines of text fast it needs sysop in the&lt;br /&gt;
arena (sysop in arena bot first spawns to also) otherwise it'll print slow to avoid being&lt;br /&gt;
kicked for spam&lt;br /&gt;
&lt;br /&gt;
===Output of data in messages===&lt;br /&gt;
&amp;lt;p&amp;gt;An example of using normal strings to output data/messages.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 // does *arena X pilots left in game&lt;br /&gt;
 // NOTE: variable temp needs to be defined with some value&lt;br /&gt;
&lt;br /&gt;
 String s = &amp;quot;*arena &amp;quot;;&lt;br /&gt;
       s += temp;&lt;br /&gt;
       s += &amp;quot; pilots left in the game.&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
 sendPublic(s);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Or,&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 //NOTE: this can be considered inefficient.&lt;br /&gt;
&lt;br /&gt;
 sendPublic(&amp;quot;*arena &amp;quot; + (String)temp + &amp;quot; pilots left in the game&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;An example using sprintf to align/space data, where output data will be in this approximate format.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// output data will be in this approximate format (not lined up perfectly because of html)&lt;br /&gt;
// --------------------------------------------------------------------------------------&lt;br /&gt;
// Squad: squadname       PTS     FPTS    K    D  DMG DEALT TAKEN   F  FK    FLT&lt;br /&gt;
// --------------------------------------------------------------------------------------&lt;br /&gt;
// PlayerA              10000      500  116  101       9999 99999  10 150 980:55&lt;br /&gt;
// PlayerB                500      200    7    5       9999 99999   5   3   0:04&lt;br /&gt;
&lt;br /&gt;
char str[255];&lt;br /&gt;
sendPublic(&amp;quot;*arena--------------------------------------------------------------------------------&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
sprintf(str, &amp;quot;*arena Squad: %-20s   PTS     FPTS   K   D  DMG DEALT  TAKEN  F  FK  FLT&amp;quot;,&lt;br /&gt;
         freqs[freq].freqname&lt;br /&gt;
        );&lt;br /&gt;
&lt;br /&gt;
sendPublic(str);&lt;br /&gt;
&lt;br /&gt;
sendPublic(&amp;quot;*arena--------------------------------------------------------------------------------&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
            // assuming existing freqs struct with data&lt;br /&gt;
            for (pilot=freqs[freq].playercount-1; pilot&amp;gt;=0; pilot--)&lt;br /&gt;
            {&lt;br /&gt;
                // on freq squad so print stats&lt;br /&gt;
                char outString[255];&lt;br /&gt;
&lt;br /&gt;
                sprintf(outString, &amp;quot;*arena %-20s %12d %8d %3d %3d %10d %6d %2d %3d %3d:%02d&amp;quot;,&lt;br /&gt;
                       freqs[freq].pilots[pilot].name,&lt;br /&gt;
                       freqs[freq].pilots[pilot].points,&lt;br /&gt;
                       freqs[freq].pilots[pilot].flagpoints,&lt;br /&gt;
                       freqs[freq].pilots[pilot].kills,&lt;br /&gt;
                       freqs[freq].pilots[pilot].deaths,&lt;br /&gt;
                       freqs[freq].pilots[pilot].dmgdealt,&lt;br /&gt;
                       freqs[freq].pilots[pilot].dmgtaken,&lt;br /&gt;
                       freqs[freq].pilots[pilot].flags,&lt;br /&gt;
                       freqs[freq].pilots[pilot].flagkills,&lt;br /&gt;
                       freqs[freq].pilots[pilot].flagtime /60,&lt;br /&gt;
                       freqs[freq].pilots[pilot].flagtime %60&lt;br /&gt;
                       );&lt;br /&gt;
                &lt;br /&gt;
                sendPublic(outString);&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // Notes: sprintf format = sprintf(output char string, spacing, variables)&lt;br /&gt;
            // Notes: s = chars, d = integer, - = left align, right align default&lt;br /&gt;
            // Notes: doing %02d = put 0 in front if not 2 digits, %3d:%02d makes 0:04 format&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Time==&lt;br /&gt;
&lt;br /&gt;
Each time MERVBot sends an EVENT_Tick to a plugin (once a second), the default handler code decrements each value in an array of countdowns. You can modify the number of countdowns and add code to occur at a specific value for one of the countdowns.&lt;br /&gt;
&lt;br /&gt;
Setup number of timers and initialize in spawn.h:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class botInfo&lt;br /&gt;
{&lt;br /&gt;
	#define COUNTDOWNS 10 		// how many countdowns you want&lt;br /&gt;
	int countdown[COUNTDOWNS];	// this gives you 10 timers&lt;br /&gt;
&lt;br /&gt;
// unrelated code&lt;br /&gt;
 &lt;br /&gt;
	public:&lt;br /&gt;
	botInfo(CALL_HANDLE given)&lt;br /&gt;
	{&lt;br /&gt;
	countdown[0] = 0;&lt;br /&gt;
	countdown[1] = 60; // 60 seconds&lt;br /&gt;
	//&lt;br /&gt;
	// initialize values&lt;br /&gt;
	//&lt;br /&gt;
	countdown[9] = 5*60; // 5 minutes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Using timer functions in spawn.cpp:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
case EVENT_Tick:&lt;br /&gt;
{&lt;br /&gt;
	for (int i = 0; i &amp;lt; COUNTDOWNS; ++i) //cycles through each countdown you have&lt;br /&gt;
		--countdown[i]; //note that countdowns will continue decrementing past 0.&lt;br /&gt;
&lt;br /&gt;
	if (countdown[1] == 2) // when timer #1 hits two seconds&lt;br /&gt;
	{&lt;br /&gt;
	// do stuff here when timer #1 hits 2 seconds&lt;br /&gt;
	// example: sendPublic(&amp;quot;two seconds left, setting timer to 1 minute&amp;quot;);&lt;br /&gt;
	// example: countdown[1] = 60; // change timer #1 value&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can then have events (such as EVENT_PlayerDeath) change the value of a countdown to make the bot do something a set time after an event occurs.&lt;br /&gt;
&lt;br /&gt;
=== Tracking time not using countdown[n] ===&lt;br /&gt;
&lt;br /&gt;
This is a solution to a common problem of determining the amount of time it takes for something to occur. Using basic math, we record a start-time B, and an end-time E, both in the unit of seconds, we calculate the time elapsed by E-B.&lt;br /&gt;
&lt;br /&gt;
Lucky for us, Windows provides a function called GetTickCount() that is a measurement of time (milliseconds) that we can use for such cases.&lt;br /&gt;
&lt;br /&gt;
So:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	int begin = GetTickCount();&lt;br /&gt;
&lt;br /&gt;
	// do some code here.&lt;br /&gt;
&lt;br /&gt;
	int end = GetTickCount();&lt;br /&gt;
  &lt;br /&gt;
	int delta = (end - begin) / 1000;  // elapsed time converted to seconds from milliseconds&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Obtaining the current time ===&lt;br /&gt;
&lt;br /&gt;
''Requirements:'' Include &amp;lt;time.h&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 char u[100];&lt;br /&gt;
 time_t t=time(NULL);&lt;br /&gt;
 tm *tmp = localtime(&amp;amp;t);&lt;br /&gt;
 strftime(u,99,&amp;quot;%c&amp;quot;,tmp);&lt;br /&gt;
 sendPublic(&amp;quot;Current date and time: &amp;quot; + u);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Writing Functions==&lt;br /&gt;
&amp;lt;!-- begin of functions. --&amp;gt;&lt;br /&gt;
For this example, we will take the function called closeto, which determines&lt;br /&gt;
if a player exists in an specific radius around a point. Now to apply this function to a MervBot plugin, you need to write it into the spawn.cpp - at the top of the file in the //////// DLL &amp;amp;quot;import&amp;amp;quot; //////// setion, as below:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//////// DLL &amp;quot;import&amp;quot; ////////&lt;br /&gt;
&lt;br /&gt;
bool closeto(Player *p, int x, int y, int tolerance) &lt;br /&gt;
{&lt;br /&gt;
	// Requires the function abs() to be declared elsewhere.&lt;br /&gt;
	// Return if player p is in area of square with center x, y&lt;br /&gt;
	//   and radius = tolerance&lt;br /&gt;
	return (abs((p-&amp;gt;tile.x) - x) - tolerance) &amp;amp;&amp;amp; (abs((p-&amp;gt;tile.y) - y) - tolerance);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want your function to have access to the data from spawn.h botInfo class, you make the function apart of it. To do this, we add the '''botInfo::''' infront of the function name, in spawn.cpp.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//////// DLL &amp;quot;import&amp;quot; ////////&lt;br /&gt;
&lt;br /&gt;
bool botInfo::closeto(Player *p, int x, int y, int tolerance) &lt;br /&gt;
    {&lt;br /&gt;
	 ...&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In '''spawn.h''', add your method's prototype without botInfo::, it will look&lt;br /&gt;
like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//...&lt;br /&gt;
botInfo(CALL_HANDLE given)&lt;br /&gt;
 {&lt;br /&gt;
//  ...&lt;br /&gt;
 } &lt;br /&gt;
  bool closeto(Player *p, int x, int y, int tolerance); // Your function prototype.&lt;br /&gt;
&lt;br /&gt;
  void clear_objects(); //provided by Catid, and already exists.&lt;br /&gt;
  void object_target(Player *p); //provided by Catid, and already exists.&lt;br /&gt;
//  ...&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you're not familiar with prototypes, notice it is similar to that in your spawn.cpp, but without the botInfo::, and a trailing ;.&lt;br /&gt;
&lt;br /&gt;
===Function notes===&lt;br /&gt;
&lt;br /&gt;
Remember that you can pass variables [http://www.cplusplus.com/doc/tutorial/tut2-3.html by reference]. If variables are passed by reference, any changes a function makes to the variables will remain after the function returns.&lt;br /&gt;
&lt;br /&gt;
From time to time you will need to pass an array to a function. An example illustrating this is:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	int freqs[5]; // declare our example data.&lt;br /&gt;
&lt;br /&gt;
	// call function - notice freqs and not freqs[5] or freqs[].&lt;br /&gt;
	my_function(freqs); //You're not passing the array itself, just a pointer to the array.&lt;br /&gt;
&lt;br /&gt;
	// function - notice freqs[] and not freqs[5] or freqs&lt;br /&gt;
	void my_function(int freqs[]) {} //You're specifying that the freqs parameter is an array&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Cycling through players==&lt;br /&gt;
&lt;br /&gt;
MERVBot stores player-related data in a linked list. A linked list is a datatype that stores its data in a series of structures linked to each other, hence the name.&lt;br /&gt;
&lt;br /&gt;
To search through the players in the arena, just start at the first link, then continue through all the following links until you reach the end:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
_listnode &amp;lt;Player&amp;gt; *parse = playerlist-&amp;gt;head;	//set to first link of the player linked list&lt;br /&gt;
&lt;br /&gt;
while (parse)	//parse will be NULL when we reach the last link&lt;br /&gt;
{&lt;br /&gt;
	Player *p = parse-&amp;gt;item;	//item is the actual data stored in the link&lt;br /&gt;
&lt;br /&gt;
	// do functionality here&lt;br /&gt;
	// Example 1: sendPrivate(p,&amp;quot;*watchdamage&amp;quot;); // turns on all pilot's watchdamage&lt;br /&gt;
	// Example 2: if (p-&amp;gt;safety != 0) sendPrivate(p,&amp;quot;*spec&amp;quot;); // spec all pilots in safe zone&lt;br /&gt;
&lt;br /&gt;
	parse = parse-&amp;gt;next;	//set parse to the next link&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, assuming our bot has smod+ privilages, the following code will set all non-spectator players to a specific ship. First begin by adding the following function prototype to the spawn.h in the botInfo class:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void handleCmdSetShip(enum Ship_Types ship);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In spawn.cpp add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void botInfo::handleCmdSetShip(enum Ship_Types ship)&lt;br /&gt;
{&lt;br /&gt;
	//Note that the parameter ship is of the Ship_Types enum,&lt;br /&gt;
	//so its value is hopefully restricted to the proper types.&lt;br /&gt;
&lt;br /&gt;
	_listnode &amp;lt;Player&amp;gt; *parse = playerlist-&amp;gt;head;&lt;br /&gt;
	while (parse)&lt;br /&gt;
	{&lt;br /&gt;
		Player *p = parse-&amp;gt;item;&lt;br /&gt;
&lt;br /&gt;
		if ( p-&amp;gt;ship != ship &amp;amp;&amp;amp; p-&amp;gt;ship != SHIP_Spectator )&lt;br /&gt;
				sendPrivate(p, &amp;quot;*setship &amp;quot; + (String)ship);&lt;br /&gt;
&lt;br /&gt;
		parse = parse-&amp;gt;next;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To use, just call the function with the appropriate Ship_Type from the enum in clientprot.h:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 handleCmdSetShip(SHIP_Warbird);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Random numbers==&lt;br /&gt;
&lt;br /&gt;
===Generating a random number===&lt;br /&gt;
&lt;br /&gt;
To use this method, these two includes must be used:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;quot;time.h&amp;quot;    //provides time() function.&lt;br /&gt;
#include &amp;quot;stdlib.h&amp;quot;  //provides srand() and rand() functions.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    srand(time(NULL)); // seed random number generator.&lt;br /&gt;
&lt;br /&gt;
    rand(); // randomize.&lt;br /&gt;
&lt;br /&gt;
    int temp = (int) (51 * ((float)rand()/RAND_MAX));&lt;br /&gt;
       // the above line returns a random integer between 0 and 51.&lt;br /&gt;
       // Note: RAND_MAX is a global constant defined in stdlib.h&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Picking a random pilot===&lt;br /&gt;
&lt;br /&gt;
''Note:'' A required user-defined function, getInGame(), must be created for this example to work.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int temp = GetTickCount() % getInGame();  // getInGame() = how many pilots in arena&lt;br /&gt;
&lt;br /&gt;
Player *rabbit = NULL;&lt;br /&gt;
&lt;br /&gt;
_listnode &amp;lt;Player&amp;gt; *parse = playerlist-&amp;gt;head;&lt;br /&gt;
while (parse)&lt;br /&gt;
{&lt;br /&gt;
	Player *p = parse-&amp;gt;item;&lt;br /&gt;
&lt;br /&gt;
	if (p-&amp;gt;ship != SHIP_Spectator) // if player is not a spectator&lt;br /&gt;
	if ( !(--temp) ) // and if we've hit the randomly-selected pilot&lt;br /&gt;
	{&lt;br /&gt;
		rabbit = p;&lt;br /&gt;
		break;&lt;br /&gt;
	}&lt;br /&gt;
	parse = parse-&amp;gt;next;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Storing data for pilots==&lt;br /&gt;
&lt;br /&gt;
There are several ways to store data for pilots (ie tracking flagtime or kills in a period of time). Note that these methods are all purely internal to the bot, and don't effect anything beyond the plugin in any way.&lt;br /&gt;
&lt;br /&gt;
# Built-in get/setTag: Tracks data until player leaves the arena, then automatically deletes data.&lt;br /&gt;
# Modified perm get/setTag: Tracks data until bot leaves arena, then automatically deletes data. (Advantage: easier to sort by player)&lt;br /&gt;
# Custom Structs: Tracks data until plugin deletes it. (Advantage: easier to sort by freqs)&lt;br /&gt;
&lt;br /&gt;
''Note:'' 2 and 3 are similar in effect, mostly the difference is in how you are able to search through data you need to decide which method of storing data is best for each bot depending on what it does.&lt;br /&gt;
&lt;br /&gt;
===Built-in get/setTag method===&lt;br /&gt;
&lt;br /&gt;
Player tags simply tag a player with a number. Define the wanted values in '''spawn.h''' at the top:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define DMG_DEALT        0&lt;br /&gt;
#define DMG_TAKEN        1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In spawn.cpp, initialize the values on ArenaEnter and PlayerEnter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
case EVENT_ArenaEnter:&lt;br /&gt;
{&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// do for all pilots in arena when bot enters&lt;br /&gt;
	_listnode &amp;lt;Player&amp;gt; *parse = playerlist-&amp;gt;head;&lt;br /&gt;
	while (parse)&lt;br /&gt;
	{&lt;br /&gt;
	   Player *p = parse-&amp;gt;item;  // get pilot&lt;br /&gt;
&lt;br /&gt;
	   set_tag(p, DMG_DEALT, 0); // initialize to 0&lt;br /&gt;
	   set_tag(p, DMG_TAKEN, 0);&lt;br /&gt;
	   sendPrivate(p, &amp;quot;*watchdamage&amp;quot;);  // optionally turn on player *watchdamage&lt;br /&gt;
&lt;br /&gt;
	   parse = parse-&amp;gt;next;  // get next pilot&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
case EVENT_PlayerEntering:&lt;br /&gt;
{&lt;br /&gt;
//	...&lt;br /&gt;
	set_tag(p, DMG_DEALT, 0); // initialize to 0&lt;br /&gt;
	set_tag(p, DMG_TAKEN, 0);&lt;br /&gt;
	sendPrivate(p,&amp;quot;*watchdamage&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then somewhere edit the tag values:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
case EVENT_WatchDamage:&lt;br /&gt;
{&lt;br /&gt;
	// sets tag for k (shooter) to be old value plus damage currently dealt&lt;br /&gt;
&lt;br /&gt;
	int old_damage = get_tag(k, DMG_BOMB_DEALT);&lt;br /&gt;
	set_tag(k, DMG_BOMB_DEALT, old_damage + damage);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following demonstrates how to retrieve the tag values as a command in command.cpp:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (c-&amp;gt;check(&amp;quot;showstats&amp;quot;))&lt;br /&gt;
{&lt;br /&gt;
	int temp = get_tag(p, DMG_TOTAL_DEALT);&lt;br /&gt;
&lt;br /&gt;
	String s = &amp;quot;You've done &amp;quot;;&lt;br /&gt;
	s += temp;&lt;br /&gt;
	s += &amp;quot; damage so far!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	sendPrivate(p,s);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Modified permanent get/setTag method===&lt;br /&gt;
&lt;br /&gt;
This method is the same as get/setTag with some modifications to the tag code to retain them after the player leaves. Beware of using this method if bot is in an arena for long periods of time, linkedlist could get huge.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// spawn.h, add char name[20]; into struct PlayerTag&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct PlayerTag&lt;br /&gt;
{&lt;br /&gt;
	Player *p;&lt;br /&gt;
	char name[20];&lt;br /&gt;
	int index;&lt;br /&gt;
	int data;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In spawn.cpp:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	case EVENT_PlayerLeaving:&lt;br /&gt;
	{&lt;br /&gt;
	    Player *p = (Player*)event.p[0];&lt;br /&gt;
&lt;br /&gt;
	    // killTags(p);  // remove so tag not deleted on arena exit&lt;br /&gt;
&lt;br /&gt;
//	...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Locate in spawn.cpp and modify accordingly:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int botInfo::get_tag(Player *p, int index)&lt;br /&gt;
{&lt;br /&gt;
    _listnode &amp;lt;PlayerTag&amp;gt; *parse = taglist.head;&lt;br /&gt;
    PlayerTag *tag;&lt;br /&gt;
&lt;br /&gt;
    while (parse)&lt;br /&gt;
    {&lt;br /&gt;
      tag = parse-&amp;gt;item;&lt;br /&gt;
&lt;br /&gt;
      // if (tag-&amp;gt;p == p)&lt;br /&gt;
      if (strcmp(tag-&amp;gt;name,p-&amp;gt;name)==0)  // now tracking by player name, not pointer&lt;br /&gt;
      if (tag-&amp;gt;index == index)&lt;br /&gt;
        return tag-&amp;gt;data;&lt;br /&gt;
&lt;br /&gt;
      parse = parse-&amp;gt;next;&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void botInfo::set_tag(Player *p, int index, int data)&lt;br /&gt;
{&lt;br /&gt;
    _listnode &amp;lt;PlayerTag&amp;gt; *parse = taglist.head;&lt;br /&gt;
    PlayerTag *tag;&lt;br /&gt;
&lt;br /&gt;
    while (parse)&lt;br /&gt;
    {&lt;br /&gt;
      tag = parse-&amp;gt;item;&lt;br /&gt;
&lt;br /&gt;
      //if (tag-&amp;gt;p == p)&lt;br /&gt;
      if (strcmp(tag-&amp;gt;name,p-&amp;gt;name)==0) // now tracking by player name, not pointer&lt;br /&gt;
      if (tag-&amp;gt;index == index)&lt;br /&gt;
      {&lt;br /&gt;
        tag-&amp;gt;data = data;&lt;br /&gt;
        return;&lt;br /&gt;
      }&lt;br /&gt;
      parse = parse-&amp;gt;next;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    tag = new PlayerTag;&lt;br /&gt;
    // tag-&amp;gt;p = p; // not tracking by pointer anymore&lt;br /&gt;
    strncpy(tag-&amp;gt;name, p-&amp;gt;name, 20); // tracking by player name&lt;br /&gt;
    tag-&amp;gt;index = index;&lt;br /&gt;
    tag-&amp;gt;data = data;&lt;br /&gt;
    taglist.append(tag);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using structs===&lt;br /&gt;
&lt;br /&gt;
In '''spawn.h''':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class botInfo&lt;br /&gt;
{&lt;br /&gt;
	struct freqdata &lt;br /&gt;
	{&lt;br /&gt;
		int kills, deaths;&lt;br /&gt;
	};&lt;br /&gt;
// ...&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To make use of this structure, implement accordingly:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	freqdata freqs[100]; // 100 of those structs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Access the data in spawn.cpp using&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
freqs[56].kills = 1;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See CPlusPlus.com's [http://www.cplusplus.com/doc/tutorial/tut3-5.html Structures] tutorial for a more comprehensive guide. Note that, as shown on the bottom of the page, you can have structures within structures. Thus, for example, you could have a structure for each freq with a structure for each player nested within them.&lt;br /&gt;
&lt;br /&gt;
==Input/Output to files==&lt;br /&gt;
&lt;br /&gt;
For reading and/or writing to files with C++ you must have the required include statement as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;fstream&amp;gt;&lt;br /&gt;
using namespace std;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===File stream input===&lt;br /&gt;
The following example will show you how to read a file, duel.ini, line by line.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;quot;stdlib.h&amp;quot; // for atoi()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  ifstream file(&amp;quot;duel.ini&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  if (!file.good()) // if there was an error opening the file&lt;br /&gt;
    sendPublic(&amp;quot;*arena Error opening file for reading&amp;quot;); // or add your own error handler&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    char line[256];&lt;br /&gt;
&lt;br /&gt;
    // read in MaxBoxes=X&lt;br /&gt;
    while (file.getline(line, 256))&lt;br /&gt;
    {&lt;br /&gt;
     &lt;br /&gt;
      if (CMPSTART(&amp;quot;MaxBoxes=&amp;quot;, line)) //Does the line begin with MaxBoxes= ?&lt;br /&gt;
      {&lt;br /&gt;
        MAX_BOXES = atoi(&amp;amp;(line[9]));  //If so, read the value into an integer, using atoi.&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    file.close();&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===File stream output===&lt;br /&gt;
The following code example will demonstrate how to append to a file, duelleaguestat.inc.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 ofstream file(&amp;quot;duelleaguestat.inc&amp;quot;, ios::app);   // app = put all data at end of file&lt;br /&gt;
&lt;br /&gt;
 if (!file.good()) // if there was an error opening the file&lt;br /&gt;
   sendPublic(&amp;quot;*arena Error opening file.&amp;quot;);&lt;br /&gt;
 else&lt;br /&gt;
 {&lt;br /&gt;
   file &amp;lt;&amp;lt; squad1&amp;lt;&amp;lt; endl;  // squad1 = char[20]&lt;br /&gt;
   file &amp;lt;&amp;lt; &amp;quot; vs &amp;quot;&amp;lt;&amp;lt; endl;&lt;br /&gt;
   file &amp;lt;&amp;lt; squad2&amp;lt;&amp;lt; endl;  // squad2 = char[20]&lt;br /&gt;
   file.close();&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, you are able to write an output of a String to a file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 // key is converting String to (char*) to file write&lt;br /&gt;
 String str = freqs[freq].slotname[slot];&lt;br /&gt;
 str += &amp;quot;, Repels: &amp;quot; + (String)(int) t-&amp;gt;repel;&lt;br /&gt;
 file &amp;lt;&amp;lt; endl;&lt;br /&gt;
 file &amp;lt;&amp;lt; (char*) str;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Input with GetPrivateProfileString===&lt;br /&gt;
&lt;br /&gt;
GetPrivateProfileString(), a function provided by Windows for reading INI files, will automatically find an INI key (like &amp;quot;MaxBoxes=&amp;quot;) in a file for you. See the [http://msdn.microsoft.com/library MSDN Library] for help on this function. This next example will show how to read input using GetPrivateProfileString() based on the rampage plugin.&lt;br /&gt;
&lt;br /&gt;
The file format for rampage.ini is like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 7=is on a killing spree! (6:0)&lt;br /&gt;
 10=is opening a can of booya! (9:0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In '''rampageini.cpp''':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;quot;rampageini.h&amp;quot;&lt;br /&gt;
#define WIN32_LEAN_AND_MEAN&lt;br /&gt;
#include &amp;lt;windows.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUM_RANKS 10&lt;br /&gt;
#define BUFFER_LEN 256&lt;br /&gt;
&lt;br /&gt;
struct RampageSettings&lt;br /&gt;
{&lt;br /&gt;
	char quotes[NUM_RANKS][BUFFER_LEN];&lt;br /&gt;
};&lt;br /&gt;
 &lt;br /&gt;
void LoadSettings(RampageSettings &amp;amp;setts);&lt;br /&gt;
&lt;br /&gt;
static char path[BUFFER_LEN];&lt;br /&gt;
&lt;br /&gt;
char *rank_type[NUM_RANKS] = { &amp;quot;7&amp;quot;, &amp;quot;10&amp;quot; };&lt;br /&gt;
&lt;br /&gt;
void LoadSettings(RampageSettings &amp;amp;setts)&lt;br /&gt;
{&lt;br /&gt;
	GetCurrentDirectory(BUFFER_LEN - 64, path);&lt;br /&gt;
	strcat(path, &amp;quot;\rampage.ini&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	for (int i = 0; i &amp;lt; NUM_RANKS; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		GetPrivateProfileString(&amp;quot;Comments&amp;quot;, rank_type[i], &amp;quot;-ERROR-&amp;quot;,&lt;br /&gt;
					setts.quotes[i], BUFFER_LEN, path);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Player data==&lt;br /&gt;
&lt;br /&gt;
As stated earlier in the tutorial, MervBot stores useful player data internally as Player objects, see player.h for implementation details.&lt;br /&gt;
&lt;br /&gt;
* p-&amp;gt;name = player name stored as char[20] (''Note:'' SubSpace protocol allows for usernames to be 19+ in length, do not rely on this for player-name comparisions.)&lt;br /&gt;
* p-&amp;gt;squad = player squad stored as char[20]&lt;br /&gt;
* p-&amp;gt;ship = ship (0-9) enumerated as SHIP_Warbird, SHIP_Spectator, etc..&lt;br /&gt;
* p-&amp;gt;safety = whether ship is in safety zone (boolean)&lt;br /&gt;
* p-&amp;gt;bounty = player bounty&lt;br /&gt;
* p-&amp;gt;energy = player energy (have bot with *energy on to get accurate readings)&lt;br /&gt;
* p-&amp;gt;flagCount = how many flags player is holding&lt;br /&gt;
* p-&amp;gt;team = player frequency&lt;br /&gt;
* p-&amp;gt;(burst, repel, thor, brick, decoy, rocket, portal) = how many items of that type player has&lt;br /&gt;
* p-&amp;gt;(stealth, cloak, xradar, awarp, ufo, flash, safety, shields, supers) = if player has that item on (boolean)&lt;br /&gt;
* p-&amp;gt;score.killPoints = player kill points&lt;br /&gt;
* p-&amp;gt;score.flagPoints = player flag points&lt;br /&gt;
* p-&amp;gt;score.wins = player kills from f2&lt;br /&gt;
* p-&amp;gt;score.losses = player deaths from f2&lt;br /&gt;
&lt;br /&gt;
Just access the respective member of the Player class to check the player's property.&lt;br /&gt;
&lt;br /&gt;
For example, in spawn.cpp, to check whether a player is in a safety zone:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
EVENT_PlayerMove:&lt;br /&gt;
{&lt;br /&gt;
   Player *p = (Player*)event.p[0];&lt;br /&gt;
&lt;br /&gt;
   if ( p-&amp;gt;safety ) // player is in safe zone.&lt;br /&gt;
     {&lt;br /&gt;
        // do something.&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
   if ( !p-&amp;gt;safety ) // player NOT in safe zone.&lt;br /&gt;
     {&lt;br /&gt;
        // do something.&lt;br /&gt;
     }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Obtaining a player pointer using name comparison ===&lt;br /&gt;
&lt;br /&gt;
Since Player pointers are internal to MERVBot, it is necessary to find a way of obtaining a Player pointer from the identifying information given by the game. One of the simpler ways is just to compare the names after converting to lowercase.&lt;br /&gt;
&lt;br /&gt;
''Note'': Using pilot names as vital comparisions should be used with caution. See [http://cypherjf.sscentral.com/articles/bots-as-clients/ Bot-Issues] by CypherJF.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// return Player* info (or NULL if not found) from p-&amp;gt;name info&lt;br /&gt;
Player * botInfo::GetPilot(char *name)&lt;br /&gt;
{&lt;br /&gt;
	// get pilot from a name, return as TempPlayer&lt;br /&gt;
	_listnode &amp;lt;Player&amp;gt; *parse = playerlist-&amp;gt;head;&lt;br /&gt;
&lt;br /&gt;
	//convert search name to lowercase&lt;br /&gt;
	char nname[20], pname[20];&lt;br /&gt;
	strncpy(nname, name, 20);&lt;br /&gt;
	tolower(nname);&lt;br /&gt;
&lt;br /&gt;
	while (parse)&lt;br /&gt;
	{&lt;br /&gt;
		Player *p = parse-&amp;gt;item;&lt;br /&gt;
&lt;br /&gt;
		// convert to lowercase to compare&lt;br /&gt;
		strncpy(pname,p-&amp;gt;name,20);&lt;br /&gt;
		tolower(pname);&lt;br /&gt;
		if (strcmp(pname,nname)==0)&lt;br /&gt;
			return p;&lt;br /&gt;
		&lt;br /&gt;
		parse = parse-&amp;gt;next;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return NULL;	//player not found&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Bot built in functions==&lt;br /&gt;
&lt;br /&gt;
Here are some useful MervBot commands to control what the bot is doing.&lt;br /&gt;
&lt;br /&gt;
Player.cpp:&lt;br /&gt;
* Player::move(Sint32 x, Sint32 y) moves a player to the coordinates specified by x and y&lt;br /&gt;
* Player::clone(Player *p) clones a player into a player class&lt;br /&gt;
&lt;br /&gt;
Look in Commands.txt , command.cpp (core), or /!help to bot to see all bot external commands (example /!go &amp;amp;lt;arena&amp;amp;gt;).&lt;br /&gt;
&lt;br /&gt;
''LVZ Object toggling commands in plugins are to go here.''&lt;br /&gt;
&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_Eclipse&amp;diff=6009</id>
		<title>Creating and Testing a Simple Discretion Module in Eclipse</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_Eclipse&amp;diff=6009"/>
				<updated>2009-04-06T10:39:53Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: and apparently I did too :/&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how anyone can using minGW (and probably g++) and Eclipse to compile a simple module and put get it to run on [[Discretion]]. It assumes you're using Windows (although g++ may work) and you don't have any tools installed. However, you should have already gotten the source code (if not see the [[Obtaining the Discretion Source using Subversion]] tutorial). This tutorial is part of a series of tutorials consisting of the [[Discretion Module Tutorial]].&lt;br /&gt;
&lt;br /&gt;
minGW stands for minimalistic Gnu for Windows. It is an open source complier almost identical to gcc and g++, which are the compilers used for linux, among other things. The compiler produces native Windows exectuables, and best of all it's free! However, its interface isn't the best for the novice user. Thus, we use eclipse to help manage the minGW compiler for us.&lt;br /&gt;
&lt;br /&gt;
Eclipse, is an integrated development environment (IDE) which is also open-source and free. It is basically a program that makes it easier to make other programs. It was originally designed for Java development, but people made plugins to allow C++ development. These extensions are called the CDT (C/C++ Development Tooling). The CDT integrates nicely with minGW so these two make a good match. Discretion's modules come with Eclipse Projects when you get the source so modifications are easy to make. Eclipse is implemented in Java, so in order to use it you need the Java Runtime Environment. The good news is you probably already have this installed. Nonetheless, the tutorial covers downloading it if you don't already have it installed.&lt;br /&gt;
&lt;br /&gt;
==Videos==&lt;br /&gt;
&lt;br /&gt;
This tutorial is divided a few parts:&lt;br /&gt;
* [[Media:Disc_mingw.wmv|Obtaining and Testing minGW]]&lt;br /&gt;
* [[Media:Disc_jre.wmv|Getting the Java Runtime Environment]] (90% of people can skip this step)&lt;br /&gt;
* [[Media:Disc_eclipse.wmv|Downloading Eclipse with CDT]]&lt;br /&gt;
* [[Media:Disc_simplemod.wmv|Creating and Testing a Simple Module within Discretion]]&lt;br /&gt;
* [[Media:Disc_tricks.wmv|Discretion with Eclipse Tricks and Tips]]&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
&lt;br /&gt;
minGW: [http://sourceforge.net/project/showfiles.php?group_id=2435 Sourceforge File List]&lt;br /&gt;
&lt;br /&gt;
java runtime environment: [http://java.sun.com/javase/downloads/?intcmp=1281 Downloads]&lt;br /&gt;
&lt;br /&gt;
eclipse: [http://www.eclipse.org/downloads/ Eclipse Downloads]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_Eclipse&amp;diff=6008</id>
		<title>Creating and Testing a Simple Discretion Module in Eclipse</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_Eclipse&amp;diff=6008"/>
				<updated>2009-04-06T10:38:52Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: mgb messed up one of the video links :/&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how anyone can using minGW (and probably g++) and Eclipse to compile a simple module and put get it to run on [[Discretion]]. It assumes you're using Windows (although g++ may work) and you don't have any tools installed. However, you should have already gotten the source code (if not see the [[Obtaining the Discretion Source using Subversion]] tutorial). This tutorial is part of a series of tutorials consisting of the [[Discretion Module Tutorial]].&lt;br /&gt;
&lt;br /&gt;
minGW stands for minimalistic Gnu for Windows. It is an open source complier almost identical to gcc and g++, which are the compilers used for linux, among other things. The compiler produces native Windows exectuables, and best of all it's free! However, its interface isn't the best for the novice user. Thus, we use eclipse to help manage the minGW compiler for us.&lt;br /&gt;
&lt;br /&gt;
Eclipse, is an integrated development environment (IDE) which is also open-source and free. It is basically a program that makes it easier to make other programs. It was originally designed for Java development, but people made plugins to allow C++ development. These extensions are called the CDT (C/C++ Development Tooling). The CDT integrates nicely with minGW so these two make a good match. Discretion's modules come with Eclipse Projects when you get the source so modifications are easy to make. Eclipse is implemented in Java, so in order to use it you need the Java Runtime Environment. The good news is you probably already have this installed. Nonetheless, the tutorial covers downloading it if you don't already have it installed.&lt;br /&gt;
&lt;br /&gt;
==Videos==&lt;br /&gt;
&lt;br /&gt;
This tutorial is divided a few parts:&lt;br /&gt;
* [[Media:Disc_disc_mingw.wmv|Obtaining and Testing minGW]]&lt;br /&gt;
* [[Media:Disc_jre.wmv|Getting the Java Runtime Environment]] (90% of people can skip this step)&lt;br /&gt;
* [[Media:Disc_eclipse.wmv|Downloading Eclipse with CDT]]&lt;br /&gt;
* [[Media:Disc_simplemod.wmv|Creating and Testing a Simple Module within Discretion]]&lt;br /&gt;
* [[Media:Disc_tricks.wmv|Discretion with Eclipse Tricks and Tips]]&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
&lt;br /&gt;
minGW: [http://sourceforge.net/project/showfiles.php?group_id=2435 Sourceforge File List]&lt;br /&gt;
&lt;br /&gt;
java runtime environment: [http://java.sun.com/javase/downloads/?intcmp=1281 Downloads]&lt;br /&gt;
&lt;br /&gt;
eclipse: [http://www.eclipse.org/downloads/ Eclipse Downloads]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Discretion&amp;diff=5974</id>
		<title>Discretion</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Discretion&amp;diff=5974"/>
				<updated>2008-10-01T02:58:52Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: /* Weapons */ removed bouncing bullet business&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:discretionss.PNG|thumb|A Screenshot of SubSpace Discretion.]]&lt;br /&gt;
&lt;br /&gt;
Discretion[http://ss-discretion.sf.net] is a [[SubSpace]] client created by [[User:BaK|BaK]]. It is open source, like [[ASSS]], and is released under the [http://en.wikipedia.org/wiki/GPL GPL]. Discretion was developed because of the limitations of the in-use client, [[Continuum]]. Furthermore, the lack of development of Continuum led to a situation where limitations in the client would never be overcome. Making heavy use of [http://en.wikipedia.org/wiki/Simple_DirectMedia_Layer SDL], Discretion is cross-platform, and is currently supported under Windows, Linux, and Mac OS X. Discretion is intended to be secure through design, rather than through obscurity like Continuum. It is designed to make cheating is impossible, rather than just difficult. There is also an extensive [[Discretion Module Tutorial]] on this wiki for those interested in helping out.&lt;br /&gt;
&lt;br /&gt;
Since cheating is to be made impossible, the server must check the data players send it for cheating. This requires modifying the server, which rules out using [[Subgame]]. There is, however, a modified ASSS Server that allows Discretion clients to connect. &lt;br /&gt;
&lt;br /&gt;
In order to encourage client development, Discretion is designed with a modular system similar to ASSS. There are interfaces which define actions for modules (such as &amp;quot;draw ship at 50,50&amp;quot;), and callbacks which signal when events occur (such as &amp;quot;player has been killed&amp;quot;). Where ever possible, magic values have been removed and are instead loaded from plain-text settings files. The goal of this is to eliminate any built-in constraints present in VIE SubSpace and Continuum. These magic values include the location / color of the FPS counter, 1024x1024 tiles in maps, each tile being 16x16 pixels, each ship image having 40 frames thus 9 degree turns, the number of fly over tiles, two sets of doors four tiles each per map, the 0x01 type packet corresponding to an arena login, friendly players showing up yellow in the stat box, the colors in the font file, the number of frames in the wormhole animation, the text that shows up when you press ESC, the number of ships, as well as all the settings Continuum does allow you to change such as the ship images, the game play settings, and the controls. The server is intended to be able to modify most of these, thus giving [[Zone]] developers maximum creativity and flexibility.&lt;br /&gt;
&lt;br /&gt;
==Modules==&lt;br /&gt;
Discretion is divided up into several modules, dynamically linked into the main program much like ASSS. These modules are desired to be as generic as possible, with their Continuum-like actions coming from the settings, rather than the modules themselves. Thus Discretion is like a 2D grid game engine, with settings and graphics which make it look like SubSpace. The module interfaces are documented in the corresponding header files using Javadoc-style documentation. There are currently over 30 modules in the Discretion release. Some of the main ones are discussed below.&lt;br /&gt;
&lt;br /&gt;
===Settings Handler===&lt;br /&gt;
The '''SettingsHandler''' modules loads the settings from ini-like plain text files. The main settings file is located in conf/MAIN.CONF, which #includes many other settings files. All these settings files are plain text, meaning they can be edited using a utility like pico or notepad. Individual settings can be specified in several formats, depending on how they should be interpreted. Supported types include integers (''50'', ''0x30'', ''0777''), strings (''hello person''), points/vectors/dimensions (''(100,200)''), rgb colors (''(255,255,255)'', ''(0,128,128)''), and [[LVZ]]-style screen locations (''(C+50,50)'', ''(B-10,C+25)''). There also exists a helper function to parse comma separated a list of strings from a single sting in shared/StringManip.h. This module interface also allows modules to load their own conf files, or save a group of settings to a file which the program can then read out of.&lt;br /&gt;
&lt;br /&gt;
The front end program, '''cskinviewer''' uses the saving capability of '''SettingsHandler''' to keep track of zone data between program executions.&lt;br /&gt;
&lt;br /&gt;
===Module Manager===&lt;br /&gt;
The '''Module Manger''' itself is a module which is loaded by the program, which then proceeds to load any other modules. This uses the setting Modules::Names which is a comma separated list of strings to figure out which modules to load. It loads module files, '.dll's in Windows and '.so's in Linux, from the bin/ directory. Modules are loaded in stages. During the first stage, LOADMODE_Init, modules register their interface, if any, with the '''Module Manager''' and register any callbacks they want to listen for. During the next stage, LOADMODE_LoadInterfaces, modules load any interfaces they plan to use. Finally, during LOADMODE_PostLoadInterfaces, modules can use their loaded interfaces to other modules to initialize themselves. Upon successful program termination, LOADMODE_Unload is invoked which allows the module to free any data or resources it's using. The module manager also facilitates callbacks. Where possible, C++ exception handling is used to aid in catching errors in a non-fatal way and reports the cause of the problem.&lt;br /&gt;
&lt;br /&gt;
Note that some initialization tasks should not be done in LOADMODE_PostLoadInterfaces since they require modules be initialized in a specific order. For example, the '''Text''' module, which writes text to the screen should not be initialized before the ''Graphics'' module is, since it would be unable to load the text image. Thus some initialization tasks are be done in callbacks, CB_LOADIMAGES in this instance.&lt;br /&gt;
&lt;br /&gt;
===Graphics===&lt;br /&gt;
The '''Graphics''' module allows one to load images and draw them to the screen or map. When an image is loaded through the interface, an image handle is given to the calling module which is used to refer to the image. This handle can also be used to get the image size (taking into account that some images are framed animations), or free the image when it's no longer needed. Blank images can also be created and drawn on, thus allowing one to predraw complex images instead of redrawing them every frame. Images, when drawn to the screen, are drawn in layers. This allows several modules to queue up images to be drawn out of order and still result in a correct drawing. Some layers include L_Tiles, L_Weapons, L_AfterWeapons, L_Gauges, L_Chat and L_TopMost. Images can be drawn relative to the screen, or relative to the map. Images can also be blended such that they appear translucent, as long as the user has Graphics::UseBlending set to 1. Rectangles of a constant color can also be drawn to the screen or on to another image. The images are queued up to be drawn during the CB_PRERENDER callback.&lt;br /&gt;
&lt;br /&gt;
Although providing a basic interface, it is uncommon to '''Graphics''' module directly for loading images. Instead the '''UniqueImage''' module allows one to specify an image in the settings and refer to it in code by a name. This is much easier than loading the image yourself, and easily allows a single graphic to contain many different images, which is not uncommon in SubSpace images (the bullets image, for example, contains images for all sorts of bullets rather than just a single type). The '''UniqueImage''' module makes sure to only keep a single copy of the image in memory at all times. The '''UniqueImage''' module, in turn, is used by the '''Animations''' module to provide simple access to SubSpace-style animations. Thus, a programmer can code something like 'draw animation &amp;quot;bullet explosion&amp;quot; at 512,512' and it will handle loading the image, figuring out how many frames there are, the speed of the animation, and how long to display it for.&lt;br /&gt;
&lt;br /&gt;
===Controls===&lt;br /&gt;
The '''Controls''' module permits the programmer to provide actions(&amp;quot;move forward&amp;quot;), while the settings specify exactly what keyboard or joystick input they correspond to(&amp;quot;up arrow key&amp;quot;). Controls should be registered in the CB_CONTROLSLOADED callback. Also, since this a generic module it does not capture any of the physical controls itself, instead relying on other modules to handle that aspect.&lt;br /&gt;
&lt;br /&gt;
The '''SDL Key Controls''' module handles capturing keyboard input and sending it to the '''Controls''' module. The '''Mouse''' module does not use the '''Controls''' module directly, instead providing its own interface which allows one to create mouse hotspots and be notified of mouse clicks or movements within these hotspots.&lt;br /&gt;
&lt;br /&gt;
===Timers===&lt;br /&gt;
Similar to how ASSS has timers implemented in the mainloop module, Discretion has a '''Timers''' module that provides a timer functionality. One can register a function to be called in X milliseconds, or every X milliseconds until it's canceled. Discretion is currently not multithreaded beyond SDL, so that a timer in an infinite loop (or any piece of code that gets to run, for that matter), will result in the program freezing up. Thus you should not use blocking calls in timers or take up too much processing time which will degrade performance.&lt;br /&gt;
&lt;br /&gt;
The '''Net''' module uses a timer to send and receive packets.&lt;br /&gt;
&lt;br /&gt;
===Text===&lt;br /&gt;
The '''Text''' module provides an easy way to draw text on the screen. This is the standard subspace text and can be specfied by color. This module draws the text on one line for a single frame. Therefore, you must call the appropriate functions in this interface during CB_PRERENDER every frame for however long you wish to display the text. There is support for drawing text relative to the screen or to the map, as well as blending text and drawing on any layer.&lt;br /&gt;
&lt;br /&gt;
The '''Textbox''' module uses '''Text''' to draw its text, but provides additional features such as drawing textbox borders and allowing easy textbox loading from files. '''EscapeBox''' and '''PlayerList''', in turn, use '''Textbox'''. '''Chat''' also makes use of the '''Text''' module when it draws player chat to the screen. The '''Flash''' module, which handles messages similar to SubSpace's kill and prize messages, also uses the '''Text''' module. Pretty much anywhere you see text, the '''Text''' module is at work.&lt;br /&gt;
&lt;br /&gt;
===Physics===&lt;br /&gt;
The '''Physics''' module provides functions which can give you a particle's new position given its initial position, velocity, and time elapsed. This is used for ships as well as weapons. The position can be advanced in such a way that is affected by the map (such as bombs going around a wormhole), or not. Particles can bounce off the level or explode on contact.&lt;br /&gt;
&lt;br /&gt;
The '''SelfShip''' module uses '''Physics''' to compute the new position of the player over time. '''SS_Items''' uses '''Physics''' to find the position of a bullet after a certain amount of time.&lt;br /&gt;
&lt;br /&gt;
===PerPlayerData===&lt;br /&gt;
The '''PerPlayerData''' module provides a simple way to have data that is common to every player. This is similar to ASSS' PlayerData module in that a struct of memory can be allocated for every player and referred to using a key. The module also facilitates simple sharing of per player data between module such as &amp;quot;name&amp;quot;, &amp;quot;x&amp;quot;, or &amp;quot;y&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The '''PlayerList''' module uses the sharing facility of '''PerPlayerData''' to get the names of the players on the player list.&lt;br /&gt;
&lt;br /&gt;
===Level===&lt;br /&gt;
The '''Level''' module provides a simple interface to possibly many different types of level formats. Modules can load levels through the interface, as well as get the map or tile size. Furthermore, forces on the level, such as wormholes, friction, or gravity can be applied through the interface.&lt;br /&gt;
&lt;br /&gt;
Currently, the only map format implemented is '''oldlvl''' which supports regular SubSpace [[LVL]] files. This provides a somewhat more generic implementation, which a customizable amount of doors or custom animation tiles (wormholes, space station, and asteriods), as well as having wormholes with different properties on the same map.&lt;br /&gt;
&lt;br /&gt;
===Front End===&lt;br /&gt;
The front end, not exactly a module, is implemented as its own program, '''cskinviewer''', contributed by [[User:Smong|Smong]]. This program allows one to download a list of ASSS servers from a [[Directory Server]], and choose one and login. It uses the '''SettingsHandler''' to save the current zone list to the settings. Custom zones can not be added through the interface yet, but can be added by hand by editing conf/profiles/ZoneList.conf. &lt;br /&gt;
&lt;br /&gt;
The front end executes '''in_game''', which in turn loads the '''Module Manager''' which runs '''Main SDL''' which runs callbacks to load the various SDL Subsystems and starts the program's main loop.&lt;br /&gt;
&lt;br /&gt;
==Contribute==&lt;br /&gt;
Development for Discretion is ongoing and everyone is encouraged to contribute. Graphics are always helpful, and if you have an idea feel free to make it. In the spirit of free software, it would be best if eventually all VIE owned graphics were replaced, as their copyright status is unknown. This includes the ships, bullets, default tileset, and all other graphics from VIE SubSpace or Continuum. Also, a Discretion [[skin]] is yet to be made for the front end (the format follows that of Continuum's, see the skins directory in your Continuum folder). Additionally, many features are in development or unimplemented. If one wanted to help out, just contact [[User:BaK|BaK]], or start working on graphics or a module. There is also a [[Discretion Module Tutorial]] which shows you how to create a simple module. Some planned modules include:&lt;br /&gt;
&lt;br /&gt;
====Star Background====&lt;br /&gt;
A '''StarBackground''' module that draws stars and planets similar to how Continuum does it. It would be great it this looked better than Continuum as it would really lead to the immersion necessary for a fun experience. This could also be used to draw all sorts of backgrounds, such as grass for earth-based zones, to provide an alternate to tiling LVZ all over the map. This would be a good module to make to get introduced to Discretion development.&lt;br /&gt;
&lt;br /&gt;
====LVZ====&lt;br /&gt;
A reverse compatible LVZ module is desired to allow current zones to easily switch over to Discretion without remaking their lvz files. This could provide additional functionality not present in current lvz such as lvz that depend on ship locations to allow animations within shipsets. The easier way to make this is probably to make a static image/animation module which uses the settings and '''UniqueImage''' and '''Animations''' to draw images on the map and screen. Then, an lvz compatibility layer module would be made which translates an lvz file into a .conf file and uses '''SettingsHandler''' to load in the images from the generated file.&lt;br /&gt;
&lt;br /&gt;
====Radar====&lt;br /&gt;
Subspace and Continuum include a radar for locating enemies. This will have to be implemented in Discretion. The users should also be able to make the radar bigger by pressing a key (alt).&lt;br /&gt;
&lt;br /&gt;
====Sound====&lt;br /&gt;
Sound provides immersion in video games and gives them an authentic feel. We need a way to play sounds when certain actions occur such as a bullet being fired or player bouncing off a wall. WAV sounds will have to be implemented for reverse compatibility, but mp3 is not out of the question for longer sounds such as victory music or just music in general. After this is done, a built in mp3 player could be made to allow players to change songs from within the game. SDL_mixer[http://www.libsdl.org/projects/SDL_mixer/] provides mp3 capabilities and may be used.&lt;br /&gt;
&lt;br /&gt;
====Weapons====&lt;br /&gt;
There are many items SubSpace uses which must be implemented. Care must be taken here to prevent cheating. For example, it would not be difficult to write a program to detect right before a player is about to get hit and automatically portal out or repel. Thus, these items may have to be modified to be on a timer, so that using a portal might require your ship to take a second to &amp;quot;charge up&amp;quot; instead of instantly warping. Also, it would be great if weapons didn't have to follow boring straight lines and instead could turn. Thus I could specify in the settings the direction a weapon would travel if the ship were facing straight up and it would happen. So a straight line would be (0,t), a curvy shot may be (sin(t),t), a shot that speeds up over time may be (0,2^t).&lt;br /&gt;
&lt;br /&gt;
====Custom Client Side Code====&lt;br /&gt;
The server should be able to provide code that can be executed client side. There are two types of code that will be provided: updated versions of modules, and game play related code. This is especially dangerous since a malicious server owner should not be permitted to compromise players' computers. The module updates can be done by providing a RSA signature with the binary .dll or .so which can be checked before executing any downloaded files. As for game play related code, a Java virtual machine could be used with a Security Manager that allows nothing beyond basic functions. Then, an interface could be provided to the game code that could be used by the code. Thus, binary .class file could be distributed for an arena that aren't allowed to delete files off your computer, but are allowed to access the game play relayed interface thus permitting graphics to be drawn or players to be warped around.&lt;br /&gt;
&lt;br /&gt;
==External links==&lt;br /&gt;
*[http://ss-discretion.sf.net Main Discretion Website]&lt;br /&gt;
&lt;br /&gt;
[[Category: Clients]]&lt;br /&gt;
[[Category: Discretion]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=SubSpace&amp;diff=5960</id>
		<title>SubSpace</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=SubSpace&amp;diff=5960"/>
				<updated>2008-06-01T19:12:47Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: fucking spammer, ban that guy&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:SS_screen.png|thumb|VIE SubSpace]] SubSpace is a massively multiplayer online game of death. Specifically, it is a top-down shooter much like Asteroids, in which a player chooses between 8 [[Ships]] to fly around and shoot other players with. Over time, other game types were developed for SubSpace such as Rabbit, [[Flag|Flagging]], [[Soccer]], Speed, [[King of the Hill]], and more.&lt;br /&gt;
&lt;br /&gt;
Currently, SubSpace is run by its playerbase and distributed as a player-made client, [[Continuum]]. Also, some servers are running a player-made and Open Source server software, [[ASSS]].&lt;br /&gt;
&lt;br /&gt;
Some SubSpace dates can be found in [http://wiki.aswz.com/index.php/SubSpace%20History here].&lt;br /&gt;
&lt;br /&gt;
===History===&lt;br /&gt;
&lt;br /&gt;
[[SubSpace]] began as a massively multiplayer (before that term existed) combat game dubbed '[[Sniper]]' in 1995 (later reincarnated as [http://infantry.station.sony.com/en/main.jsp Infantry]) but was quickly renamed and re-themed; it was made by Virgin Interactive Entertainment (VIE) and was one of the earliest action multiplayer online games, possibly the first semi-successful one.&lt;br /&gt;
&lt;br /&gt;
For two years the game was in open beta and several [[zone]]s were hosted by the VIE servers. The problems started when the game went retail. The servers were still free, but you had to buy the game CD to play on them. The game wasn't advertised well (very small marketing budget) and in spite of a severely addicted, albeit small, player community VIE pulled out in 1997 and a year later turned their servers off with little more than a shrug.&lt;br /&gt;
&lt;br /&gt;
The server software was included with the CD due to the foresight of one of the main programmers, so user-made and hosted [[zone]]s continued to be made, but without VIE there was no central control or client code updates and cheating was rampant. In 1998, a West European company based in [http://en.wikipedia.org/wiki/Finland Finland] had purchased distribution rights just before VIE pulled the plug and their servers were initially used as a crutch while the American community regrouped. Slowly the community came together as strong servers were set up on the east and west coast of the US. The cheating was still choking the game to death, but a loyal legion of volunteers kept the torches lit while a handful of programmers began a new project in secret.&lt;br /&gt;
&lt;br /&gt;
In 2001 these programmers unveiled a brand new client for [[SubSpace]] that had been reverse-engineered from the ground up to replace the aging VIE client. This new client was programmed by [[Mr Ekted]] and [[PriitK]] (aka Priit Kasesalu, one of the creators of [http://kazaa.com Kazaa]). It was called [[Continuum]] and allowed the community to arrest cheating and continue the development of the game.&lt;br /&gt;
&lt;br /&gt;
Although now roughly nine years old, [[SubSpace]] is as popular and addicting as it's ever been. Some of the old VIE [[zone]]s are still there, now known as [[SVS]] zones, and many more new kinds of different [[zone]]s and settings have emerged. The recent updates to [[Continuum]] as well as extensive [[bot]] &amp;amp; scripting development throughout individual zones has allowed the entire community to constantly develop and evolve the gameplay and graphics.&lt;br /&gt;
&lt;br /&gt;
For a little taste of nostalgia for vets and a glimpse into history for new players, there is [http://subspace.legendzones.com/history/vie/ a mirror of the official VIE website] from 1997.&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
*[http://www.subspacehq.com SubspaceHQ.com]&lt;br /&gt;
*[http://beginners.subspace.net Subspace.net]&lt;br /&gt;
*[http://www.ssdownloads.com SSDownloads]&lt;br /&gt;
*[http://www.ssforum.net SSForum.net]&lt;br /&gt;
[[Category: Clients]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=MERVBot_Tutorial&amp;diff=5940</id>
		<title>MERVBot Tutorial</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=MERVBot_Tutorial&amp;diff=5940"/>
				<updated>2008-04-26T00:04:50Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: /* Setting up a MERVBot (plugin) */ fixed link to mervbot site&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is based on the ever-popular MERVBot Tutorial by Underlord. It has since been updated to reflect new changes with MervBot. To see examples of how to use this instruction, see [[MERVBot Example Code]].&lt;br /&gt;
&lt;br /&gt;
This tutorial also assumes that you have a basic knowledge of C++. If you don't, check out cplusplus.com's great [http://www.cplusplus.com/doc documentation].&lt;br /&gt;
&lt;br /&gt;
==Setting up a MERVBot (plugin)==&lt;br /&gt;
&lt;br /&gt;
[http://mervbot.com MERVBot download site]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Obtaining MERVBot===&lt;br /&gt;
&lt;br /&gt;
* Download the [http://mervbot.com/files/MERVBot.rar latest build].&lt;br /&gt;
* Unrar MERVBot.rar into a new folder. (example c:\program files\continuum\mervbot)&lt;br /&gt;
* Unzip src.zip into &amp;amp;quot;src&amp;amp;quot; subfolder of that new folder (example c:\program files\continuum\mervbot\src)&lt;br /&gt;
&lt;br /&gt;
===Preparing to write a plugin===&lt;br /&gt;
&lt;br /&gt;
''Note:'' if you only want to execute someone's premade plugin (.dll), skip to [[MERVBot Tutorial#Run your bot dll|step 4]], otherwise continue to learn how to make your own bot&lt;br /&gt;
&lt;br /&gt;
Download [http://catid.sscontinuum.com/files/Tutorial.rar DLL-plugin Tutorial] and unzip Tutorial.zip (containing spawn.h, spawn.cpp, and command.cpp) into a &amp;amp;quot;tutorial&amp;amp;quot; subfolder of that new folder. (example c:\program files\continuum\mervbot\src\tutorial).&lt;br /&gt;
&lt;br /&gt;
''File descriptions:''&lt;br /&gt;
* spawn.h = declare/initialize globals&lt;br /&gt;
* command.cpp = code for commands coming into bot (ie /!help, /!play, etc)&lt;br /&gt;
* spawn.cpp = code that interacts with bot spawns&lt;br /&gt;
&lt;br /&gt;
===Microsoft Visual c++===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Start Visual Studios 6.0.&lt;br /&gt;
&amp;lt;li&amp;gt;Click the Drop Down Menu labeled &amp;amp;quot;File&amp;amp;quot; at the top left of your screen.&lt;br /&gt;
&amp;lt;li&amp;gt;Click &amp;amp;quot;New&amp;amp;quot;.&lt;br /&gt;
&amp;lt;li&amp;gt;On the next screen that comes up, choose from the Project tab, then Win32 Dynamic-Link Library&lt;br /&gt;
&amp;lt;li&amp;gt;Select the &amp;amp;quot;/src&amp;amp;quot; folder as the base folder (example c:\program files\continuum\mervbot\src)&lt;br /&gt;
&amp;lt;li&amp;gt;Name your project &amp;amp;quot;mybot&amp;amp;quot;. This will make a &amp;amp;quot;mybot&amp;amp;quot; subfolder in your &amp;amp;quot;src&amp;amp;quot; folder. Click OK. (example creates c:\program files\continuum\mervbot\src\mybot)&lt;br /&gt;
&amp;lt;li&amp;gt;Choose to create an &amp;amp;quot;Empty DLL project&amp;amp;quot;.&lt;br /&gt;
&amp;lt;li&amp;gt;Click &amp;amp;quot;Finish&amp;amp;quot;.&lt;br /&gt;
&amp;lt;li&amp;gt;Click the Drop Down Menu labbled &amp;amp;quot;Project&amp;amp;quot;.&lt;br /&gt;
&amp;lt;li&amp;gt;Click &amp;amp;quot;Add To Project Files&amp;amp;quot;&lt;br /&gt;
&amp;lt;li&amp;gt;Copy only spawn.h, spawn.cpp, and command.cpp from the &amp;amp;quot;tutorial&amp;amp;quot; folder into the this new folder. (example from c:\program files\continuum\mervbot\src\tutorial to c:\program files\continuum\mervbot\src\mybot)&lt;br /&gt;
&amp;lt;li&amp;gt;Click the Drop Down Menu labelled &amp;amp;quot;Build&amp;amp;quot;.&lt;br /&gt;
&amp;lt;li&amp;gt;Click &amp;amp;quot;Build (dll name)&amp;amp;quot; - where (dll name) is &amp;amp;quot;mybot&amp;amp;quot;&lt;br /&gt;
&amp;lt;li&amp;gt;Go into your &amp;amp;quot;mybot&amp;amp;quot; folder and look for a folder named &amp;amp;quot;Debug&amp;amp;quot;&lt;br /&gt;
(example c:\program files\continuum\mervbot\src\mybot\debug)&lt;br /&gt;
&amp;lt;li&amp;gt;Your new DLL will be in that folder. (example mybot.dll)&lt;br /&gt;
&amp;lt;li&amp;gt;Copy mybot.dll to your base folder that has mervbot.exe in it (example c:\program files\continuum\mervbot)&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Run your bot dll===&lt;br /&gt;
&lt;br /&gt;
To run your bot you need your DLL (mybot.dll), Commands.txt, MERVBot.exe, MERVBot.ini, Operators.txt, Spawns.txt, and zlib.dll all in one folder (example c:\program files\continuum\mervbot).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Edit spawns.txt. '''Read every word of spawns.txt to find out what needs to go in there.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
''Example:''&lt;br /&gt;
&amp;lt;pre&amp;gt;2v2-Bot-League : botpw : 2v2a : 2v2league : staffpw&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''Note:'' The bot will attempt to create the name if it doesn't exist already.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Edit MERVBot.ini&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;[Login]&lt;br /&gt;
Zone=216.33.98.254:21000	// your zone IP:PORT available from zone.dat in Continuum dir&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Edit operators.txt. '''Read every word of operators.txt to find out what needs to go in there.'''&amp;lt;br /&amp;gt;&lt;br /&gt;
        &lt;br /&gt;
''Example:''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
4:my_name:&lt;br /&gt;
4:another_sysop:&lt;br /&gt;
3:other_person:&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;Make sure the bot is on vip.txt or has smod+ access, then run MERVBot.exe.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;You can now edit your plugin code by opening &amp;amp;quot;mybot.dsw&amp;amp;quot; (example c:\program files\continuum\mervbot\src\mybot\mybot.dsw) in Microsoft Visual C++. Edit the spawn.h, spawn.cpp, and command.cpp to create your plugin, then build, copy your updated DLL to your MERVBot.exe folder and then execute the bot. Use the tutorial to get ideas on how to implement certain types of features into the bot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Player Commands - (command.cpp)==&lt;br /&gt;
&lt;br /&gt;
This section describes how to implement player commands into your plugin. Commands are sent to the botInfo::gotCommand function in command.cpp.&lt;br /&gt;
&lt;br /&gt;
Example (makes bot reply to !test with &amp;quot;hi&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void botInfo::gotCommand(Player *p, Command *c) {&lt;br /&gt;
	switch (p-&amp;gt;access)&lt;br /&gt;
	{&lt;br /&gt;
        case OP_Moderator:&lt;br /&gt;
                {&lt;br /&gt;
                     // handle moderator-operator commands here.&lt;br /&gt;
                }&lt;br /&gt;
	case OP_Player: //appropriate staff rank here.&lt;br /&gt;
		{&lt;br /&gt;
			if (c-&amp;gt;check(&amp;quot;test&amp;quot;)) //replace &amp;quot;test&amp;quot; with whatever command you want&lt;br /&gt;
			{&lt;br /&gt;
				//put your command code here&lt;br /&gt;
				sendPrivate(p,&amp;quot;hi&amp;quot;); //example&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===How to have commands with numerical parameters===&lt;br /&gt;
Example (!test #):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	if (c-&amp;gt;check(&amp;quot;test&amp;quot;)) { // reads in test #, default to 1 if invalid number input&lt;br /&gt;
		int temp = 1;&lt;br /&gt;
&lt;br /&gt;
		if (isNumeric(c-&amp;gt;final))&lt;br /&gt;
			temp = atoi(c-&amp;gt;final);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===How to have player name as input===&lt;br /&gt;
Example (!rank player):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	if (c-&amp;gt;check(&amp;quot;rank&amp;quot;))&lt;br /&gt;
	{&lt;br /&gt;
		String player_name = c-&amp;gt;final;&lt;br /&gt;
&lt;br /&gt;
		if (player_name.IsEmpty()) // default name to self if invalid name&lt;br /&gt;
			player_name = p-&amp;gt;name;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===How to have multi-parameter input===&lt;br /&gt;
&lt;br /&gt;
Use the CRT function sscanf() to scan the string for the values.&lt;br /&gt;
&lt;br /&gt;
Example (!squads squadA vs squadB ''or'' !squads teamA:squadA:teamB:squadB):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
else if (c-&amp;gt;check(&amp;quot;squads&amp;quot;))&lt;br /&gt;
{&lt;br /&gt;
	char squadA[20], squadB[20];&lt;br /&gt;
	int teamA, teamB;&lt;br /&gt;
&lt;br /&gt;
	strncpy(squadA, &amp;quot;&amp;quot;, 20);&lt;br /&gt;
	strncpy(squadB, &amp;quot;&amp;quot;, 20);&lt;br /&gt;
&lt;br /&gt;
	int n_found;&lt;br /&gt;
&lt;br /&gt;
	//Note: %[A-Za-z ] is equivalent to %s, but allows an internal space.&lt;br /&gt;
&lt;br /&gt;
	//scan the string for the two squads separated by &amp;quot; vs &amp;quot;&lt;br /&gt;
	n_found = sscanf(c-&amp;gt;final, &amp;quot;%[A-Za-z ] vs %[A-Za-z ]&amp;quot;, squadA, squadB);&lt;br /&gt;
&lt;br /&gt;
	//if that fails, scan the string for freqA:squadA:freqB:squadB&lt;br /&gt;
	if (n_found &amp;lt; 2)&lt;br /&gt;
		sscanf(c-&amp;gt;final, &amp;quot;%d:%[A-Za-z ]:%d:%[A-Za-z ]&amp;quot;, &amp;amp;teamA, squadA, &amp;amp;teamB, squadB);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Help Menu===&lt;br /&gt;
When a player sends !help to the bot, MERVBot calls botInfo::gotHelp() in each plugin loaded.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void botInfo::gotHelp(Player *p, Command *c)&lt;br /&gt;
{&lt;br /&gt;
	if (!*c-&amp;gt;final)&lt;br /&gt;
	{&lt;br /&gt;
	sendPrivate(p, &amp;quot;4v4 Bot General Commands:&amp;quot;);&lt;br /&gt;
	sendPrivate(p, &amp;quot;------------------------&amp;quot;);&lt;br /&gt;
	sendPrivate(p, &amp;quot;!caps - get captain names&amp;quot;);&lt;br /&gt;
	sendPrivate(p, &amp;quot;!roster &amp;lt;squad&amp;gt; - get roster of a squad&amp;quot;);&lt;br /&gt;
	sendPrivate(p, &amp;quot;!schedule- get current schedule&amp;quot;);&lt;br /&gt;
	sendPrivate(p, &amp;quot;!score - get current score&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Event Calls==&lt;br /&gt;
&lt;br /&gt;
MERVBot is event based, so when making a bot you need to decide what will happen at certain events. Normal plugins need to consider what happens when bot enters arena, player enters arena, player leaves arena, player events like kill, shipchange, teamchange, spec, move then any other relevant events to your bot. Just worry about events that are relevant to the tasks your bot is doing.&lt;br /&gt;
&lt;br /&gt;
MERVBot sends events to botInfo::gotEvent() in spawn.cpp. Each supported event is already present and categorized in gotEvent(), along with the paramters that MERVBot sends with the event. When a plugin wants the bot to do something, it sends tell(event) to the bot.&lt;br /&gt;
&lt;br /&gt;
See dllcore.h for a list of current events and their descriptions. Dllcore.h also contains functions (like makeFollowing) to make events to send back to the bot via tell().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;tell(makeFollowing(false));&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==The Messaging System==&lt;br /&gt;
&lt;br /&gt;
Private message - void sendPrivate(Player *player, char *msg);&lt;br /&gt;
&lt;br /&gt;
''Examples:''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sendPrivate(p,&amp;quot;hi&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
String s=&amp;quot;test&amp;quot;;&lt;br /&gt;
sendPrivate(p,s);&lt;br /&gt;
&lt;br /&gt;
String s=&amp;quot;test&amp;quot;;&lt;br /&gt;
s += &amp;quot;ing&amp;quot;;&lt;br /&gt;
sendPrivate(p,s);&lt;br /&gt;
&lt;br /&gt;
char captain1[20];&lt;br /&gt;
char captain2[20];&lt;br /&gt;
strncpy(captain1,&amp;quot;&amp;quot;,20);&lt;br /&gt;
strncpy(captain2,&amp;quot;&amp;quot;,20);&lt;br /&gt;
sendPrivate(p,(String) captain1 + &amp;quot; and &amp;quot; + (String) captain2 + &amp;quot; are the captains.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Team message - void sendTeamPrivate(Uint16 team, char *msg);&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Examples: &amp;lt;br /&amp;gt;&lt;br /&gt;
a) sendTeamPrivate(8025,&amp;amp;quot;hi spec freq&amp;amp;quot;);&amp;lt;br /&amp;gt;&lt;br /&gt;
b) Uint16 test=0; sendTeamPrivate(test,&amp;amp;quot;hi freq 0&amp;amp;quot;);&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Public message - void sendPublic(char *msg);&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Example: sendPublic(&amp;amp;quot;*arena &amp;amp;quot; + (String) p-&amp;amp;gt;name + &amp;amp;quot; is now a captain&amp;amp;quot;);&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
Chat channel message - void sendChannel(char *msg);&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Example: sendChannel(&amp;amp;quot;hi chat channel&amp;amp;quot;);&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
Remote private message - void sendRemotePrivate(char *name, char *msg);&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Example: sendRemotePrivate(&amp;amp;quot;Player01&amp;amp;quot;, &amp;amp;quot;hi&amp;amp;quot;);&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: to have bot print several lines of text fast it needs sysop in the&lt;br /&gt;
arena (sysop in arena bot first spawns to also) otherwise it'll print slow to avoid being&lt;br /&gt;
kicked for spam&lt;br /&gt;
&lt;br /&gt;
===Output of data in messages===&lt;br /&gt;
&amp;lt;p&amp;gt;An example of using normal strings to output data/messages.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 // does *arena X pilots left in game&lt;br /&gt;
 // NOTE: variable temp needs to be defined with some value&lt;br /&gt;
&lt;br /&gt;
 String s = &amp;quot;*arena &amp;quot;;&lt;br /&gt;
       s += temp;&lt;br /&gt;
       s += &amp;quot; pilots left in the game.&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
 sendPublic(s);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Or,&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 //NOTE: this can be considered inefficient.&lt;br /&gt;
&lt;br /&gt;
 sendPublic(&amp;quot;*arena &amp;quot; + (String)temp + &amp;quot; pilots left in the game&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;An example using sprintf to align/space data, where output data will be in this approximate format.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// output data will be in this approximate format (not lined up perfectly because of html)&lt;br /&gt;
// --------------------------------------------------------------------------------------&lt;br /&gt;
// Squad: squadname       PTS     FPTS    K    D  DMG DEALT TAKEN   F  FK    FLT&lt;br /&gt;
// --------------------------------------------------------------------------------------&lt;br /&gt;
// PlayerA              10000      500  116  101       9999 99999  10 150 980:55&lt;br /&gt;
// PlayerB                500      200    7    5       9999 99999   5   3   0:04&lt;br /&gt;
&lt;br /&gt;
char str[255];&lt;br /&gt;
sendPublic(&amp;quot;*arena--------------------------------------------------------------------------------&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
sprintf(str, &amp;quot;*arena Squad: %-20s   PTS     FPTS   K   D  DMG DEALT  TAKEN  F  FK  FLT&amp;quot;,&lt;br /&gt;
         freqs[freq].freqname&lt;br /&gt;
        );&lt;br /&gt;
&lt;br /&gt;
sendPublic(str);&lt;br /&gt;
&lt;br /&gt;
sendPublic(&amp;quot;*arena--------------------------------------------------------------------------------&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
            // assuming existing freqs struct with data&lt;br /&gt;
            for (pilot=freqs[freq].playercount-1; pilot&amp;gt;=0; pilot--)&lt;br /&gt;
            {&lt;br /&gt;
                // on freq squad so print stats&lt;br /&gt;
                char outString[255];&lt;br /&gt;
&lt;br /&gt;
                sprintf(outString, &amp;quot;*arena %-20s %12d %8d %3d %3d %10d %6d %2d %3d %3d:%02d&amp;quot;,&lt;br /&gt;
                       freqs[freq].pilots[pilot].name,&lt;br /&gt;
                       freqs[freq].pilots[pilot].points,&lt;br /&gt;
                       freqs[freq].pilots[pilot].flagpoints,&lt;br /&gt;
                       freqs[freq].pilots[pilot].kills,&lt;br /&gt;
                       freqs[freq].pilots[pilot].deaths,&lt;br /&gt;
                       freqs[freq].pilots[pilot].dmgdealt,&lt;br /&gt;
                       freqs[freq].pilots[pilot].dmgtaken,&lt;br /&gt;
                       freqs[freq].pilots[pilot].flags,&lt;br /&gt;
                       freqs[freq].pilots[pilot].flagkills,&lt;br /&gt;
                       freqs[freq].pilots[pilot].flagtime /60,&lt;br /&gt;
                       freqs[freq].pilots[pilot].flagtime %60&lt;br /&gt;
                       );&lt;br /&gt;
                &lt;br /&gt;
                sendPublic(outString);&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // Notes: sprintf format = sprintf(output char string, spacing, variables)&lt;br /&gt;
            // Notes: s = chars, d = integer, - = left align, right align default&lt;br /&gt;
            // Notes: doing %02d = put 0 in front if not 2 digits, %3d:%02d makes 0:04 format&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Time==&lt;br /&gt;
&lt;br /&gt;
Each time MERVBot sends an EVENT_Tick to a plugin (once a second), the default handler code decrements each value in an array of countdowns. You can modify the number of countdowns and add code to occur at a specific value for one of the countdowns.&lt;br /&gt;
&lt;br /&gt;
Setup number of timers and initialize in spawn.h:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class botInfo&lt;br /&gt;
{&lt;br /&gt;
	#define COUNTDOWNS 10 		// how many countdowns you want&lt;br /&gt;
	int countdown[COUNTDOWNS];	// this gives you 10 timers&lt;br /&gt;
&lt;br /&gt;
// unrelated code&lt;br /&gt;
 &lt;br /&gt;
	public:&lt;br /&gt;
	botInfo(CALL_HANDLE given)&lt;br /&gt;
	{&lt;br /&gt;
	countdown[0] = 0;&lt;br /&gt;
	countdown[1] = 60; // 60 seconds&lt;br /&gt;
	//&lt;br /&gt;
	// initialize values&lt;br /&gt;
	//&lt;br /&gt;
	countdown[9] = 5*60; // 5 minutes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Using timer functions in spawn.cpp:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
case EVENT_Tick:&lt;br /&gt;
{&lt;br /&gt;
	for (int i = 0; i &amp;lt; COUNTDOWNS; ++i) //cycles through each countdown you have&lt;br /&gt;
		--countdown[i]; //note that countdowns will continue decrementing past 0.&lt;br /&gt;
&lt;br /&gt;
	if (countdown[1] == 2) // when timer #1 hits two seconds&lt;br /&gt;
	{&lt;br /&gt;
	// do stuff here when timer #1 hits 2 seconds&lt;br /&gt;
	// example: sendPublic(&amp;quot;two seconds left, setting timer to 1 minute&amp;quot;);&lt;br /&gt;
	// example: countdown[1] = 60; // change timer #1 value&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can then have events (such as EVENT_PlayerDeath) change the value of a countdown to make the bot do something a set time after an event occurs.&lt;br /&gt;
&lt;br /&gt;
=== Tracking time not using countdown[n] ===&lt;br /&gt;
&lt;br /&gt;
This is a solution to a common problem of determining the amount of time it takes for something to occur. Using basic math, we record a start-time B, and an end-time E, both in the unit of seconds, we calculate the time elapsed by E-B.&lt;br /&gt;
&lt;br /&gt;
Lucky for us, Windows provides a function called GetTickCount() that is a measurement of time (milliseconds) that we can use for such cases.&lt;br /&gt;
&lt;br /&gt;
So:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	int begin = GetTickCount();&lt;br /&gt;
&lt;br /&gt;
	// do some code here.&lt;br /&gt;
&lt;br /&gt;
	int end = GetTickCount();&lt;br /&gt;
  &lt;br /&gt;
	int delta = (end - begin) / 1000;  // elapsed time converted to seconds from milliseconds&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Obtaining the current time ===&lt;br /&gt;
&lt;br /&gt;
''Requirements:'' Include &amp;lt;time.h&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 char u[100];&lt;br /&gt;
 time_t t=time(NULL);&lt;br /&gt;
 tm *tmp = localtime(&amp;amp;t);&lt;br /&gt;
 strftime(u,99,&amp;quot;%c&amp;quot;,tmp);&lt;br /&gt;
 sendPublic(&amp;quot;Current date and time: &amp;quot; + u);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Writing Functions==&lt;br /&gt;
&amp;lt;!-- begin of functions. --&amp;gt;&lt;br /&gt;
For this example, we will take the function called closeto, which determines&lt;br /&gt;
if a player exists in an specific radius around a point. Now to apply this function to a MervBot plugin, you need to write it into the spawn.cpp - at the top of the file in the //////// DLL &amp;amp;quot;import&amp;amp;quot; //////// setion, as below:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//////// DLL &amp;quot;import&amp;quot; ////////&lt;br /&gt;
&lt;br /&gt;
bool closeto(Player *p, int x, int y, int tolerance) &lt;br /&gt;
{&lt;br /&gt;
	// Requires the function abs() to be declared elsewhere.&lt;br /&gt;
	// Return if player p is in area of square with center x, y&lt;br /&gt;
	//   and radius = tolerance&lt;br /&gt;
	return (abs((p-&amp;gt;tile.x) - x) - tolerance) &amp;amp;&amp;amp; (abs((p-&amp;gt;tile.y) - y) - tolerance);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want your function to have access to the data from spawn.h botInfo class, you make the function apart of it. To do this, we add the '''botInfo::''' infront of the function name, in spawn.cpp.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//////// DLL &amp;quot;import&amp;quot; ////////&lt;br /&gt;
&lt;br /&gt;
bool botInfo::closeto(Player *p, int x, int y, int tolerance) &lt;br /&gt;
    {&lt;br /&gt;
	 ...&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In '''spawn.h''', add your method's prototype without botInfo::, it will look&lt;br /&gt;
like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//...&lt;br /&gt;
botInfo(CALL_HANDLE given)&lt;br /&gt;
 {&lt;br /&gt;
//  ...&lt;br /&gt;
 } &lt;br /&gt;
  bool closeto(Player *p, int x, int y, int tolerance); // Your function prototype.&lt;br /&gt;
&lt;br /&gt;
  void clear_objects(); //provided by Catid, and already exists.&lt;br /&gt;
  void object_target(Player *p); //provided by Catid, and already exists.&lt;br /&gt;
//  ...&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you're not familiar with prototypes, notice it is similar to that in your spawn.cpp, but without the botInfo::, and a trailing ;.&lt;br /&gt;
&lt;br /&gt;
===Function notes===&lt;br /&gt;
&lt;br /&gt;
Remember that you can pass variables [http://www.cplusplus.com/doc/tutorial/tut2-3.html by reference]. If variables are passed by reference, any changes a function makes to the variables will remain after the function returns.&lt;br /&gt;
&lt;br /&gt;
From time to time you will need to pass an array to a function. An example illustrating this is:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	int freqs[5]; // declare our example data.&lt;br /&gt;
&lt;br /&gt;
	// call function - notice freqs and not freqs[5] or freqs[].&lt;br /&gt;
	my_function(freqs); //You're not passing the array itself, just a pointer to the array.&lt;br /&gt;
&lt;br /&gt;
	// function - notice freqs[] and not freqs[5] or freqs&lt;br /&gt;
	void my_function(int freqs[]) {} //You're specifying that the freqs parameter is an array&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Cycling through players==&lt;br /&gt;
&lt;br /&gt;
MERVBot stores player-related data in a linked list. A linked list is a datatype that stores its data in a series of structures linked to each other, hence the name.&lt;br /&gt;
&lt;br /&gt;
To search through the players in the arena, just start at the first link, then continue through all the following links until you reach the end:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
_listnode &amp;lt;Player&amp;gt; *parse = playerlist-&amp;gt;head;	//set to first link of the player linked list&lt;br /&gt;
&lt;br /&gt;
while (parse)	//parse will be NULL when we reach the last link&lt;br /&gt;
{&lt;br /&gt;
	Player *p = parse-&amp;gt;item;	//item is the actual data stored in the link&lt;br /&gt;
&lt;br /&gt;
	// do functionality here&lt;br /&gt;
	// Example 1: sendPrivate(p,&amp;quot;*watchdamage&amp;quot;); // turns on all pilot's watchdamage&lt;br /&gt;
	// Example 2: if (p-&amp;gt;safety != 0) sendPrivate(p,&amp;quot;*spec&amp;quot;); // spec all pilots in safe zone&lt;br /&gt;
&lt;br /&gt;
	parse = parse-&amp;gt;next;	//set parse to the next link&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, assuming our bot has smod+ privilages, the following code will set all non-spectator players to a specific ship. First begin by adding the following function prototype to the spawn.h in the botInfo class:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 void handleCmdSetShip(enum Ship_Types ship);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In spawn.cpp add:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void botInfo::handleCmdSetShip(enum Ship_Types ship)&lt;br /&gt;
{&lt;br /&gt;
	//Note that the parameter ship is of the Ship_Types enum,&lt;br /&gt;
	//so its value is hopefully restricted to the proper types.&lt;br /&gt;
&lt;br /&gt;
	_listnode &amp;lt;Player&amp;gt; *parse = playerlist-&amp;gt;head;&lt;br /&gt;
	while (parse)&lt;br /&gt;
	{&lt;br /&gt;
		Player *p = parse-&amp;gt;item;&lt;br /&gt;
&lt;br /&gt;
		if ( p-&amp;gt;ship != ship &amp;amp;&amp;amp; p-&amp;gt;ship != SHIP_Spectator )&lt;br /&gt;
				sendPrivate(p, &amp;quot;*setship &amp;quot; + (String)ship);&lt;br /&gt;
&lt;br /&gt;
		parse = parse-&amp;gt;next;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To use, just call the function with the appropriate Ship_Type from the enum in clientprot.h:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 handleCmdSetShip(SHIP_Warbird);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Random numbers==&lt;br /&gt;
&lt;br /&gt;
===Generating a random number===&lt;br /&gt;
&lt;br /&gt;
To use this method, these two includes must be used:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;quot;time.h&amp;quot;    //provides time() function.&lt;br /&gt;
#include &amp;quot;stdlib.h&amp;quot;  //provides srand() and rand() functions.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    srand(time(NULL)); // seed random number generator.&lt;br /&gt;
&lt;br /&gt;
    rand(); // randomize.&lt;br /&gt;
&lt;br /&gt;
    int temp = (int) (51 * ((float)rand()/RAND_MAX));&lt;br /&gt;
       // the above line returns a random integer between 0 and 51.&lt;br /&gt;
       // Note: RAND_MAX is a global constant defined in stdlib.h&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Picking a random pilot===&lt;br /&gt;
&lt;br /&gt;
''Note:'' A required user-defined function, getInGame(), must be created for this example to work.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int temp = GetTickCount() % getInGame();  // getInGame() = how many pilots in arena&lt;br /&gt;
&lt;br /&gt;
Player *rabbit = NULL;&lt;br /&gt;
&lt;br /&gt;
_listnode &amp;lt;Player&amp;gt; *parse = playerlist-&amp;gt;head;&lt;br /&gt;
while (parse)&lt;br /&gt;
{&lt;br /&gt;
	Player *p = parse-&amp;gt;item;&lt;br /&gt;
&lt;br /&gt;
	if (p-&amp;gt;ship != SHIP_Spectator) // if player is not a spectator&lt;br /&gt;
	if ( !(--temp) ) // and if we've hit the randomly-selected pilot&lt;br /&gt;
	{&lt;br /&gt;
		rabbit = p;&lt;br /&gt;
		break;&lt;br /&gt;
	}&lt;br /&gt;
	parse = parse-&amp;gt;next;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Storing data for pilots==&lt;br /&gt;
&lt;br /&gt;
There are several ways to store data for pilots (ie tracking flagtime or kills in a period of time). Note that these methods are all purely internal to the bot, and don't effect anything beyond the plugin in any way.&lt;br /&gt;
&lt;br /&gt;
# Built-in get/setTag: Tracks data until player leaves the arena, then automatically deletes data.&lt;br /&gt;
# Modified perm get/setTag: Tracks data until bot leaves arena, then automatically deletes data. (Advantage: easier to sort by player)&lt;br /&gt;
# Custom Structs: Tracks data until plugin deletes it. (Advantage: easier to sort by freqs)&lt;br /&gt;
&lt;br /&gt;
''Note:'' 2 and 3 are similar in effect, mostly the difference is in how you are able to search through data you need to decide which method of storing data is best for each bot depending on what it does.&lt;br /&gt;
&lt;br /&gt;
===Built-in get/setTag method===&lt;br /&gt;
&lt;br /&gt;
Player tags simply tag a player with a number. Define the wanted values in '''spawn.h''' at the top:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define DMG_DEALT        0&lt;br /&gt;
#define DMG_TAKEN        1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In spawn.cpp, initialize the values on ArenaEnter and PlayerEnter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
case EVENT_ArenaEnter:&lt;br /&gt;
{&lt;br /&gt;
	// ...&lt;br /&gt;
&lt;br /&gt;
	// do for all pilots in arena when bot enters&lt;br /&gt;
	_listnode &amp;lt;Player&amp;gt; *parse = playerlist-&amp;gt;head;&lt;br /&gt;
	while (parse)&lt;br /&gt;
	{&lt;br /&gt;
	   Player *p = parse-&amp;gt;item;  // get pilot&lt;br /&gt;
&lt;br /&gt;
	   set_tag(p, DMG_DEALT, 0); // initialize to 0&lt;br /&gt;
	   set_tag(p, DMG_TAKEN, 0);&lt;br /&gt;
	   sendPrivate(p, &amp;quot;*watchdamage&amp;quot;);  // optionally turn on player *watchdamage&lt;br /&gt;
&lt;br /&gt;
	   parse = parse-&amp;gt;next;  // get next pilot&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
case EVENT_PlayerEntering:&lt;br /&gt;
{&lt;br /&gt;
//	...&lt;br /&gt;
	set_tag(p, DMG_DEALT, 0); // initialize to 0&lt;br /&gt;
	set_tag(p, DMG_TAKEN, 0);&lt;br /&gt;
	sendPrivate(p,&amp;quot;*watchdamage&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then somewhere edit the tag values:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
case EVENT_WatchDamage:&lt;br /&gt;
{&lt;br /&gt;
	// sets tag for k (shooter) to be old value plus damage currently dealt&lt;br /&gt;
&lt;br /&gt;
	int old_damage = get_tag(k, DMG_BOMB_DEALT);&lt;br /&gt;
	set_tag(k, DMG_BOMB_DEALT, old_damage + damage);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following demonstrates how to retrieve the tag values as a command in command.cpp:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (c-&amp;gt;check(&amp;quot;showstats&amp;quot;))&lt;br /&gt;
{&lt;br /&gt;
	int temp = get_tag(p, DMG_TOTAL_DEALT);&lt;br /&gt;
&lt;br /&gt;
	String s = &amp;quot;You've done &amp;quot;;&lt;br /&gt;
	s += temp;&lt;br /&gt;
	s += &amp;quot; damage so far!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	sendPrivate(p,s);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Modified permanent get/setTag method===&lt;br /&gt;
&lt;br /&gt;
This method is the same as get/setTag with some modifications to the tag code to retain them after the player leaves. Beware of using this method if bot is in an arena for long periods of time, linkedlist could get huge.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// spawn.h, add char name[20]; into struct PlayerTag&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct PlayerTag&lt;br /&gt;
{&lt;br /&gt;
	Player *p;&lt;br /&gt;
	char name[20];&lt;br /&gt;
	int index;&lt;br /&gt;
	int data;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In spawn.cpp:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	case EVENT_PlayerLeaving:&lt;br /&gt;
	{&lt;br /&gt;
	    Player *p = (Player*)event.p[0];&lt;br /&gt;
&lt;br /&gt;
	    // killTags(p);  // remove so tag not deleted on arena exit&lt;br /&gt;
&lt;br /&gt;
//	...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Locate in spawn.cpp and modify accordingly:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int botInfo::get_tag(Player *p, int index)&lt;br /&gt;
{&lt;br /&gt;
    _listnode &amp;lt;PlayerTag&amp;gt; *parse = taglist.head;&lt;br /&gt;
    PlayerTag *tag;&lt;br /&gt;
&lt;br /&gt;
    while (parse)&lt;br /&gt;
    {&lt;br /&gt;
      tag = parse-&amp;gt;item;&lt;br /&gt;
&lt;br /&gt;
      // if (tag-&amp;gt;p == p)&lt;br /&gt;
      if (strcmp(tag-&amp;gt;name,p-&amp;gt;name)==0)  // now tracking by player name, not pointer&lt;br /&gt;
      if (tag-&amp;gt;index == index)&lt;br /&gt;
        return tag-&amp;gt;data;&lt;br /&gt;
&lt;br /&gt;
      parse = parse-&amp;gt;next;&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void botInfo::set_tag(Player *p, int index, int data)&lt;br /&gt;
{&lt;br /&gt;
    _listnode &amp;lt;PlayerTag&amp;gt; *parse = taglist.head;&lt;br /&gt;
    PlayerTag *tag;&lt;br /&gt;
&lt;br /&gt;
    while (parse)&lt;br /&gt;
    {&lt;br /&gt;
      tag = parse-&amp;gt;item;&lt;br /&gt;
&lt;br /&gt;
      //if (tag-&amp;gt;p == p)&lt;br /&gt;
      if (strcmp(tag-&amp;gt;name,p-&amp;gt;name)==0) // now tracking by player name, not pointer&lt;br /&gt;
      if (tag-&amp;gt;index == index)&lt;br /&gt;
      {&lt;br /&gt;
        tag-&amp;gt;data = data;&lt;br /&gt;
        return;&lt;br /&gt;
      }&lt;br /&gt;
      parse = parse-&amp;gt;next;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    tag = new PlayerTag;&lt;br /&gt;
    // tag-&amp;gt;p = p; // not tracking by pointer anymore&lt;br /&gt;
    strncpy(tag-&amp;gt;name, p-&amp;gt;name, 20); // tracking by player name&lt;br /&gt;
    tag-&amp;gt;index = index;&lt;br /&gt;
    tag-&amp;gt;data = data;&lt;br /&gt;
    taglist.append(tag);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using structs===&lt;br /&gt;
&lt;br /&gt;
In '''spawn.h''':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class botInfo&lt;br /&gt;
{&lt;br /&gt;
	struct freqdata &lt;br /&gt;
	{&lt;br /&gt;
		int kills, deaths;&lt;br /&gt;
	};&lt;br /&gt;
// ...&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To make use of this structure, implement accordingly:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	freqdata freqs[100]; // 100 of those structs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Access the data in spawn.cpp using&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
freqs[56].kills = 1;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See CPlusPlus.com's [http://www.cplusplus.com/doc/tutorial/tut3-5.html Structures] tutorial for a more comprehensive guide. Note that, as shown on the bottom of the page, you can have structures within structures. Thus, for example, you could have a structure for each freq with a structure for each player nested within them.&lt;br /&gt;
&lt;br /&gt;
==Input/Output to files==&lt;br /&gt;
&lt;br /&gt;
For reading and/or writing to files with C++ you must have the required include statement as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;fstream&amp;gt;&lt;br /&gt;
using namespace std;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===File stream input===&lt;br /&gt;
The following example will show you how to read a file, duel.ini, line by line.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;quot;stdlib.h&amp;quot; // for atoi()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  ifstream file(&amp;quot;duel.ini&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  if (!file.good()) // if there was an error opening the file&lt;br /&gt;
    sendPublic(&amp;quot;*arena Error opening file for reading&amp;quot;); // or add your own error handler&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    char line[256];&lt;br /&gt;
&lt;br /&gt;
    // read in MaxBoxes=X&lt;br /&gt;
    while (file.getline(line, 256))&lt;br /&gt;
    {&lt;br /&gt;
     &lt;br /&gt;
      if (CMPSTART(&amp;quot;MaxBoxes=&amp;quot;, line)) //Does the line begin with MaxBoxes= ?&lt;br /&gt;
      {&lt;br /&gt;
        MAX_BOXES = atoi(&amp;amp;(line[9]));  //If so, read the value into an integer, using atio.&lt;br /&gt;
        break;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    file.close();&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===File stream output===&lt;br /&gt;
The following code example will demonstrate how to append to a file, duelleaguestat.inc.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 ofstream file(&amp;quot;duelleaguestat.inc&amp;quot;, ios::app);   // app = put all data at end of file&lt;br /&gt;
&lt;br /&gt;
 if (!file.good()) // if there was an error opening the file&lt;br /&gt;
   sendPublic(&amp;quot;*arena Error opening file.&amp;quot;);&lt;br /&gt;
 else&lt;br /&gt;
 {&lt;br /&gt;
   file &amp;lt;&amp;lt; squad1&amp;lt;&amp;lt; endl;  // squad1 = char[20]&lt;br /&gt;
   file &amp;lt;&amp;lt; &amp;quot; vs &amp;quot;&amp;lt;&amp;lt; endl;&lt;br /&gt;
   file &amp;lt;&amp;lt; squad2&amp;lt;&amp;lt; endl;  // squad2 = char[20]&lt;br /&gt;
   file.close();&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, you are able to write an output of a String to a file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 // key is converting String to (char*) to file write&lt;br /&gt;
 String str = freqs[freq].slotname[slot];&lt;br /&gt;
 str += &amp;quot;, Repels: &amp;quot; + (String)(int) t-&amp;gt;repel;&lt;br /&gt;
 file &amp;lt;&amp;lt; endl;&lt;br /&gt;
 file &amp;lt;&amp;lt; (char*) str;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Input with GetPrivateProfileString===&lt;br /&gt;
&lt;br /&gt;
GetPrivateProfileString(), a function provided by Windows for reading INI files, will automatically find an INI key (like &amp;quot;MaxBoxes=&amp;quot;) in a file for you. See the [http://msdn.microsoft.com/library MSDN Library] for help on this function. This next example will show how to read input using GetPrivateProfileString() based on the rampage plugin.&lt;br /&gt;
&lt;br /&gt;
The file format for rampage.ini is like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 7=is on a killing spree! (6:0)&lt;br /&gt;
 10=is opening a can of booya! (9:0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In '''rampageini.cpp''':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;quot;rampageini.h&amp;quot;&lt;br /&gt;
#define WIN32_LEAN_AND_MEAN&lt;br /&gt;
#include &amp;lt;windows.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUM_RANKS 10&lt;br /&gt;
#define BUFFER_LEN 256&lt;br /&gt;
&lt;br /&gt;
struct RampageSettings&lt;br /&gt;
{&lt;br /&gt;
	char quotes[NUM_RANKS][BUFFER_LEN];&lt;br /&gt;
};&lt;br /&gt;
 &lt;br /&gt;
void LoadSettings(RampageSettings &amp;amp;setts);&lt;br /&gt;
&lt;br /&gt;
static char path[BUFFER_LEN];&lt;br /&gt;
&lt;br /&gt;
char *rank_type[NUM_RANKS] = { &amp;quot;7&amp;quot;, &amp;quot;10&amp;quot; };&lt;br /&gt;
&lt;br /&gt;
void LoadSettings(RampageSettings &amp;amp;setts)&lt;br /&gt;
{&lt;br /&gt;
	GetCurrentDirectory(BUFFER_LEN - 64, path);&lt;br /&gt;
	strcat(path, &amp;quot;\rampage.ini&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	for (int i = 0; i &amp;lt; NUM_RANKS; ++i)&lt;br /&gt;
	{&lt;br /&gt;
		GetPrivateProfileString(&amp;quot;Comments&amp;quot;, rank_type[i], &amp;quot;-ERROR-&amp;quot;,&lt;br /&gt;
					setts.quotes[i], BUFFER_LEN, path);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Player data==&lt;br /&gt;
&lt;br /&gt;
As stated earlier in the tutorial, MervBot stores useful player data internally as Player objects, see player.h for implementation details.&lt;br /&gt;
&lt;br /&gt;
* p-&amp;gt;name = player name stored as char[20] (''Note:'' SubSpace protocol allows for usernames to be 19+ in length, do not rely on this for player-name comparisions.)&lt;br /&gt;
* p-&amp;gt;squad = player squad stored as char[20]&lt;br /&gt;
* p-&amp;gt;ship = ship (0-9) enumerated as SHIP_Warbird, SHIP_Spectator, etc..&lt;br /&gt;
* p-&amp;gt;safety = whether ship is in safety zone (boolean)&lt;br /&gt;
* p-&amp;gt;bounty = player bounty&lt;br /&gt;
* p-&amp;gt;energy = player energy (have bot with *energy on to get accurate readings)&lt;br /&gt;
* p-&amp;gt;flagCount = how many flags player is holding&lt;br /&gt;
* p-&amp;gt;team = player frequency&lt;br /&gt;
* p-&amp;gt;(burst, repel, thor, brick, decoy, rocket, portal) = how many items of that type player has&lt;br /&gt;
* p-&amp;gt;(stealth, cloak, xradar, awarp, ufo, flash, safety, shields, supers) = if player has that item on (boolean)&lt;br /&gt;
* p-&amp;gt;score.killPoints = player kill points&lt;br /&gt;
* p-&amp;gt;score.flagPoints = player flag points&lt;br /&gt;
* p-&amp;gt;score.wins = player kills from f2&lt;br /&gt;
* p-&amp;gt;score.losses = player deaths from f2&lt;br /&gt;
&lt;br /&gt;
Just access the respective member of the Player class to check the player's property.&lt;br /&gt;
&lt;br /&gt;
For example, in spawn.cpp, to check whether a player is in a safety zone:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
EVENT_PlayerMove:&lt;br /&gt;
{&lt;br /&gt;
   Player *p = (Player*)event.p[0];&lt;br /&gt;
&lt;br /&gt;
   if ( p-&amp;gt;safety ) // player is in safe zone.&lt;br /&gt;
     {&lt;br /&gt;
        // do something.&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
   if ( !p-&amp;gt;safety ) // player NOT in safe zone.&lt;br /&gt;
     {&lt;br /&gt;
        // do something.&lt;br /&gt;
     }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Obtaining a player pointer using name comparison ===&lt;br /&gt;
&lt;br /&gt;
Since Player pointers are internal to MERVBot, it is necessary to find a way of obtaining a Player pointer from the identifying information given by the game. One of the simpler ways is just to compare the names after converting to lowercase.&lt;br /&gt;
&lt;br /&gt;
''Note'': Using pilot names as vital comparisions should be used with caution. See [http://cypherjf.sscentral.com/articles/bots-as-clients/ Bot-Issues] by CypherJF.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// return Player* info (or NULL if not found) from p-&amp;gt;name info&lt;br /&gt;
Player * botInfo::GetPilot(char *name)&lt;br /&gt;
{&lt;br /&gt;
	// get pilot from a name, return as TempPlayer&lt;br /&gt;
	_listnode &amp;lt;Player&amp;gt; *parse = playerlist-&amp;gt;head;&lt;br /&gt;
&lt;br /&gt;
	//convert search name to lowercase&lt;br /&gt;
	char nname[20], pname[20];&lt;br /&gt;
	strncpy(nname, name, 20);&lt;br /&gt;
	tolower(nname);&lt;br /&gt;
&lt;br /&gt;
	while (parse)&lt;br /&gt;
	{&lt;br /&gt;
		Player *p = parse-&amp;gt;item;&lt;br /&gt;
&lt;br /&gt;
		// convert to lowercase to compare&lt;br /&gt;
		strncpy(pname,p-&amp;gt;name,20);&lt;br /&gt;
		tolower(pname);&lt;br /&gt;
		if (strcmp(pname,nname)==0)&lt;br /&gt;
			return p;&lt;br /&gt;
		&lt;br /&gt;
		parse = parse-&amp;gt;next;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return NULL;	//player not found&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Bot built in functions==&lt;br /&gt;
&lt;br /&gt;
Here are some useful MervBot commands to control what the bot is doing.&lt;br /&gt;
&lt;br /&gt;
Player.cpp:&lt;br /&gt;
* Player::move(Sint32 x, Sint32 y) moves a player to the coordinates specified by x and y&lt;br /&gt;
* Player::clone(Player *p) clones a player into a player class&lt;br /&gt;
&lt;br /&gt;
Look in Commands.txt , command.cpp (core), or /!help to bot to see all bot external commands (example /!go &amp;amp;lt;arena&amp;amp;gt;).&lt;br /&gt;
&lt;br /&gt;
''LVZ Object toggling commands in plugins are to go here.''&lt;br /&gt;
&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5939</id>
		<title>Obtaining the Discretion Source using Subversion</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5939"/>
				<updated>2008-04-24T08:31:05Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: /* Links */  added server link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how to obtain the Discretion source code using subversion. It assumes you know nothing and have no tools already installed. It is part of the [[Discretion Module Tutorial]]. It assumes you are using Windows, although the process for other operating systems is very similar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Subversion is a version control system which allows many programmers to incrementally and concurrently work on a project. Basically it is a common way of organizing large projects superior to the &amp;quot;e-mail your changes to everyone&amp;quot; method. It also has lots of other nifty tricks which aren't important for right now.&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
The tutorial video can be obtained [[Media:disc_svn.wmv|here]].&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
svn link: [http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91|download subversion]&lt;br /&gt;
&lt;br /&gt;
Discretion client repository: https://ss-discretion.svn.sourceforge.net/svnroot/ss-discretion/client/trunk&lt;br /&gt;
&lt;br /&gt;
Discretion server repository: https://ss-discretion.svn.sourceforge.net/svnroot/ss-discretion/server/trunk&lt;br /&gt;
&lt;br /&gt;
[[Category:Discretion]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Discretion&amp;diff=5935</id>
		<title>Discretion</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Discretion&amp;diff=5935"/>
				<updated>2008-03-22T13:17:58Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: updates&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:discretionss.PNG|thumb|A Screenshot of SubSpace Discretion.]]&lt;br /&gt;
&lt;br /&gt;
Discretion[http://ss-discretion.sf.net] is a [[SubSpace]] client created by [[User:BaK|BaK]]. It is open source, like [[ASSS]], and is released under the [http://en.wikipedia.org/wiki/GPL GPL]. Discretion was developed because of the limitations of the in-use client, [[Continuum]]. Furthermore, the lack of development of Continuum led to a situation where limitations in the client would never be overcome. Making heavy use of [http://en.wikipedia.org/wiki/Simple_DirectMedia_Layer SDL], Discretion is cross-platform, and is currently supported under Windows, Linux, and Mac OS X. Discretion is intended to be secure through design, rather than through obscurity like Continuum. It is designed to make cheating is impossible, rather than just difficult. There is also an extensive [[Discretion Module Tutorial]] on this wiki for those interested in helping out.&lt;br /&gt;
&lt;br /&gt;
Since cheating is to be made impossible, the server must check the data players send it for cheating. This requires modifying the server, which rules out using [[Subgame]]. There is, however, a modified ASSS Server that allows Discretion clients to connect. &lt;br /&gt;
&lt;br /&gt;
In order to encourage client development, Discretion is designed with a modular system similar to ASSS. There are interfaces which define actions for modules (such as &amp;quot;draw ship at 50,50&amp;quot;), and callbacks which signal when events occur (such as &amp;quot;player has been killed&amp;quot;). Where ever possible, magic values have been removed and are instead loaded from plain-text settings files. The goal of this is to eliminate any built-in constraints present in VIE SubSpace and Continuum. These magic values include the location / color of the FPS counter, 1024x1024 tiles in maps, each tile being 16x16 pixels, each ship image having 40 frames thus 9 degree turns, the number of fly over tiles, two sets of doors four tiles each per map, the 0x01 type packet corresponding to an arena login, friendly players showing up yellow in the stat box, the colors in the font file, the number of frames in the wormhole animation, the text that shows up when you press ESC, the number of ships, as well as all the settings Continuum does allow you to change such as the ship images, the game play settings, and the controls. The server is intended to be able to modify most of these, thus giving [[Zone]] developers maximum creativity and flexibility.&lt;br /&gt;
&lt;br /&gt;
==Modules==&lt;br /&gt;
Discretion is divided up into several modules, dynamically linked into the main program much like ASSS. These modules are desired to be as generic as possible, with their Continuum-like actions coming from the settings, rather than the modules themselves. Thus Discretion is like a 2D grid game engine, with settings and graphics which make it look like SubSpace. The module interfaces are documented in the corresponding header files using Javadoc-style documentation. There are currently over 30 modules in the Discretion release. Some of the main ones are discussed below.&lt;br /&gt;
&lt;br /&gt;
===Settings Handler===&lt;br /&gt;
The '''SettingsHandler''' modules loads the settings from ini-like plain text files. The main settings file is located in conf/MAIN.CONF, which #includes many other settings files. All these settings files are plain text, meaning they can be edited using a utility like pico or notepad. Individual settings can be specified in several formats, depending on how they should be interpreted. Supported types include integers (''50'', ''0x30'', ''0777''), strings (''hello person''), points/vectors/dimensions (''(100,200)''), rgb colors (''(255,255,255)'', ''(0,128,128)''), and [[LVZ]]-style screen locations (''(C+50,50)'', ''(B-10,C+25)''). There also exists a helper function to parse comma separated a list of strings from a single sting in shared/StringManip.h. This module interface also allows modules to load their own conf files, or save a group of settings to a file which the program can then read out of.&lt;br /&gt;
&lt;br /&gt;
The front end program, '''cskinviewer''' uses the saving capability of '''SettingsHandler''' to keep track of zone data between program executions.&lt;br /&gt;
&lt;br /&gt;
===Module Manager===&lt;br /&gt;
The '''Module Manger''' itself is a module which is loaded by the program, which then proceeds to load any other modules. This uses the setting Modules::Names which is a comma separated list of strings to figure out which modules to load. It loads module files, '.dll's in Windows and '.so's in Linux, from the bin/ directory. Modules are loaded in stages. During the first stage, LOADMODE_Init, modules register their interface, if any, with the '''Module Manager''' and register any callbacks they want to listen for. During the next stage, LOADMODE_LoadInterfaces, modules load any interfaces they plan to use. Finally, during LOADMODE_PostLoadInterfaces, modules can use their loaded interfaces to other modules to initialize themselves. Upon successful program termination, LOADMODE_Unload is invoked which allows the module to free any data or resources it's using. The module manager also facilitates callbacks. Where possible, C++ exception handling is used to aid in catching errors in a non-fatal way and reports the cause of the problem.&lt;br /&gt;
&lt;br /&gt;
Note that some initialization tasks should not be done in LOADMODE_PostLoadInterfaces since they require modules be initialized in a specific order. For example, the '''Text''' module, which writes text to the screen should not be initialized before the ''Graphics'' module is, since it would be unable to load the text image. Thus some initialization tasks are be done in callbacks, CB_LOADIMAGES in this instance.&lt;br /&gt;
&lt;br /&gt;
===Graphics===&lt;br /&gt;
The '''Graphics''' module allows one to load images and draw them to the screen or map. When an image is loaded through the interface, an image handle is given to the calling module which is used to refer to the image. This handle can also be used to get the image size (taking into account that some images are framed animations), or free the image when it's no longer needed. Blank images can also be created and drawn on, thus allowing one to predraw complex images instead of redrawing them every frame. Images, when drawn to the screen, are drawn in layers. This allows several modules to queue up images to be drawn out of order and still result in a correct drawing. Some layers include L_Tiles, L_Weapons, L_AfterWeapons, L_Gauges, L_Chat and L_TopMost. Images can be drawn relative to the screen, or relative to the map. Images can also be blended such that they appear translucent, as long as the user has Graphics::UseBlending set to 1. Rectangles of a constant color can also be drawn to the screen or on to another image. The images are queued up to be drawn during the CB_PRERENDER callback.&lt;br /&gt;
&lt;br /&gt;
Although providing a basic interface, it is uncommon to '''Graphics''' module directly for loading images. Instead the '''UniqueImage''' module allows one to specify an image in the settings and refer to it in code by a name. This is much easier than loading the image yourself, and easily allows a single graphic to contain many different images, which is not uncommon in SubSpace images (the bullets image, for example, contains images for all sorts of bullets rather than just a single type). The '''UniqueImage''' module makes sure to only keep a single copy of the image in memory at all times. The '''UniqueImage''' module, in turn, is used by the '''Animations''' module to provide simple access to SubSpace-style animations. Thus, a programmer can code something like 'draw animation &amp;quot;bullet explosion&amp;quot; at 512,512' and it will handle loading the image, figuring out how many frames there are, the speed of the animation, and how long to display it for.&lt;br /&gt;
&lt;br /&gt;
===Controls===&lt;br /&gt;
The '''Controls''' module permits the programmer to provide actions(&amp;quot;move forward&amp;quot;), while the settings specify exactly what keyboard or joystick input they correspond to(&amp;quot;up arrow key&amp;quot;). Controls should be registered in the CB_CONTROLSLOADED callback. Also, since this a generic module it does not capture any of the physical controls itself, instead relying on other modules to handle that aspect.&lt;br /&gt;
&lt;br /&gt;
The '''SDL Key Controls''' module handles capturing keyboard input and sending it to the '''Controls''' module. The '''Mouse''' module does not use the '''Controls''' module directly, instead providing its own interface which allows one to create mouse hotspots and be notified of mouse clicks or movements within these hotspots.&lt;br /&gt;
&lt;br /&gt;
===Timers===&lt;br /&gt;
Similar to how ASSS has timers implemented in the mainloop module, Discretion has a '''Timers''' module that provides a timer functionality. One can register a function to be called in X milliseconds, or every X milliseconds until it's canceled. Discretion is currently not multithreaded beyond SDL, so that a timer in an infinite loop (or any piece of code that gets to run, for that matter), will result in the program freezing up. Thus you should not use blocking calls in timers or take up too much processing time which will degrade performance.&lt;br /&gt;
&lt;br /&gt;
The '''Net''' module uses a timer to send and receive packets.&lt;br /&gt;
&lt;br /&gt;
===Text===&lt;br /&gt;
The '''Text''' module provides an easy way to draw text on the screen. This is the standard subspace text and can be specfied by color. This module draws the text on one line for a single frame. Therefore, you must call the appropriate functions in this interface during CB_PRERENDER every frame for however long you wish to display the text. There is support for drawing text relative to the screen or to the map, as well as blending text and drawing on any layer.&lt;br /&gt;
&lt;br /&gt;
The '''Textbox''' module uses '''Text''' to draw its text, but provides additional features such as drawing textbox borders and allowing easy textbox loading from files. '''EscapeBox''' and '''PlayerList''', in turn, use '''Textbox'''. '''Chat''' also makes use of the '''Text''' module when it draws player chat to the screen. The '''Flash''' module, which handles messages similar to SubSpace's kill and prize messages, also uses the '''Text''' module. Pretty much anywhere you see text, the '''Text''' module is at work.&lt;br /&gt;
&lt;br /&gt;
===Physics===&lt;br /&gt;
The '''Physics''' module provides functions which can give you a particle's new position given its initial position, velocity, and time elapsed. This is used for ships as well as weapons. The position can be advanced in such a way that is affected by the map (such as bombs going around a wormhole), or not. Particles can bounce off the level or explode on contact.&lt;br /&gt;
&lt;br /&gt;
The '''SelfShip''' module uses '''Physics''' to compute the new position of the player over time. '''SS_Items''' uses '''Physics''' to find the position of a bullet after a certain amount of time.&lt;br /&gt;
&lt;br /&gt;
===PerPlayerData===&lt;br /&gt;
The '''PerPlayerData''' module provides a simple way to have data that is common to every player. This is similar to ASSS' PlayerData module in that a struct of memory can be allocated for every player and referred to using a key. The module also facilitates simple sharing of per player data between module such as &amp;quot;name&amp;quot;, &amp;quot;x&amp;quot;, or &amp;quot;y&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The '''PlayerList''' module uses the sharing facility of '''PerPlayerData''' to get the names of the players on the player list.&lt;br /&gt;
&lt;br /&gt;
===Level===&lt;br /&gt;
The '''Level''' module provides a simple interface to possibly many different types of level formats. Modules can load levels through the interface, as well as get the map or tile size. Furthermore, forces on the level, such as wormholes, friction, or gravity can be applied through the interface.&lt;br /&gt;
&lt;br /&gt;
Currently, the only map format implemented is '''oldlvl''' which supports regular SubSpace [[LVL]] files. This provides a somewhat more generic implementation, which a customizable amount of doors or custom animation tiles (wormholes, space station, and asteriods), as well as having wormholes with different properties on the same map.&lt;br /&gt;
&lt;br /&gt;
===Front End===&lt;br /&gt;
The front end, not exactly a module, is implemented as its own program, '''cskinviewer''', contributed by [[User:Smong|Smong]]. This program allows one to download a list of ASSS servers from a [[Directory Server]], and choose one and login. It uses the '''SettingsHandler''' to save the current zone list to the settings. Custom zones can not be added through the interface yet, but can be added by hand by editing conf/profiles/ZoneList.conf. &lt;br /&gt;
&lt;br /&gt;
The front end executes '''in_game''', which in turn loads the '''Module Manager''' which runs '''Main SDL''' which runs callbacks to load the various SDL Subsystems and starts the program's main loop.&lt;br /&gt;
&lt;br /&gt;
==Contribute==&lt;br /&gt;
Development for Discretion is ongoing and everyone is encouraged to contribute. Graphics are always helpful, and if you have an idea feel free to make it. In the spirit of free software, it would be best if eventually all VIE owned graphics were replaced, as their copyright status is unknown. This includes the ships, bullets, default tileset, and all other graphics from VIE SubSpace or Continuum. Also, a Discretion [[skin]] is yet to be made for the front end (the format follows that of Continuum's, see the skins directory in your Continuum folder). Additionally, many features are in development or unimplemented. If one wanted to help out, just contact [[User:BaK|BaK]], or start working on graphics or a module. There is also a [[Discretion Module Tutorial]] which shows you how to create a simple module. Some planned modules include:&lt;br /&gt;
&lt;br /&gt;
====Star Background====&lt;br /&gt;
A '''StarBackground''' module that draws stars and planets similar to how Continuum does it. It would be great it this looked better than Continuum as it would really lead to the immersion necessary for a fun experience. This could also be used to draw all sorts of backgrounds, such as grass for earth-based zones, to provide an alternate to tiling LVZ all over the map. This would be a good module to make to get introduced to Discretion development.&lt;br /&gt;
&lt;br /&gt;
====LVZ====&lt;br /&gt;
A reverse compatible LVZ module is desired to allow current zones to easily switch over to Discretion without remaking their lvz files. This could provide additional functionality not present in current lvz such as lvz that depend on ship locations to allow animations within shipsets. The easier way to make this is probably to make a static image/animation module which uses the settings and '''UniqueImage''' and '''Animations''' to draw images on the map and screen. Then, an lvz compatibility layer module would be made which translates an lvz file into a .conf file and uses '''SettingsHandler''' to load in the images from the generated file.&lt;br /&gt;
&lt;br /&gt;
====Radar====&lt;br /&gt;
Subspace and Continuum include a radar for locating enemies. This will have to be implemented in Discretion. The users should also be able to make the radar bigger by pressing a key (alt).&lt;br /&gt;
&lt;br /&gt;
====Sound====&lt;br /&gt;
Sound provides immersion in video games and gives them an authentic feel. We need a way to play sounds when certain actions occur such as a bullet being fired or player bouncing off a wall. WAV sounds will have to be implemented for reverse compatibility, but mp3 is not out of the question for longer sounds such as victory music or just music in general. After this is done, a built in mp3 player could be made to allow players to change songs from within the game. SDL_mixer[http://www.libsdl.org/projects/SDL_mixer/] provides mp3 capabilities and may be used.&lt;br /&gt;
&lt;br /&gt;
====Weapons====&lt;br /&gt;
Currently, only non-bouncing bullets are implemented. There are many items SubSpace uses which must be implemented. Care must be taken here to prevent cheating. For example, it would not be difficult to write a program to detect right before a player is about to get hit and automatically portal out or repel. Thus, these items may have to be modified to be on a timer, so that using a portal might require your ship to take a second to &amp;quot;charge up&amp;quot; instead of instantly warping. Also, it would be great if weapons didn't have to follow boring straight lines and instead could turn. Thus I could specify in the settings the direction a weapon would travel if the ship were facing straight up and it would happen. So a straight line would be (0,t), a curvy shot may be (sin(t),t), a shot that speeds up over time may be (0,2^t).&lt;br /&gt;
&lt;br /&gt;
====Custom Client Side Code====&lt;br /&gt;
The server should be able to provide code that can be executed client side. There are two types of code that will be provided: updated versions of modules, and game play related code. This is especially dangerous since a malicious server owner should not be permitted to compromise players' computers. The module updates can be done by providing a RSA signature with the binary .dll or .so which can be checked before executing any downloaded files. As for game play related code, a Java virtual machine could be used with a Security Manager that allows nothing beyond basic functions. Then, an interface could be provided to the game code that could be used by the code. Thus, binary .class file could be distributed for an arena that aren't allowed to delete files off your computer, but are allowed to access the game play relayed interface thus permitting graphics to be drawn or players to be warped around.&lt;br /&gt;
&lt;br /&gt;
==External links==&lt;br /&gt;
*[http://ss-discretion.sf.net Main Discretion Website]&lt;br /&gt;
&lt;br /&gt;
[[Category: Clients]]&lt;br /&gt;
[[Category: Discretion]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Core_Protocol&amp;diff=5934</id>
		<title>Core Protocol</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Core_Protocol&amp;diff=5934"/>
				<updated>2008-03-18T05:39:20Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: spacing&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This protocol is UDP and bi-directional. It can be thought of as another layer within an application's network layer. [[Subgame]], [[ASSS]], [[Continuum]], VIE's [[SubSpace]] client, the [[Directory server]], and some [[Billing Server|Billing Servers]] utilize this protocol.&lt;br /&gt;
&lt;br /&gt;
There is support for reliable ordered packets, large packets and cluster packets.&lt;br /&gt;
&lt;br /&gt;
*The maximum packet size is 520 bytes&lt;br /&gt;
*All integers are little endian&lt;br /&gt;
*All core packets begin with the type byte 0x00&lt;br /&gt;
*Packets can be nested (They are usually processed recursively)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
0x01 login&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x01&lt;br /&gt;
2      4    client key&lt;br /&gt;
6      2    protocol version (vie = 0x01, ctm = 0x11)&lt;br /&gt;
&lt;br /&gt;
0x02 login response&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x02&lt;br /&gt;
2      4    ~client key (negative)&lt;br /&gt;
&lt;br /&gt;
0x03 reliable header&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x03&lt;br /&gt;
2      4    packet id&lt;br /&gt;
6      ?    payload (514 max)&lt;br /&gt;
&lt;br /&gt;
0x04 reliable acknowledge&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x04&lt;br /&gt;
2      4    packet id&lt;br /&gt;
&lt;br /&gt;
0x05 sync&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x05&lt;br /&gt;
2      4    local time&lt;br /&gt;
6      4    packets sent&lt;br /&gt;
10     4    packets received&lt;br /&gt;
&lt;br /&gt;
0x06 sync response&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x06&lt;br /&gt;
2      4    time from last received 0x05 packet&lt;br /&gt;
6      4    server time&lt;br /&gt;
&lt;br /&gt;
0x07 disconnect&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x07&lt;br /&gt;
&lt;br /&gt;
0x08 small chunk&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x08&lt;br /&gt;
2      ?    payload (expect 472 max)&lt;br /&gt;
keep appending payloads until 0x09 chunk tail is received&lt;br /&gt;
&lt;br /&gt;
0x09 chunk tail&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x09&lt;br /&gt;
2      ?    payload (expect 472 or less)&lt;br /&gt;
append this payload then process contents as a non-core packet&lt;br /&gt;
&lt;br /&gt;
0x0A stream&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x0A&lt;br /&gt;
2      4    total length of all segments&lt;br /&gt;
6      ?    payload &lt;br /&gt;
keep appending payloads until total length is reached then process contents as&lt;br /&gt;
a non-core packet.&lt;br /&gt;
&lt;br /&gt;
0x0B cancel stream request&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x0B&lt;br /&gt;
&lt;br /&gt;
0x0C cancel stream acknowledge&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x0C&lt;br /&gt;
&lt;br /&gt;
0x0E cluster&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x0E&lt;br /&gt;
2      1    length&lt;br /&gt;
3      ?    payload with length as above&lt;br /&gt;
packet repeats from offset 2 until end, process contents as arbitrary packet&lt;br /&gt;
&lt;br /&gt;
0x10 Continuum alternate encryption response (s2c)?&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x10&lt;br /&gt;
2      10   ??&lt;br /&gt;
&lt;br /&gt;
0x11 Continuum alternate encryption response response (c2s)?&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x11&lt;br /&gt;
2      6   ??&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Protocol]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Core_Protocol&amp;diff=5933</id>
		<title>Core Protocol</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Core_Protocol&amp;diff=5933"/>
				<updated>2008-03-18T05:38:56Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: observed some undocumented packets &amp;quot;in the wild&amp;quot; so I'd figure I'd add them&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This protocol is UDP and bi-directional. It can be thought of as another layer within an application's network layer. [[Subgame]], [[ASSS]], [[Continuum]], VIE's [[SubSpace]] client, the [[Directory server]], and some [[Billing Server|Billing Servers]] utilize this protocol.&lt;br /&gt;
&lt;br /&gt;
There is support for reliable ordered packets, large packets and cluster packets.&lt;br /&gt;
&lt;br /&gt;
*The maximum packet size is 520 bytes&lt;br /&gt;
*All integers are little endian&lt;br /&gt;
*All core packets begin with the type byte 0x00&lt;br /&gt;
*Packets can be nested (They are usually processed recursively)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
0x01 login&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x01&lt;br /&gt;
2      4    client key&lt;br /&gt;
6      2    protocol version (vie = 0x01, ctm = 0x11)&lt;br /&gt;
&lt;br /&gt;
0x02 login response&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x02&lt;br /&gt;
2      4    ~client key (negative)&lt;br /&gt;
&lt;br /&gt;
0x03 reliable header&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x03&lt;br /&gt;
2      4    packet id&lt;br /&gt;
6      ?    payload (514 max)&lt;br /&gt;
&lt;br /&gt;
0x04 reliable acknowledge&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x04&lt;br /&gt;
2      4    packet id&lt;br /&gt;
&lt;br /&gt;
0x05 sync&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x05&lt;br /&gt;
2      4    local time&lt;br /&gt;
6      4    packets sent&lt;br /&gt;
10     4    packets received&lt;br /&gt;
&lt;br /&gt;
0x06 sync response&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x06&lt;br /&gt;
2      4    time from last received 0x05 packet&lt;br /&gt;
6      4    server time&lt;br /&gt;
&lt;br /&gt;
0x07 disconnect&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x07&lt;br /&gt;
&lt;br /&gt;
0x08 small chunk&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x08&lt;br /&gt;
2      ?    payload (expect 472 max)&lt;br /&gt;
keep appending payloads until 0x09 chunk tail is received&lt;br /&gt;
&lt;br /&gt;
0x09 chunk tail&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x09&lt;br /&gt;
2      ?    payload (expect 472 or less)&lt;br /&gt;
append this payload then process contents as a non-core packet&lt;br /&gt;
&lt;br /&gt;
0x0A stream&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x0A&lt;br /&gt;
2      4    total length of all segments&lt;br /&gt;
6      ?    payload &lt;br /&gt;
keep appending payloads until total length is reached then process contents as&lt;br /&gt;
a non-core packet.&lt;br /&gt;
&lt;br /&gt;
0x0B cancel stream request&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x0B&lt;br /&gt;
&lt;br /&gt;
0x0C cancel stream acknowledge&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x0C&lt;br /&gt;
&lt;br /&gt;
0x0E cluster&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x0E&lt;br /&gt;
2      1    length&lt;br /&gt;
3      ?    payload with length as above&lt;br /&gt;
packet repeats from offset 2 until end, process contents as arbitrary packet&lt;br /&gt;
&lt;br /&gt;
0x10 Continuum alternate encryption response(s2c)?&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x10&lt;br /&gt;
2      10   ??&lt;br /&gt;
&lt;br /&gt;
0x11 Continuum alternate encryption response response (c2s)?&lt;br /&gt;
offset size comment&lt;br /&gt;
0      1    type 0x00&lt;br /&gt;
1      1    type 0x11&lt;br /&gt;
2      6   ??&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Protocol]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=User_talk:Mine_GO_BOOM&amp;diff=5932</id>
		<title>User talk:Mine GO BOOM</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=User_talk:Mine_GO_BOOM&amp;diff=5932"/>
				<updated>2008-03-18T04:13:17Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: yeah..&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I was cutting my wiki teeth on here yesterday- I apologize for the unneccesary updates.&amp;lt;br/&amp;gt;&lt;br /&gt;
Was the formatting and content ok?&lt;br /&gt;
&lt;br /&gt;
[[User:I88gerbils|i88gerbils]]: Where's rollback?  I'm trying to look up that functionality but can't find it on the Wiki help site.  update:  I see, it's an admin. command. :)&lt;br /&gt;
&lt;br /&gt;
[[User:I88gerbils|i88gerbils]]: Please delete the dumbass duplicate page I created today.  Thanks.&lt;br /&gt;
&lt;br /&gt;
== mineplowers.com ==&lt;br /&gt;
&lt;br /&gt;
[[User:Mine GO BOOM|Mine GO BOOM]] 23:35, 30 May 2006 (EDT): This is the wiki running off mineplowers.com.&lt;br /&gt;
&lt;br /&gt;
awesome, thanks [[User:BaK|BaK]] 21:13, March 17, 2008 (PDT)&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Talk:MERVBot_Tutorial&amp;diff=5922</id>
		<title>Talk:MERVBot Tutorial</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Talk:MERVBot_Tutorial&amp;diff=5922"/>
				<updated>2008-03-17T05:43:53Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: yea.. .mem leak&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==hmm==&lt;br /&gt;
Modified permanent get/setTag method = memory leak... boo&lt;br /&gt;
telling them to beware is eh... i dunno [[User:BaK|BaK]]&lt;br /&gt;
&lt;br /&gt;
==General Convo==&lt;br /&gt;
D1s: Anybody wanna format this int a table of contents? I'm lazy&lt;br /&gt;
&lt;br /&gt;
[[User:Smong|Smong]]: That is sick. Maybe split into more pages? Says it is over 160k.&lt;br /&gt;
&lt;br /&gt;
[[User:Pests|Pests]]: There is already pages defined. You could just split them up into that.&lt;br /&gt;
&lt;br /&gt;
OK, I'm working on converting it to real HTML (using &amp;amp;lt;pre&amp;amp;gt;) instead of the &amp;amp;amp;nbsp; crap. --[[User:Cyan~Fire|Cyan~Fire]]&lt;br /&gt;
&lt;br /&gt;
[[User:CypherJF|CypherJF]]: Should we just call this &amp;quot;the bot tutorial&amp;quot; based on the tutorial by Underlord? Then update it accordingly? -- And also, the link to MervBot w/e 37 is now 45; should we just comment that this tutorial was writen for the 37 -- or... comments! lol.&lt;br /&gt;
&lt;br /&gt;
[[User:CypherJF|CypherJF]]: I'd like to say that all sections appear to have been updated for the Wiki; time to go through edit, and catch mistakes. Add to the wiki itself - perhaps more example code.&lt;br /&gt;
&lt;br /&gt;
[[User:CypherJF|CypherJF]]: Cyan and I were talking about the section &amp;quot;Checking if pilot is in a safe zone&amp;quot;; whether or not to just remove it. I remarked that it's a nice section for those to the whole plugin deal. But, I was just noticing how it'd make more sense to put the &amp;quot;Useful Player data&amp;quot; before hand... So i guess the next step is to go through and try to address the logical-aspect of ordering of the content? What's your guys' take?&lt;br /&gt;
&lt;br /&gt;
[[User:Smong|Smong]]: Uh yeah.. so why are there so many major edits to just one page? I can't see anything in recent changes but edits to the mervbot tutorial.&lt;br /&gt;
&lt;br /&gt;
[[User:CypherJF|CypherJF]]: See my other notes: &amp;quot;CypherJF: Well I've been doing the edits from all around campus. Like yesterday I did 4-6 things from the MathLab; and the rest from the dorm, etc. lol. I don't think it really matters, since there isn't much other activity going on.. on the wiki.&amp;quot; So, I'd make edits and just post em. It happened to be the only activity and sooo it looks worse than it is.&lt;br /&gt;
&lt;br /&gt;
== sscanf ==&lt;br /&gt;
&lt;br /&gt;
Well, I'm using sscanf() for parsing player input. Yes, an advanced function, but maybe it will discourage C++ newbs from making bot plugins. Any comments? --[[User:Cyan~Fire|Cyan~Fire]]&lt;br /&gt;
&lt;br /&gt;
D1st0rt: Cool beans. I learned something new :D&lt;br /&gt;
&lt;br /&gt;
== Event list ==&lt;br /&gt;
&lt;br /&gt;
Removed event list because it was redundant with dllcore.h, less descriptive, and too easy to get out-of-date. Anybody who wants it back, please post here so I can ignore you. :-D --[[User:Cyan~Fire|Cyan~Fire]]&lt;br /&gt;
&lt;br /&gt;
[[User:CypherJF|CypherJF]]: Like people are really going to read through the dllcore.h file.. on a webpage tutorial. hmm i think not. I still say keep it there.&lt;br /&gt;
&lt;br /&gt;
If someone doesn't make the effort to look up events in dllcore.h, they shouldn't be making plugins. I think of this tutorial as more of a &amp;quot;here are the basics and intricacies of making a MERVBot plugin&amp;quot; more than &amp;quot;here is how to follow step-by-step instructions and call it programming&amp;quot;. --[[User:Cyan~Fire|Cyan~Fire]]&lt;br /&gt;
&lt;br /&gt;
D1s: Even ''I'' look up things in dllcore.h, its a very useful resource. As long as it says to look in it, I don't think we'd need the full list here&lt;br /&gt;
&lt;br /&gt;
== Extra Code Samples ==&lt;br /&gt;
[[User:CypherJF|CypherJF]]: I'd like to somehow split these up better; and make them linkable, what do you guy's think?&lt;br /&gt;
&lt;br /&gt;
[[User:CypherJF|CypherJF]]: I made sub-headers, and so they'll be added into the table of contents. Let me know what you guys think of it.&lt;br /&gt;
&lt;br /&gt;
Alrighty, looks good. One thing I would ask is to try to save up a bunch of edits in a text editor or something, than have the myriad edits you do now. Thanks for sharing the burden with me! --[[User:Cyan~Fire|Cyan~Fire]]&lt;br /&gt;
&lt;br /&gt;
[[User:CypherJF|CypherJF]]: Well I've been doing the edits from all around campus. Like yesterday I did 4-6 things from the MathLab; and the rest from the dorm, etc. lol. I don't think it really matters, since there isn't much other activity going on.. on the wiki.&lt;br /&gt;
&lt;br /&gt;
Oh, OK, that's fine. Also, do remember that the wiki will automatically do your &amp;amp;lt;p&amp;amp;gt;ing for you as long as you leave a blank line in-between &amp;quot;paragraphs&amp;quot;. --[[User:Cyan~Fire|Cyan~Fire]]&lt;br /&gt;
&lt;br /&gt;
== Example Code commenting system ==&lt;br /&gt;
&lt;br /&gt;
What's the use of it? --[[User:Cyan~Fire|Cyan~Fire]]&lt;br /&gt;
&lt;br /&gt;
[[User:Smong|Smong]]: So if people don't understand the examples they can request help or a clarification. Also people that do understand an example might want to post a better/alternative solution. I suppose since you need an account to edit a page, maybe the wiki can be setup so you don't need an account to edit the discussion page so people can put comments in there.&lt;br /&gt;
&lt;br /&gt;
I think I wasn't being very clear, Cypher didn't understand me either. I was talking about his &amp;amp;lt;!-- EXAMPLE A: BEGIN--&amp;amp;gt; stuff. Anyway, I've gotten permission from him to remove it, it was only supposed to be temporary. The idea of anonymous talk posts is a good idea, but I'm not sure if its possible. --[[User:Cyan~Fire|Cyan~Fire]]&lt;br /&gt;
&lt;br /&gt;
== Make bot spectate specific coordinates Section ==&lt;br /&gt;
--[[User:50% Packetloss|50% Packetloss]] 14:34, Feb 21, 2005 (EST)&lt;br /&gt;
&lt;br /&gt;
This is what is currently there.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tell(makeFollowing(false));&lt;br /&gt;
tell(makeFlying(true));&lt;br /&gt;
me-&amp;gt;move(512 * 16, 600 * 16);&lt;br /&gt;
tell(makeSendPosition(true));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now when you tell the bot tell(makeFlying(true)); the core makes DLLFlying= true; Thus in the core's function void Host::doEvents() instead of the bot sending position packets, the job is left to the dll. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//...&lt;br /&gt;
if (DLLFlying)&lt;br /&gt;
{&lt;br /&gt;
	Uint32 limit = settings.SendPositionDelay;&lt;br /&gt;
&lt;br /&gt;
	if (time - lastPosition &amp;gt; limit)&lt;br /&gt;
	{&lt;br /&gt;
		imports-&amp;gt;talk(makePositionHook());&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
else if (Me-&amp;gt;ship == SHIP_Spectator)&lt;br /&gt;
{	// Spectating&lt;br /&gt;
	Uint32 limit = settings.SendPositionDelay;&lt;br /&gt;
&lt;br /&gt;
	if (time - lastPosition &amp;gt; limit)&lt;br /&gt;
	{&lt;br /&gt;
		// Cycle player spectated&lt;br /&gt;
		if (Me-&amp;gt;ship == SHIP_Spectator)&lt;br /&gt;
			spectateNext();&lt;br /&gt;
&lt;br /&gt;
			sendPosition(false);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
else if //...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So in the dll, in the positionhook event, you need to add tell(sendPosition(false));. Im not sure if it will have a dramatic effect if the bot is in spec (never tested it), but if the bot is in a ship it will disappear from the screen. I don't know a lot about this wiki stuff so Ill leave it up to you ladies to edit.&lt;br /&gt;
&lt;br /&gt;
== Random Number Selection ==&lt;br /&gt;
&lt;br /&gt;
When picking a random number, the code for [[MERVBot_Tutorial#Picking_a_random_pilot|Picking a random pilot]] works off GetTickCount, which is very bad. GTC does not have single digit accuracy, and you can see this by running a loop for a couple of seconds and 'bucketing' the return values module X. If X is something like 25 or 50, you'll see very obvious patterns, where certain numbers are skipped completely. Even modulo something smaller like 10, and the distribution is horrible. The section right above this uses rand() correctly. In a simple tutorial, even rand() % X is much better than GTC() % X.&lt;br /&gt;
&lt;br /&gt;
== About recent code changes ==&lt;br /&gt;
&lt;br /&gt;
[[User:Mine GO BOOM|Mine GO BOOM]] 22:42, Jun 8, 2006 (EDT): Instead of using numbers in the code, such as '9' in atoi and 256 for str, you should use sizeof. If you change the size of str in the future, makes it easier to handle, and is also less prone to errors when you are coding, as you '''know''' it won't overflow the variable (unless it doesn't tack on '\0' at the end, check documentation on that function?).&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5921</id>
		<title>Obtaining the Discretion Source using Subversion</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5921"/>
				<updated>2008-03-17T05:33:22Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: category'd&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how to obtain the Discretion source code using subversion. It assumes you know nothing and have no tools already installed. It is part of the [[Discretion Module Tutorial]]. It assumes you are using Windows, although the process for other operating systems is very similar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Subversion is a version control system which allows many programmers to incrementally and concurrently work on a project. Basically it is a common way of organizing large projects superior to the &amp;quot;e-mail your changes to everyone&amp;quot; method. It also has lots of other nifty tricks which aren't important for right now.&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
The tutorial video can be obtained [http://ews.uiuc.edu/~sbak2/disc/disc_svn.wmv here].&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
svn link: [http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91|download subversion]&lt;br /&gt;
&lt;br /&gt;
discretion repository link: https://ss-discretion.svn.sourceforge.net/svnroot/ss-discretion/client/trunk&lt;br /&gt;
&lt;br /&gt;
[[Category:Discretion]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Discretion_Commands_and_Displaying_Images&amp;diff=5920</id>
		<title>Discretion Commands and Displaying Images</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Discretion_Commands_and_Displaying_Images&amp;diff=5920"/>
				<updated>2008-03-17T05:11:51Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: format&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a tutorial for module creation in [[Discretion]]. For other tutorials, see the [[Discretion Module Tutorial]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In this tutorial, you wil learn how to listen for chat commands using Discretion's Chat Module as well as how to load and display images on the screen using UniqueImage and Graphics.&lt;br /&gt;
&lt;br /&gt;
Topics covered: Listening for Callbacks, Using Interfaces, UniqueImage, Graphics&lt;br /&gt;
&lt;br /&gt;
We will make two commands, ?show and ?hide which will cause a graphic to appear and disappear on the screen.&lt;br /&gt;
&lt;br /&gt;
The first thing we'll do is make the graphic we want to display and put it in our Discretion/graphics folder. This can be done in a progam such as Paint. Here we saved the file as my_testimage.png.&lt;br /&gt;
&lt;br /&gt;
[[Image:cg_1.PNG]]&lt;br /&gt;
&lt;br /&gt;
Now onto the code, make a module as specified in the [[Creating and Testing a Simple Discretion Module]] tutorial. The first thing we're going to do is listen to the callback when commands are sent through the chat. Callbacks in Discretion are similar to callbacks in AS3. They represent events that occur that you can react to. Callbacks are registered through the module manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
  * -	tells the module manager that you want to receive a callback&lt;br /&gt;
  * @param myVersion the version of the module requresting this callback, this is useful in&lt;br /&gt;
  * debugging if we were to cause a crash while we're in a callback&lt;br /&gt;
  * @param callbackName is a name string that will tell the module manager which callback you want &lt;br /&gt;
  * to receive &lt;br /&gt;
  * @param callbackVersion is the version string for the callback. If you use an antiquated version, &lt;br /&gt;
  * and a different version of the callback is called, an error will be recorded&lt;br /&gt;
  * @param func is a function pointer to a function that should be called when the callback occurs, &lt;br /&gt;
  * note that all callback functions are of the same form, but you can cast the parameter to a more &lt;br /&gt;
  * usable form. Donâ€™t change the param, as it must be used to call the other functions too&lt;br /&gt;
  */&lt;br /&gt;
void (*regCallback)(const char* myVersion, const char* callbackName, const char* callbackVersion, callbackFunc func);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we pass in myVersion, which is used only if there's a problem with your callback handler, so make it something that you will be able to recognise when it's printed to the console, such as &amp;quot;show-hide graphic module&amp;quot; or the interface handle if you have an interface defined, or even the C preprocessor macro __FILE__ will work. callbackName and callbackVersion are unique to the callback, more on that in a moment, func is the function to call when the callback occurs. callbackFunc is typedefed to a function pointer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
typedef void (*callbackFunc)(void* param);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In general, you can figure out information about the callback in the file where it's defined. For the command callback we're interested in, we look in Chat.h:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// occurs when a possible internal command is sent, if you're processing this command set processed to TRUE&lt;br /&gt;
#define CB_INTERNALCOMMAND				&amp;quot;InternalCommand&amp;quot;&lt;br /&gt;
#define CB_INTERNALCOMMAND_VERSION		&amp;quot;1&amp;quot;&lt;br /&gt;
// the parameter is as follows, set processed to TRUE if you process it&lt;br /&gt;
struct InternalCommandParam&lt;br /&gt;
{&lt;br /&gt;
	const char* command; // the entire command line, with parameters and everything, but no command character&lt;br /&gt;
	BOOL processed; // set this to true if you process the command&lt;br /&gt;
&lt;br /&gt;
	// you can use this function to check if this command is yours, sets processed for you&lt;br /&gt;
	// setToParams points to whatever's after the command if successful, can be NULL if you don't care&lt;br /&gt;
	BOOL isCommand(const char* what, const char** setToParams)&lt;br /&gt;
	{&lt;br /&gt;
	...&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here the callback name is defined to CB_INTERNALCOMMAND and callback version is defined to CB_INTERNALCOMMAND_VERSION. The parameter to the callback, which is a anonymous pointer (void*) can be cast to a InternalCommandParam*. We then use the isCommand to check if this is the command we're interested in.&lt;br /&gt;
&lt;br /&gt;
So now to register the internal command callback with the module manager and print out a message to the console when we receive &amp;quot;?show&amp;quot; or &amp;quot;?hide&amp;quot;. Note that we have to #include &amp;quot;Chat/Chat.h&amp;quot; because that's where the callback is defined.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Commands - Graphics Tutorial Discretion Module&lt;br /&gt;
#include &amp;quot;Module.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Chat/Chat.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ModuleManager* mm = 0;&lt;br /&gt;
&lt;br /&gt;
void gotInternalCommand(void* param)&lt;br /&gt;
{&lt;br /&gt;
	InternalCommandParam* icp = (InternalCommandParam*)param;&lt;br /&gt;
&lt;br /&gt;
	if (icp-&amp;gt;isCommand(&amp;quot;show&amp;quot;,0))&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Received Command: show\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	else if (icp-&amp;gt;isCommand(&amp;quot;hide&amp;quot;,0))&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Received Command: hide\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void* getClassInstance(void* _mm, LoadMode lm)&lt;br /&gt;
{&lt;br /&gt;
	mm = (ModuleManager*)_mm;&lt;br /&gt;
&lt;br /&gt;
	if (lm == LOADMODE_Init)&lt;br /&gt;
	{&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__, CB_INTERNALCOMMAND, CB_INTERNALCOMMAND_VERSION, gotInternalCommand);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
extern &amp;quot;C&amp;quot; &lt;br /&gt;
{&lt;br /&gt;
	EXPORT void* getInstance(void* mm, LoadMode lm)&lt;br /&gt;
	{&lt;br /&gt;
		return getClassInstance(mm,lm);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We should be able to make this module and see the effect when we type ?show and ?hide and press enter in the chat.&lt;br /&gt;
&lt;br /&gt;
[[Image:cg_2.PNG]]&lt;br /&gt;
&lt;br /&gt;
Now onto making an image display on the screen. There are two steps to this, loading the image, and drawing the image on the screen. Loading the image can be done in a few ways, the easiest is to use the UniqueImage module. The UniqueImage module loads settings from conf files, so you can refer to the image by name in the code. UniqueImage also ensures the image is only loaded once (it's unique), so that you can use the same image in different modules without worrying about wasting memory. Unique image will give you an image handle from an image name. An image handle is just an int, which we can pass to Graphics when we're drawing the image. First we'll define the image in the conf files. Open up Image.conf in conf/visual/ and add &amp;lt;Image Name&amp;gt;Path = &amp;lt;path to image&amp;gt; and &amp;lt;Image Name&amp;gt;Frames = (1, 1) to the bottom of the file. In the picture we use CommandsGraphicsTutorial as the name of our image... this is what we'll refer to the image in the code, just make sure it isn't the same as any of the other names. The Frams setting defines how many frames are in the image, for example ships are typcially defined in a single file with 40 images aranged 10 wide and 4 tall, so we'd use (10,4) for the frames if we had such an image. For our image though, we only use a single frame so (1, 1) is correct.&lt;br /&gt;
&lt;br /&gt;
[[Image:cg_3.PNG]]&lt;br /&gt;
&lt;br /&gt;
Now we have to get the UniqueImage interface and use it. Interfaces are generally loaded during LOADMODE_LoadInterfaces in getClassInstance. They are gotten using the interface identifier and the module manager. The interface identifier is defined in UniqueImage.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define I_UNIQUEIMAGE 	&amp;quot;UniqueImage-1&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To use this constant we need to #include &amp;quot;UniqueImage/UniqueImage.h&amp;quot;. In getClassInstance, if lm is LOADMODE_LoadInterfaces, we use the module manager to load the interface using the getInterface function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
  * -	tells the module manager that you want an interface. If the interface is not loaded by the &lt;br /&gt;
		module manager, an error will result which the module manager takes care of &lt;br /&gt;
  * -	this should be called when getInstance(MODE_LoadInterfaces) is called&lt;br /&gt;
  * @param myVersion the version of the module calling this function&lt;br /&gt;
  * @param getVersion the version of the module we want to load&lt;br /&gt;
  * @return a void* pointing to the class interface of the loaded module&lt;br /&gt;
  */&lt;br /&gt;
void* (*getInterface)(const char* myVersion, const char *getVersion);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here getVersion is I_UNIQUEIMAGE, myVersion, as in callbacks, is only used in case of errors. We can use __FILE__ or an identfying string like &amp;quot;commands-graphics tutorial&amp;quot;. We save the pointer returned by getInterface. The question now is when should we call UniqueImage's getImageHandle function. We want to make sure that we do not call it too early, because the image loading system may not be initialized. This problem is solved through callbacks. For loading images, there is a callback that says &amp;quot;the image loading system is initialized, load your images now&amp;quot;. This callback is in Graphics.h, CB_LoadImages.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
This LoadImage callback will be called when the images are to be loaded, there is no parameter&lt;br /&gt;
This is guarenteed to be in POSTLOAD_Interfaces&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define CB_LOADIMAGES			&amp;quot;LoadImages&amp;quot;&lt;br /&gt;
#define CB_LOADIMAGES_VERSION	&amp;quot;1&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So we register a callback for this function (and #include &amp;quot;Graphics/Graphics.h&amp;quot;), and load our image and save the image handle UniqueImage gives us.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Commands - Graphics Tutorial Discretion Module&lt;br /&gt;
#include &amp;quot;Module.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Chat/Chat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;UniqueImage/UniqueImage.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Graphics/Graphics.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ModuleManager* mm = 0;&lt;br /&gt;
UniqueImage* ui = 0;&lt;br /&gt;
&lt;br /&gt;
int imageHandle = 0;&lt;br /&gt;
&lt;br /&gt;
void gotInternalCommand(void* param)&lt;br /&gt;
{&lt;br /&gt;
	InternalCommandParam* icp = (InternalCommandParam*)param;&lt;br /&gt;
&lt;br /&gt;
	if (icp-&amp;gt;isCommand(&amp;quot;show&amp;quot;,0))&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Received Command: show\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	else if (icp-&amp;gt;isCommand(&amp;quot;hide&amp;quot;,0))&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Received Command: hide\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loadImages(void* param)&lt;br /&gt;
{&lt;br /&gt;
	imageHandle = ui-&amp;gt;getImageHandle(&amp;quot;CommandsGraphicsTutorial&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void* getClassInstance(void* _mm, LoadMode lm)&lt;br /&gt;
{&lt;br /&gt;
	mm = (ModuleManager*)_mm;&lt;br /&gt;
&lt;br /&gt;
	if (lm == LOADMODE_Init)&lt;br /&gt;
	{&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__, CB_INTERNALCOMMAND, CB_INTERNALCOMMAND_VERSION, gotInternalCommand);&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__, CB_LOADIMAGES, CB_LOADIMAGES_VERSION, loadImages);&lt;br /&gt;
	}&lt;br /&gt;
	else if (lm == LOADMODE_LoadInterfaces)&lt;br /&gt;
	{&lt;br /&gt;
		ui = (UniqueImage*)mm-&amp;gt;getInterface(__FILE__,I_UNIQUEIMAGE);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
extern &amp;quot;C&amp;quot; &lt;br /&gt;
{&lt;br /&gt;
	EXPORT void* getInstance(void* mm, LoadMode lm)&lt;br /&gt;
	{&lt;br /&gt;
		return getClassInstance(mm,lm);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the image, we need to draw it on the screen. This is done using the Graphics interface. We get this interface similar to how we got the UniqueImage interface (in getClassInstance where lm == LOADMODE_LoadInterfaces). The function we're interested is one that draws images on the screen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Draw an image in the next frame, this is to be done in the prerender callback&lt;br /&gt;
  * This one draws relative to screen coordinates, rather than absolute coordinates, no bounds checking is done&lt;br /&gt;
  * @param imageHandle an image handle from the loadImage function&lt;br /&gt;
  * @param frame the frame of the image to draw on, for example the rotated ship graphic is 0-39&lt;br /&gt;
  * @param xPixel the xPixel to draw with, this in screen coordinates&lt;br /&gt;
  * @param yPixel the yPixel to draw with, this in screen coordinates&lt;br /&gt;
  * @param Layer the layer to draw on, probably from the enum Layer&lt;br /&gt;
  * @blend a number between 0 and 100 to determine how much blending is to be done for this image, &lt;br /&gt;
  *        so 0 is completely transparent and 100 is opaque&lt;br /&gt;
  */&lt;br /&gt;
void (*drawScreenImage)(int imageHandle, int xPixel, int yPixel, int frame, int layer, int blend);&lt;br /&gt;
void (*drawScreenImage2)(int imageHandle, int xPixel, int yPixel, int layer);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
imageHandle is the handle we got from UniqueImage, xPixel is the x pixel to use for the left part of the image, yPixel is the y pixel for the top of the image. (0, 0) is the upper left corner of the screen, with y increasing downward and x increasing rightward. Frame is the frame of the image to draw, for us this is 0 since we have only a single frame defined in our image. Layer is layer to draw on, some common ones are given in the enum Layer. Blend is the amount to blend the image, 100 for opaque images and fading to completely transparent when blend is 0. Here is the layer enum:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// The layer enum, note you can define your own layers between these ones if you want&lt;br /&gt;
enum Layer&lt;br /&gt;
{&lt;br /&gt;
	L_BelowAll = 50,&lt;br /&gt;
	L_Background = 100,&lt;br /&gt;
	L_AfterBackground = 150,&lt;br /&gt;
	L_Tiles = 200,&lt;br /&gt;
	L_AfterTiles = 250,&lt;br /&gt;
	L_Weapons = 300,&lt;br /&gt;
	L_AfterWeapons = 350,&lt;br /&gt;
	L_Ships = 400,&lt;br /&gt;
	L_AfterShips = 450,&lt;br /&gt;
	L_Gauges = 500,&lt;br /&gt;
	L_AfterGauges = 550,&lt;br /&gt;
	L_Chat = 600,&lt;br /&gt;
	L_AfterChat = 650,&lt;br /&gt;
	L_TopMost = 700&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The question now is when we should call drawScreenImage. The answer is, once again, in a callback. The callback in this case is in Graphics.h, PreRender:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// The parameter to the prerender callback&lt;br /&gt;
struct PrerenderParam&lt;br /&gt;
{&lt;br /&gt;
	PrerenderParam(int m, Rect* s) : milDif(m) , screen(s) {} &lt;br /&gt;
&lt;br /&gt;
	int milDif; // milliseconds since last prerender callback, or 0 on the first one&lt;br /&gt;
	Rect* screen; // the screen bounds, in pixels&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// The prerender callback&lt;br /&gt;
#define CB_PRERENDER			&amp;quot;Pre-render&amp;quot;&lt;br /&gt;
#define CB_PRERENDER_VERSION	&amp;quot;2&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
This callback occurs every frame, when we call drawScreenImage, it will get drawn for a single frame. We register the callback like we did for LoadImages and InternalCommand. We then call drawScreenImage based on whether the user has used ?show or not. The final version the code is below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Commands - Graphics Tutorial Discretion Module&lt;br /&gt;
#include &amp;quot;Module.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Chat/Chat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;UniqueImage/UniqueImage.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Graphics/Graphics.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ModuleManager* mm = 0;&lt;br /&gt;
UniqueImage* ui = 0;&lt;br /&gt;
Graphics* g = 0;&lt;br /&gt;
&lt;br /&gt;
int imageHandle = 0;&lt;br /&gt;
bool showImage = false;&lt;br /&gt;
&lt;br /&gt;
void gotInternalCommand(void* param)&lt;br /&gt;
{&lt;br /&gt;
	InternalCommandParam* icp = (InternalCommandParam*)param;&lt;br /&gt;
&lt;br /&gt;
	if (icp-&amp;gt;isCommand(&amp;quot;show&amp;quot;,0))&lt;br /&gt;
	{&lt;br /&gt;
		showImage = true;&lt;br /&gt;
	}&lt;br /&gt;
	else if (icp-&amp;gt;isCommand(&amp;quot;hide&amp;quot;,0))&lt;br /&gt;
	{&lt;br /&gt;
		showImage = false;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loadImages(void* param)&lt;br /&gt;
{&lt;br /&gt;
	imageHandle = ui-&amp;gt;getImageHandle(&amp;quot;CommandsGraphicsTutorial&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void preRender(void* param)&lt;br /&gt;
{&lt;br /&gt;
	if (showImage)&lt;br /&gt;
	{&lt;br /&gt;
		g-&amp;gt;drawScreenImage2(imageHandle, 200, 200, L_TopMost);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void* getClassInstance(void* _mm, LoadMode lm)&lt;br /&gt;
{&lt;br /&gt;
	mm = (ModuleManager*)_mm;&lt;br /&gt;
&lt;br /&gt;
	if (lm == LOADMODE_Init)&lt;br /&gt;
	{&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__, CB_INTERNALCOMMAND, CB_INTERNALCOMMAND_VERSION, gotInternalCommand);&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__, CB_LOADIMAGES, CB_LOADIMAGES_VERSION, loadImages);&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__, CB_PRERENDER, CB_PRERENDER_VERSION, preRender);&lt;br /&gt;
	}&lt;br /&gt;
	else if (lm == LOADMODE_LoadInterfaces)&lt;br /&gt;
	{&lt;br /&gt;
		ui = (UniqueImage*)mm-&amp;gt;getInterface(__FILE__,I_UNIQUEIMAGE);&lt;br /&gt;
		g = (Graphics*)mm-&amp;gt;getInterface(__FILE__,I_GRAPHICS);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
extern &amp;quot;C&amp;quot; &lt;br /&gt;
{&lt;br /&gt;
	EXPORT void* getInstance(void* mm, LoadMode lm)&lt;br /&gt;
	{&lt;br /&gt;
		return getClassInstance(mm,lm);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And when we run this module in Discretion we get the desired result:&lt;br /&gt;
&lt;br /&gt;
[[Image:cg_4.PNG]]&lt;br /&gt;
&lt;br /&gt;
Hopefully, by now you are comfortable with listening to callbacks and using interfaces as well as more familiar with the UniqueImage and Graphic modules. Here's a few things you can try to do:&lt;br /&gt;
&lt;br /&gt;
- Instead of drawing the image on the screen, draw it on the map at pixel 8200,8200, and make it so that you can fly over it with your ship.&lt;br /&gt;
&lt;br /&gt;
- Make your image have two frames instead of just a single one, and use a command &amp;quot;?switch&amp;quot; to change the frame of the image being displayed.&lt;br /&gt;
&lt;br /&gt;
- Add a command &amp;quot;?blend &amp;lt;int&amp;gt;&amp;quot; where &amp;lt;int&amp;gt; is an integer specifying the blend amount to use. Observe the effects of different blend values.&lt;br /&gt;
&lt;br /&gt;
[[Category:Discretion]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Discretion_Commands_and_Displaying_Images&amp;diff=5919</id>
		<title>Discretion Commands and Displaying Images</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Discretion_Commands_and_Displaying_Images&amp;diff=5919"/>
				<updated>2008-03-17T05:11:18Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: fixed internal link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a tutorial for module creation in [[Discretion]]. For other tutorials, see the [[Discretion Module Tutorial]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In this tutorial, you wil learn how to listen for chat commands using Discretion's Chat Module as well as how to load and display images on the screen using UniqueImage and Graphics.&lt;br /&gt;
&lt;br /&gt;
Topics covered: Listening for Callbacks, Using Interfaces, UniqueImage, Graphics&lt;br /&gt;
&lt;br /&gt;
We will make two commands, ?show and ?hide which will cause a graphic to appear and disappear on the screen.&lt;br /&gt;
&lt;br /&gt;
The first thing we'll do is make the graphic we want to display and put it in our Discretion/graphics folder. This can be done in a progam such as Paint. Here we saved the file as my_testimage.png.&lt;br /&gt;
[[Image:cg_1.PNG]]&lt;br /&gt;
&lt;br /&gt;
Now onto the code, make a module as specified in the [[Creating and Testing a Simple Discretion Module]]. The first thing we're going to do is listen to the callback when commands are sent through the chat. Callbacks in Discretion are similar to callbacks in AS3. They represent events that occur that you can react to. Callbacks are registered through the module manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
  * -	tells the module manager that you want to receive a callback&lt;br /&gt;
  * @param myVersion the version of the module requresting this callback, this is useful in&lt;br /&gt;
  * debugging if we were to cause a crash while we're in a callback&lt;br /&gt;
  * @param callbackName is a name string that will tell the module manager which callback you want &lt;br /&gt;
  * to receive &lt;br /&gt;
  * @param callbackVersion is the version string for the callback. If you use an antiquated version, &lt;br /&gt;
  * and a different version of the callback is called, an error will be recorded&lt;br /&gt;
  * @param func is a function pointer to a function that should be called when the callback occurs, &lt;br /&gt;
  * note that all callback functions are of the same form, but you can cast the parameter to a more &lt;br /&gt;
  * usable form. Donâ€™t change the param, as it must be used to call the other functions too&lt;br /&gt;
  */&lt;br /&gt;
void (*regCallback)(const char* myVersion, const char* callbackName, const char* callbackVersion, callbackFunc func);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we pass in myVersion, which is used only if there's a problem with your callback handler, so make it something that you will be able to recognise when it's printed to the console, such as &amp;quot;show-hide graphic module&amp;quot; or the interface handle if you have an interface defined, or even the C preprocessor macro __FILE__ will work. callbackName and callbackVersion are unique to the callback, more on that in a moment, func is the function to call when the callback occurs. callbackFunc is typedefed to a function pointer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
typedef void (*callbackFunc)(void* param);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In general, you can figure out information about the callback in the file where it's defined. For the command callback we're interested in, we look in Chat.h:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// occurs when a possible internal command is sent, if you're processing this command set processed to TRUE&lt;br /&gt;
#define CB_INTERNALCOMMAND				&amp;quot;InternalCommand&amp;quot;&lt;br /&gt;
#define CB_INTERNALCOMMAND_VERSION		&amp;quot;1&amp;quot;&lt;br /&gt;
// the parameter is as follows, set processed to TRUE if you process it&lt;br /&gt;
struct InternalCommandParam&lt;br /&gt;
{&lt;br /&gt;
	const char* command; // the entire command line, with parameters and everything, but no command character&lt;br /&gt;
	BOOL processed; // set this to true if you process the command&lt;br /&gt;
&lt;br /&gt;
	// you can use this function to check if this command is yours, sets processed for you&lt;br /&gt;
	// setToParams points to whatever's after the command if successful, can be NULL if you don't care&lt;br /&gt;
	BOOL isCommand(const char* what, const char** setToParams)&lt;br /&gt;
	{&lt;br /&gt;
	...&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here the callback name is defined to CB_INTERNALCOMMAND and callback version is defined to CB_INTERNALCOMMAND_VERSION. The parameter to the callback, which is a anonymous pointer (void*) can be cast to a InternalCommandParam*. We then use the isCommand to check if this is the command we're interested in.&lt;br /&gt;
&lt;br /&gt;
So now to register the internal command callback with the module manager and print out a message to the console when we receive &amp;quot;?show&amp;quot; or &amp;quot;?hide&amp;quot;. Note that we have to #include &amp;quot;Chat/Chat.h&amp;quot; because that's where the callback is defined.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Commands - Graphics Tutorial Discretion Module&lt;br /&gt;
#include &amp;quot;Module.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Chat/Chat.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ModuleManager* mm = 0;&lt;br /&gt;
&lt;br /&gt;
void gotInternalCommand(void* param)&lt;br /&gt;
{&lt;br /&gt;
	InternalCommandParam* icp = (InternalCommandParam*)param;&lt;br /&gt;
&lt;br /&gt;
	if (icp-&amp;gt;isCommand(&amp;quot;show&amp;quot;,0))&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Received Command: show\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	else if (icp-&amp;gt;isCommand(&amp;quot;hide&amp;quot;,0))&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Received Command: hide\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void* getClassInstance(void* _mm, LoadMode lm)&lt;br /&gt;
{&lt;br /&gt;
	mm = (ModuleManager*)_mm;&lt;br /&gt;
&lt;br /&gt;
	if (lm == LOADMODE_Init)&lt;br /&gt;
	{&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__, CB_INTERNALCOMMAND, CB_INTERNALCOMMAND_VERSION, gotInternalCommand);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
extern &amp;quot;C&amp;quot; &lt;br /&gt;
{&lt;br /&gt;
	EXPORT void* getInstance(void* mm, LoadMode lm)&lt;br /&gt;
	{&lt;br /&gt;
		return getClassInstance(mm,lm);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We should be able to make this module and see the effect when we type ?show and ?hide and press enter in the chat.&lt;br /&gt;
&lt;br /&gt;
[[Image:cg_2.PNG]]&lt;br /&gt;
&lt;br /&gt;
Now onto making an image display on the screen. There are two steps to this, loading the image, and drawing the image on the screen. Loading the image can be done in a few ways, the easiest is to use the UniqueImage module. The UniqueImage module loads settings from conf files, so you can refer to the image by name in the code. UniqueImage also ensures the image is only loaded once (it's unique), so that you can use the same image in different modules without worrying about wasting memory. Unique image will give you an image handle from an image name. An image handle is just an int, which we can pass to Graphics when we're drawing the image. First we'll define the image in the conf files. Open up Image.conf in conf/visual/ and add &amp;lt;Image Name&amp;gt;Path = &amp;lt;path to image&amp;gt; and &amp;lt;Image Name&amp;gt;Frames = (1, 1) to the bottom of the file. In the picture we use CommandsGraphicsTutorial as the name of our image... this is what we'll refer to the image in the code, just make sure it isn't the same as any of the other names. The Frams setting defines how many frames are in the image, for example ships are typcially defined in a single file with 40 images aranged 10 wide and 4 tall, so we'd use (10,4) for the frames if we had such an image. For our image though, we only use a single frame so (1, 1) is correct.&lt;br /&gt;
&lt;br /&gt;
[[Image:cg_3.PNG]]&lt;br /&gt;
&lt;br /&gt;
Now we have to get the UniqueImage interface and use it. Interfaces are generally loaded during LOADMODE_LoadInterfaces in getClassInstance. They are gotten using the interface identifier and the module manager. The interface identifier is defined in UniqueImage.h&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define I_UNIQUEIMAGE 	&amp;quot;UniqueImage-1&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To use this constant we need to #include &amp;quot;UniqueImage/UniqueImage.h&amp;quot;. In getClassInstance, if lm is LOADMODE_LoadInterfaces, we use the module manager to load the interface using the getInterface function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
  * -	tells the module manager that you want an interface. If the interface is not loaded by the &lt;br /&gt;
		module manager, an error will result which the module manager takes care of &lt;br /&gt;
  * -	this should be called when getInstance(MODE_LoadInterfaces) is called&lt;br /&gt;
  * @param myVersion the version of the module calling this function&lt;br /&gt;
  * @param getVersion the version of the module we want to load&lt;br /&gt;
  * @return a void* pointing to the class interface of the loaded module&lt;br /&gt;
  */&lt;br /&gt;
void* (*getInterface)(const char* myVersion, const char *getVersion);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here getVersion is I_UNIQUEIMAGE, myVersion, as in callbacks, is only used in case of errors. We can use __FILE__ or an identfying string like &amp;quot;commands-graphics tutorial&amp;quot;. We save the pointer returned by getInterface. The question now is when should we call UniqueImage's getImageHandle function. We want to make sure that we do not call it too early, because the image loading system may not be initialized. This problem is solved through callbacks. For loading images, there is a callback that says &amp;quot;the image loading system is initialized, load your images now&amp;quot;. This callback is in Graphics.h, CB_LoadImages.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
This LoadImage callback will be called when the images are to be loaded, there is no parameter&lt;br /&gt;
This is guarenteed to be in POSTLOAD_Interfaces&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define CB_LOADIMAGES			&amp;quot;LoadImages&amp;quot;&lt;br /&gt;
#define CB_LOADIMAGES_VERSION	&amp;quot;1&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So we register a callback for this function (and #include &amp;quot;Graphics/Graphics.h&amp;quot;), and load our image and save the image handle UniqueImage gives us.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Commands - Graphics Tutorial Discretion Module&lt;br /&gt;
#include &amp;quot;Module.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Chat/Chat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;UniqueImage/UniqueImage.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Graphics/Graphics.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ModuleManager* mm = 0;&lt;br /&gt;
UniqueImage* ui = 0;&lt;br /&gt;
&lt;br /&gt;
int imageHandle = 0;&lt;br /&gt;
&lt;br /&gt;
void gotInternalCommand(void* param)&lt;br /&gt;
{&lt;br /&gt;
	InternalCommandParam* icp = (InternalCommandParam*)param;&lt;br /&gt;
&lt;br /&gt;
	if (icp-&amp;gt;isCommand(&amp;quot;show&amp;quot;,0))&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Received Command: show\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	else if (icp-&amp;gt;isCommand(&amp;quot;hide&amp;quot;,0))&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Received Command: hide\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loadImages(void* param)&lt;br /&gt;
{&lt;br /&gt;
	imageHandle = ui-&amp;gt;getImageHandle(&amp;quot;CommandsGraphicsTutorial&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void* getClassInstance(void* _mm, LoadMode lm)&lt;br /&gt;
{&lt;br /&gt;
	mm = (ModuleManager*)_mm;&lt;br /&gt;
&lt;br /&gt;
	if (lm == LOADMODE_Init)&lt;br /&gt;
	{&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__, CB_INTERNALCOMMAND, CB_INTERNALCOMMAND_VERSION, gotInternalCommand);&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__, CB_LOADIMAGES, CB_LOADIMAGES_VERSION, loadImages);&lt;br /&gt;
	}&lt;br /&gt;
	else if (lm == LOADMODE_LoadInterfaces)&lt;br /&gt;
	{&lt;br /&gt;
		ui = (UniqueImage*)mm-&amp;gt;getInterface(__FILE__,I_UNIQUEIMAGE);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
extern &amp;quot;C&amp;quot; &lt;br /&gt;
{&lt;br /&gt;
	EXPORT void* getInstance(void* mm, LoadMode lm)&lt;br /&gt;
	{&lt;br /&gt;
		return getClassInstance(mm,lm);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that we have the image, we need to draw it on the screen. This is done using the Graphics interface. We get this interface similar to how we got the UniqueImage interface (in getClassInstance where lm == LOADMODE_LoadInterfaces). The function we're interested is one that draws images on the screen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Draw an image in the next frame, this is to be done in the prerender callback&lt;br /&gt;
  * This one draws relative to screen coordinates, rather than absolute coordinates, no bounds checking is done&lt;br /&gt;
  * @param imageHandle an image handle from the loadImage function&lt;br /&gt;
  * @param frame the frame of the image to draw on, for example the rotated ship graphic is 0-39&lt;br /&gt;
  * @param xPixel the xPixel to draw with, this in screen coordinates&lt;br /&gt;
  * @param yPixel the yPixel to draw with, this in screen coordinates&lt;br /&gt;
  * @param Layer the layer to draw on, probably from the enum Layer&lt;br /&gt;
  * @blend a number between 0 and 100 to determine how much blending is to be done for this image, &lt;br /&gt;
  *        so 0 is completely transparent and 100 is opaque&lt;br /&gt;
  */&lt;br /&gt;
void (*drawScreenImage)(int imageHandle, int xPixel, int yPixel, int frame, int layer, int blend);&lt;br /&gt;
void (*drawScreenImage2)(int imageHandle, int xPixel, int yPixel, int layer);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
imageHandle is the handle we got from UniqueImage, xPixel is the x pixel to use for the left part of the image, yPixel is the y pixel for the top of the image. (0, 0) is the upper left corner of the screen, with y increasing downward and x increasing rightward. Frame is the frame of the image to draw, for us this is 0 since we have only a single frame defined in our image. Layer is layer to draw on, some common ones are given in the enum Layer. Blend is the amount to blend the image, 100 for opaque images and fading to completely transparent when blend is 0. Here is the layer enum:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// The layer enum, note you can define your own layers between these ones if you want&lt;br /&gt;
enum Layer&lt;br /&gt;
{&lt;br /&gt;
	L_BelowAll = 50,&lt;br /&gt;
	L_Background = 100,&lt;br /&gt;
	L_AfterBackground = 150,&lt;br /&gt;
	L_Tiles = 200,&lt;br /&gt;
	L_AfterTiles = 250,&lt;br /&gt;
	L_Weapons = 300,&lt;br /&gt;
	L_AfterWeapons = 350,&lt;br /&gt;
	L_Ships = 400,&lt;br /&gt;
	L_AfterShips = 450,&lt;br /&gt;
	L_Gauges = 500,&lt;br /&gt;
	L_AfterGauges = 550,&lt;br /&gt;
	L_Chat = 600,&lt;br /&gt;
	L_AfterChat = 650,&lt;br /&gt;
	L_TopMost = 700&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The question now is when we should call drawScreenImage. The answer is, once again, in a callback. The callback in this case is in Graphics.h, PreRender:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// The parameter to the prerender callback&lt;br /&gt;
struct PrerenderParam&lt;br /&gt;
{&lt;br /&gt;
	PrerenderParam(int m, Rect* s) : milDif(m) , screen(s) {} &lt;br /&gt;
&lt;br /&gt;
	int milDif; // milliseconds since last prerender callback, or 0 on the first one&lt;br /&gt;
	Rect* screen; // the screen bounds, in pixels&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// The prerender callback&lt;br /&gt;
#define CB_PRERENDER			&amp;quot;Pre-render&amp;quot;&lt;br /&gt;
#define CB_PRERENDER_VERSION	&amp;quot;2&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
This callback occurs every frame, when we call drawScreenImage, it will get drawn for a single frame. We register the callback like we did for LoadImages and InternalCommand. We then call drawScreenImage based on whether the user has used ?show or not. The final version the code is below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Commands - Graphics Tutorial Discretion Module&lt;br /&gt;
#include &amp;quot;Module.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Chat/Chat.h&amp;quot;&lt;br /&gt;
#include &amp;quot;UniqueImage/UniqueImage.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Graphics/Graphics.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ModuleManager* mm = 0;&lt;br /&gt;
UniqueImage* ui = 0;&lt;br /&gt;
Graphics* g = 0;&lt;br /&gt;
&lt;br /&gt;
int imageHandle = 0;&lt;br /&gt;
bool showImage = false;&lt;br /&gt;
&lt;br /&gt;
void gotInternalCommand(void* param)&lt;br /&gt;
{&lt;br /&gt;
	InternalCommandParam* icp = (InternalCommandParam*)param;&lt;br /&gt;
&lt;br /&gt;
	if (icp-&amp;gt;isCommand(&amp;quot;show&amp;quot;,0))&lt;br /&gt;
	{&lt;br /&gt;
		showImage = true;&lt;br /&gt;
	}&lt;br /&gt;
	else if (icp-&amp;gt;isCommand(&amp;quot;hide&amp;quot;,0))&lt;br /&gt;
	{&lt;br /&gt;
		showImage = false;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loadImages(void* param)&lt;br /&gt;
{&lt;br /&gt;
	imageHandle = ui-&amp;gt;getImageHandle(&amp;quot;CommandsGraphicsTutorial&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void preRender(void* param)&lt;br /&gt;
{&lt;br /&gt;
	if (showImage)&lt;br /&gt;
	{&lt;br /&gt;
		g-&amp;gt;drawScreenImage2(imageHandle, 200, 200, L_TopMost);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void* getClassInstance(void* _mm, LoadMode lm)&lt;br /&gt;
{&lt;br /&gt;
	mm = (ModuleManager*)_mm;&lt;br /&gt;
&lt;br /&gt;
	if (lm == LOADMODE_Init)&lt;br /&gt;
	{&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__, CB_INTERNALCOMMAND, CB_INTERNALCOMMAND_VERSION, gotInternalCommand);&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__, CB_LOADIMAGES, CB_LOADIMAGES_VERSION, loadImages);&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__, CB_PRERENDER, CB_PRERENDER_VERSION, preRender);&lt;br /&gt;
	}&lt;br /&gt;
	else if (lm == LOADMODE_LoadInterfaces)&lt;br /&gt;
	{&lt;br /&gt;
		ui = (UniqueImage*)mm-&amp;gt;getInterface(__FILE__,I_UNIQUEIMAGE);&lt;br /&gt;
		g = (Graphics*)mm-&amp;gt;getInterface(__FILE__,I_GRAPHICS);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
extern &amp;quot;C&amp;quot; &lt;br /&gt;
{&lt;br /&gt;
	EXPORT void* getInstance(void* mm, LoadMode lm)&lt;br /&gt;
	{&lt;br /&gt;
		return getClassInstance(mm,lm);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And when we run this module in Discretion we get the desired result:&lt;br /&gt;
&lt;br /&gt;
[[Image:cg_4.PNG]]&lt;br /&gt;
&lt;br /&gt;
Hopefully, by now you are comfortable with listening to callbacks and using interfaces as well as more familiar with the UniqueImage and Graphic modules. Here's a few things you can try to do:&lt;br /&gt;
&lt;br /&gt;
- Instead of drawing the image on the screen, draw it on the map at pixel 8200,8200, and make it so that you can fly over it with your ship.&lt;br /&gt;
&lt;br /&gt;
- Make your image have two frames instead of just a single one, and use a command &amp;quot;?switch&amp;quot; to change the frame of the image being displayed.&lt;br /&gt;
&lt;br /&gt;
- Add a command &amp;quot;?blend &amp;lt;int&amp;gt;&amp;quot; where &amp;lt;int&amp;gt; is an integer specifying the blend amount to use. Observe the effects of different blend values.&lt;br /&gt;
&lt;br /&gt;
[[Category:Discretion]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_MS_Visual_Studio&amp;diff=5918</id>
		<title>Creating and Testing a Simple Discretion Module in MS Visual Studio</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_MS_Visual_Studio&amp;diff=5918"/>
				<updated>2008-03-17T05:09:59Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: updates&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a tutorial for module creation in [[Discretion]]. For other tutorials, see the [[Discretion Module Tutorial]].&lt;br /&gt;
&lt;br /&gt;
Making a module is easy pie once you know what to do, so let's get to it.&lt;br /&gt;
&lt;br /&gt;
==Windows with MSVC==&lt;br /&gt;
&lt;br /&gt;
First step: make a new VS.net C++ Project. &lt;br /&gt;
&lt;br /&gt;
1. File -&amp;gt; New Project&lt;br /&gt;
&lt;br /&gt;
2. Win32 Console Project&lt;br /&gt;
&lt;br /&gt;
3. Give your project a name (&amp;quot;TestModule&amp;quot; in the picture)&lt;br /&gt;
&lt;br /&gt;
4. Press Ok&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module1.PNG]]&lt;br /&gt;
&lt;br /&gt;
5. Click on application settings on the left &lt;br /&gt;
&lt;br /&gt;
6. Click DLL from the list of radio buttons&lt;br /&gt;
&lt;br /&gt;
7. Press the Empty Project checkbox&lt;br /&gt;
&lt;br /&gt;
8. Press Finish&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module2.PNG]]&lt;br /&gt;
&lt;br /&gt;
9. File -&amp;gt; Add New Item&lt;br /&gt;
&lt;br /&gt;
10. Select C++ Source File (.cpp)&lt;br /&gt;
&lt;br /&gt;
11. Name your source file (&amp;quot;testmodule.cpp&amp;quot; in the picture)&lt;br /&gt;
&lt;br /&gt;
12. Press Open&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module3.PNG]]&lt;br /&gt;
&lt;br /&gt;
13. Paste the following code into your source file&lt;br /&gt;
&amp;lt;pre&amp;gt;// Sample Discretion Module Source File&lt;br /&gt;
#include &amp;quot;Module.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void* getClassInstance(void* _mm, LoadMode lm)&lt;br /&gt;
{&lt;br /&gt;
	if (lm == LOADMODE_Init)&lt;br /&gt;
		printf(&amp;quot;Test Module Initialized\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
extern &amp;quot;C&amp;quot; &lt;br /&gt;
{&lt;br /&gt;
	EXPORT void* getInstance(void* mm, LoadMode lm)&lt;br /&gt;
	{&lt;br /&gt;
		return getClassInstance(mm,lm);&lt;br /&gt;
	}&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
14. Right Click your project in the Solution Explorer and go to Properties (You can also access this through the Project Menu, Project -&amp;gt; Properties)&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module4.PNG]]&lt;br /&gt;
&lt;br /&gt;
15. In the properties window, from the drop down menu select &amp;quot;All Configurations&amp;quot;&lt;br /&gt;
&lt;br /&gt;
16. Select C++, General from the tree view on the left&lt;br /&gt;
&lt;br /&gt;
17. Type the directory to the Modules directory (the one with Module.h in it, not the one with only .dlls!) that comes with the full version of Discretion in the Additional Include Directory property (&amp;quot;E:/client/modules&amp;quot; in the picture)&lt;br /&gt;
&lt;br /&gt;
18. Press Ok&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module5.PNG]]&lt;br /&gt;
&lt;br /&gt;
19. Go to Buld -&amp;gt; Build &amp;lt;project name&amp;gt; (&amp;quot;TestModule&amp;quot; in the pictue)&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module6.PNG]]&lt;br /&gt;
&lt;br /&gt;
If all goes well, you code should compile and a .dll should be produced that is a Discretion module! Now let's put the module into Discretion to see it at work. &lt;br /&gt;
&lt;br /&gt;
20. Copy the produced .dll into your Discretion executable's Module folder (the one with the .dlls in it, not the one with Module.h in it).&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module7.PNG]]&lt;br /&gt;
&lt;br /&gt;
21. Edit conf/MAIN.CONF with a program such as Notepad&lt;br /&gt;
&lt;br /&gt;
22. Add the name of your dll to the Modules::Names setting (it's a comma seperated list of module names, order doesn't matter)&lt;br /&gt;
&lt;br /&gt;
23. Save the file&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module8.PNG]]&lt;br /&gt;
&lt;br /&gt;
24. Run Discretion through the terminal (start -&amp;gt; run -&amp;gt; cmd), Select &amp;quot;Single Player&amp;quot; (if you don't run it through the terminal you're likely to not see any console output, even though the module will be loaded).&lt;br /&gt;
&lt;br /&gt;
25. Observe your modules initialization in the console window&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module9.PNG]]&lt;br /&gt;
&lt;br /&gt;
Now you might say, rightfully so, that this module doesn't do anything. The way to do real things in Discretion is by using other modules. Want to react to user key presses? Use the KeyControls module. Want to display some images? Use the Graphics module. I'll gladly write additional tutorials for how to use each of these as needed. Tell me what you want to do and I'll write a tutorial with how to use the existing modules to accomplish what you want to do.&lt;br /&gt;
&lt;br /&gt;
[[Category:Discretion]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module&amp;diff=5917</id>
		<title>Creating and Testing a Simple Discretion Module</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module&amp;diff=5917"/>
				<updated>2008-03-17T05:07:41Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: /* Microsoft Visual Studio */ wording&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Once you obtain the [[Discretion]] source, you are ready to make a module for Discretion. If you haven't gotten the source yet, follow the instructions in [[Obtaining the Discretion Source using Subversion]]. This tutorial is part of the [[Discretion Module Tutorial]].&lt;br /&gt;
&lt;br /&gt;
There are three ways to make a module: 1. Eclipse with minGW, 2. MS Visual Studio, and 3. make. If you're new, the recommended way is to use minGW and Eclipse.&lt;br /&gt;
&lt;br /&gt;
== minGW and Eclipse ==&lt;br /&gt;
The way [[User:BaK|BaK]] works on Discretion is using minGW and Eclipse. Both pieces of software are free, and minGW is a lot like gcc so this might even work for Linux development. Eclipse is also BaK's favorite Integrated Development Environment (IDE). Currently the tutorial is oriented towards Windows users. If you want to try this method see the [[Creating and Testing a Simple Discretion Module in Eclipse]] tutorial.&lt;br /&gt;
&lt;br /&gt;
== Microsoft Visual Studio ==&lt;br /&gt;
Microsoft Visual Studio is an IDE produced by Microsoft that supports C++ development. I've used it for a few years and it's pretty good at what it does. Students also often get free licenses for Visual Studio from their school. Currently for Discretion, development is done in Eclipse so there aren't any visual studio projects for you to use. Nonetheless, setting one up is a snap and is covered in the [[Creating and Testing a Simple Discretion Module in MS Visual Studio]] tutorial.&lt;br /&gt;
&lt;br /&gt;
== Make ==&lt;br /&gt;
Make is a tool that can build large projects. It relies on a compiler such as gcc. This one is typically used by the hardcore linux users, but it's also a very portable tool so it works great with multi-platform development. [[Goldeye]] is currently in charge of development using make (particularly interested in Mac OS X support), and may one day make (pun!) a [[Creating and Testing a Simple Discretion Module using Make]] tutorial. Send him a ?message in-game so he knows you appreciate him working on this and encourage him to write a tutorial for us!&lt;br /&gt;
&lt;br /&gt;
== Others ==&lt;br /&gt;
Outside of these three standard ways there are countless compilers and IDEs you can use to make any C++ project, including Discretion. However, officially we won't help you with these. Unofficially we probably will if you bug us enough ;).&lt;br /&gt;
&lt;br /&gt;
[[Category:Discretion]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5916</id>
		<title>Obtaining the Discretion Source using Subversion</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5916"/>
				<updated>2008-03-17T05:06:08Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: grammar&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how to obtain the Discretion source code using subversion. It assumes you know nothing and have no tools already installed. It is part of the [[Discretion Module Tutorial]]. It assumes you are using Windows, although the process for other operating systems is very similar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Subversion is a version control system which allows many programmers to incrementally and concurrently work on a project. Basically it is a common way of organizing large projects superior to the &amp;quot;e-mail your changes to everyone&amp;quot; method. It also has lots of other nifty tricks which aren't important for right now.&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
The tutorial video can be obtained [http://ews.uiuc.edu/~sbak2/disc/disc_svn.wmv here].&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
svn link: [http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91|download subversion]&lt;br /&gt;
&lt;br /&gt;
discretion repository link: https://ss-discretion.svn.sourceforge.net/svnroot/ss-discretion/client/trunk&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_Eclipse&amp;diff=5915</id>
		<title>Creating and Testing a Simple Discretion Module in Eclipse</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_Eclipse&amp;diff=5915"/>
				<updated>2008-03-17T05:00:52Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: /* Videos */ video links added&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how anyone can using minGW (and probably g++) and Eclipse to compile a simple module and put get it to run on [[Discretion]]. It assumes you're using Windows (although g++ may work) and you don't have any tools installed. However, you should have already gotten the source code (if not see the [[Obtaining the Discretion Source using Subversion]] tutorial). This tutorial is part of a series of tutorials consisting of the [[Discretion Module Tutorial]].&lt;br /&gt;
&lt;br /&gt;
minGW stands for minimalistic Gnu for Windows. It is an open source complier almost identical to gcc and g++, which are the compilers used for linux, among other things. The compiler produces native Windows exectuables, and best of all it's free! However, its interface isn't the best for the novice user. Thus, we use eclipse to help manage the minGW compiler for us.&lt;br /&gt;
&lt;br /&gt;
Eclipse, is an integrated development environment (IDE) which is also open-source and free. It is basically a program that makes it easier to make other programs. It was originally designed for Java development, but people made plugins to allow C++ development. These extensions are called the CDT (C/C++ Development Tooling). The CDT integrates nicely with minGW so these two make a good match. Discretion's modules come with Eclipse Projects when you get the source so modifications are easy to make. Eclipse is implemented in Java, so in order to use it you need the Java Runtime Environment. The good news is you probably already have this installed. Nonetheless, the tutorial covers downloading it if you don't already have it installed.&lt;br /&gt;
&lt;br /&gt;
==Videos==&lt;br /&gt;
&lt;br /&gt;
This tutorial is divided a few parts:&lt;br /&gt;
* [http://ews.uiuc.edu/~sbak2/disc/disc_mingw.wmv Obtaining and Testing minGW]&lt;br /&gt;
* [http://ews.uiuc.edu/~sbak2/disc/disc_jre.wmv Getting the Java Runtime Environment] (90% of people can skip this step)&lt;br /&gt;
* [http://ews.uiuc.edu/~sbak2/disc/disc_eclipse.wmv Downloading Eclipse with CDT]&lt;br /&gt;
* [http://ews.uiuc.edu/~sbak2/disc/disc_simplemod.wmv Creating and Testing a Simple Module within Discretion]&lt;br /&gt;
* [http://ews.uiuc.edu/~sbak2/disc/disc_tricks.wmv Discretion with Eclipse Tricks and Tips]&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
&lt;br /&gt;
minGW: [http://sourceforge.net/project/showfiles.php?group_id=2435 Sourceforge File List]&lt;br /&gt;
&lt;br /&gt;
java runtime environment: [http://java.sun.com/javase/downloads/?intcmp=1281 Downloads]&lt;br /&gt;
&lt;br /&gt;
eclipse: [http://www.eclipse.org/downloads/ Eclipse Downloads]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5914</id>
		<title>Obtaining the Discretion Source using Subversion</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5914"/>
				<updated>2008-03-17T04:58:51Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: wiki format&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how to obtain the Discretion source code using subversion. It assumes you know nothing and have no tools already installed. It is part of the [[Discretion Module Tutorial]]. It assumes you are using Windows, although the process for other operating systems is very similar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Subversion is a version control system which allows many programmers to incrementally and concurrently work on a project. Basically is a common way of organizing large projects superior to the &amp;quot;e-mail your changes to everyone&amp;quot; method. It also has lots of other nifty tricks which aren't important for right now.&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
The tutorial video can be obtained [http://ews.uiuc.edu/~sbak2/disc/disc_svn.wmv here].&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
svn link: [http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91|download subversion]&lt;br /&gt;
&lt;br /&gt;
discretion repository link: https://ss-discretion.svn.sourceforge.net/svnroot/ss-discretion/client/trunk&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5913</id>
		<title>Obtaining the Discretion Source using Subversion</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5913"/>
				<updated>2008-03-17T04:58:28Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: way to not allow .wmv uploads :( [changed to external link]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how to obtain the Discretion source code using subversion. It assumes you know nothing and have no tools already installed. It is part of the [[Discretion Module Tutorial]]. It assumes you are using Windows, although the process for other operating systems is very similar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Subversion is a version control system which allows many programmers to incrementally and concurrently work on a project. Basically is a common way of organizing large projects superior to the &amp;quot;e-mail your changes to everyone&amp;quot; method. It also has lots of other nifty tricks which aren't important for right now.&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
The tutorial video can be obtained [http://ews.uiuc.edu/~sbak2/disc/disc_svn.wmv|here].&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
svn link: [http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91|download subversion]&lt;br /&gt;
&lt;br /&gt;
discretion repository link: https://ss-discretion.svn.sourceforge.net/svnroot/ss-discretion/client/trunk&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5912</id>
		<title>Obtaining the Discretion Source using Subversion</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5912"/>
				<updated>2008-03-17T04:40:15Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: /* Video */ added vid link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how to obtain the Discretion source code using subversion. It assumes you know nothing and have no tools already installed. It is part of the [[Discretion Module Tutorial]]. It assumes you are using Windows, although the process for other operating systems is very similar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Subversion is a version control system which allows many programmers to incrementally and concurrently work on a project. Basically is a common way of organizing large projects superior to the &amp;quot;e-mail your changes to everyone&amp;quot; method. It also has lots of other nifty tricks which aren't important for right now.&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
The tutorial video can be obtained [[Media:Disc_svn.wmv|here]].&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
svn link: [http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91|download subversion]&lt;br /&gt;
&lt;br /&gt;
discretion repository link: https://ss-discretion.svn.sourceforge.net/svnroot/ss-discretion/client/trunk&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_Eclipse&amp;diff=5911</id>
		<title>Creating and Testing a Simple Discretion Module in Eclipse</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_Eclipse&amp;diff=5911"/>
				<updated>2008-03-16T19:11:13Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: /* Links */  fixed&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how anyone can using minGW (and probably g++) and Eclipse to compile a simple module and put get it to run on [[Discretion]]. It assumes you're using Windows (although g++ may work) and you don't have any tools installed. However, you should have already gotten the source code (if not see the [[Obtaining the Discretion Source using Subversion]] tutorial). This tutorial is part of a series of tutorials consisting of the [[Discretion Module Tutorial]].&lt;br /&gt;
&lt;br /&gt;
minGW stands for minimalistic Gnu for Windows. It is an open source complier almost identical to gcc and g++, which are the compilers used for linux, among other things. The compiler produces native Windows exectuables, and best of all it's free! However, its interface isn't the best for the novice user. Thus, we use eclipse to help manage the minGW compiler for us.&lt;br /&gt;
&lt;br /&gt;
Eclipse, is an integrated development environment (IDE) which is also open-source and free. It is basically a program that makes it easier to make other programs. It was originally designed for Java development, but people made plugins to allow C++ development. These extensions are called the CDT (C/C++ Development Tooling). The CDT integrates nicely with minGW so these two make a good match. Discretion's modules come with Eclipse Projects when you get the source so modifications are easy to make. Eclipse is implemented in Java, so in order to use it you need the Java Runtime Environment. The good news is you probably already have this installed. Nonetheless, the tutorial covers downloading it if you don't already have it installed.&lt;br /&gt;
&lt;br /&gt;
==Videos==&lt;br /&gt;
&lt;br /&gt;
This tutorial is divided a few parts:&lt;br /&gt;
* Obtaining and Testing minGW&lt;br /&gt;
* Getting the Java Runtime Environment (90% of people can skip this step)&lt;br /&gt;
* Downloading Eclipse with CDT&lt;br /&gt;
* Creating and Testing a Simple Module within Discretion&lt;br /&gt;
* Discretion with Eclipse Tricks and Tips&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
&lt;br /&gt;
minGW: [http://sourceforge.net/project/showfiles.php?group_id=2435 Sourceforge File List]&lt;br /&gt;
&lt;br /&gt;
java runtime environment: [http://java.sun.com/javase/downloads/?intcmp=1281 Downloads]&lt;br /&gt;
&lt;br /&gt;
eclipse: [http://www.eclipse.org/downloads/ Eclipse Downloads]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_Eclipse&amp;diff=5910</id>
		<title>Creating and Testing a Simple Discretion Module in Eclipse</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_Eclipse&amp;diff=5910"/>
				<updated>2008-03-16T18:14:23Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: removed code&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how anyone can using minGW (and probably g++) and Eclipse to compile a simple module and put get it to run on [[Discretion]]. It assumes you're using Windows (although g++ may work) and you don't have any tools installed. However, you should have already gotten the source code (if not see the [[Obtaining the Discretion Source using Subversion]] tutorial). This tutorial is part of a series of tutorials consisting of the [[Discretion Module Tutorial]].&lt;br /&gt;
&lt;br /&gt;
minGW stands for minimalistic Gnu for Windows. It is an open source complier almost identical to gcc and g++, which are the compilers used for linux, among other things. The compiler produces native Windows exectuables, and best of all it's free! However, its interface isn't the best for the novice user. Thus, we use eclipse to help manage the minGW compiler for us.&lt;br /&gt;
&lt;br /&gt;
Eclipse, is an integrated development environment (IDE) which is also open-source and free. It is basically a program that makes it easier to make other programs. It was originally designed for Java development, but people made plugins to allow C++ development. These extensions are called the CDT (C/C++ Development Tooling). The CDT integrates nicely with minGW so these two make a good match. Discretion's modules come with Eclipse Projects when you get the source so modifications are easy to make. Eclipse is implemented in Java, so in order to use it you need the Java Runtime Environment. The good news is you probably already have this installed. Nonetheless, the tutorial covers downloading it if you don't already have it installed.&lt;br /&gt;
&lt;br /&gt;
==Videos==&lt;br /&gt;
&lt;br /&gt;
This tutorial is divided a few parts:&lt;br /&gt;
* Obtaining and Testing minGW&lt;br /&gt;
* Getting the Java Runtime Environment (90% of people can skip this step)&lt;br /&gt;
* Downloading Eclipse with CDT&lt;br /&gt;
* Creating and Testing a Simple Module within Discretion&lt;br /&gt;
* Discretion with Eclipse Tricks and Tips&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
&lt;br /&gt;
minGW: [http://sourceforge.net/project/showfiles.php?group_id=2435|Sourceforge File List]&lt;br /&gt;
&lt;br /&gt;
java runtime environment: [http://java.sun.com/javase/downloads/?intcmp=1281|Java Downloads]&lt;br /&gt;
&lt;br /&gt;
eclipse: [http://www.eclipse.org/downloads/|Eclipse Downloads]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_Eclipse&amp;diff=5909</id>
		<title>Creating and Testing a Simple Discretion Module in Eclipse</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_Eclipse&amp;diff=5909"/>
				<updated>2008-03-16T18:13:59Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: added a step&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how anyone can using minGW (and probably g++) and Eclipse to compile a simple module and put get it to run on [[Discretion]]. It assumes you're using Windows (although g++ may work) and you don't have any tools installed. However, you should have already gotten the source code (if not see the [[Obtaining the Discretion Source using Subversion]] tutorial). This tutorial is part of a series of tutorials consisting of the [[Discretion Module Tutorial]].&lt;br /&gt;
&lt;br /&gt;
minGW stands for minimalistic Gnu for Windows. It is an open source complier almost identical to gcc and g++, which are the compilers used for linux, among other things. The compiler produces native Windows exectuables, and best of all it's free! However, its interface isn't the best for the novice user. Thus, we use eclipse to help manage the minGW compiler for us.&lt;br /&gt;
&lt;br /&gt;
Eclipse, is an integrated development environment (IDE) which is also open-source and free. It is basically a program that makes it easier to make other programs. It was originally designed for Java development, but people made plugins to allow C++ development. These extensions are called the CDT (C/C++ Development Tooling). The CDT integrates nicely with minGW so these two make a good match. Discretion's modules come with Eclipse Projects when you get the source so modifications are easy to make. Eclipse is implemented in Java, so in order to use it you need the Java Runtime Environment. The good news is you probably already have this installed. Nonetheless, the tutorial covers downloading it if you don't already have it installed.&lt;br /&gt;
&lt;br /&gt;
==Videos==&lt;br /&gt;
&lt;br /&gt;
This tutorial is divided a few parts:&lt;br /&gt;
* Obtaining and Testing minGW&lt;br /&gt;
* Getting the Java Runtime Environment (90% of people can skip this step)&lt;br /&gt;
* Downloading Eclipse with CDT&lt;br /&gt;
* Creating and Testing a Simple Module within Discretion&lt;br /&gt;
* Discretion with Eclipse Tricks and Tips&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
&lt;br /&gt;
minGW: [http://sourceforge.net/project/showfiles.php?group_id=2435|Sourceforge File List]&lt;br /&gt;
&lt;br /&gt;
java runtime environment: [http://java.sun.com/javase/downloads/?intcmp=1281|Java Downloads]&lt;br /&gt;
&lt;br /&gt;
eclipse: [http://www.eclipse.org/downloads/|Eclipse Downloads]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;pre&amp;gt;// Sample Discretion Module Source File&lt;br /&gt;
#include &amp;quot;Module.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void* getClassInstance(void* _mm, LoadMode lm)&lt;br /&gt;
{&lt;br /&gt;
	if (lm == LOADMODE_Init)&lt;br /&gt;
		printf(&amp;quot;Test Module Initialized\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
extern &amp;quot;C&amp;quot; &lt;br /&gt;
{&lt;br /&gt;
	EXPORT void* getInstance(void* mm, LoadMode lm)&lt;br /&gt;
	{&lt;br /&gt;
		return getClassInstance(mm,lm);&lt;br /&gt;
	}&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Listening_for_Key_Presses,_Displaying_Text,_and_Per_Player_Data&amp;diff=5908</id>
		<title>Listening for Key Presses, Displaying Text, and Per Player Data</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Listening_for_Key_Presses,_Displaying_Text,_and_Per_Player_Data&amp;diff=5908"/>
				<updated>2008-03-16T07:10:56Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: added eclipse solution to linking problem&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a tutorial for module creation in [[Discretion]]. For other tutorials, see the [[Discretion Module Tutorial]].&lt;br /&gt;
&lt;br /&gt;
The purpose of this tutorial is to explain how to 1) display text on the screen with the Text module, 2) show how to access shared per player data, 3) listen and act upon key presses in Discretion, and 4) show how to register and use local per player data. You are assumed to know how to create and load a basic module, as well as how to use interfaces and callbacks. If you don't know how to do this, do the corresponding [[Discretion Module Tutorial]].&lt;br /&gt;
&lt;br /&gt;
We shall construct a module that displays the currently ticked (in the playerlist) player's name, squad, or frequency. The user will be able to press the ALT key to cycle between these attributes. The module will also keep track of how many times the user has pressed alt for each player.&lt;br /&gt;
&lt;br /&gt;
So for example, consider a case where there's two players in the arena, tux(the user) on freq 0 and squad &amp;quot;Killers&amp;quot;, and BaK on freq 1 on squad &amp;quot;BakAttak&amp;quot;. Initially the player himself is ticked. The screen will say &amp;quot;Name: tux (Switched 0 times)&amp;quot;. The player can then select the next player on the playerlist using page down. After the user presses page down, the screen says &amp;quot;Name: BaK (Switched 0 times)&amp;quot;. The user can then press the alt key and the screen switches to &amp;quot;Squad: BakAttak (Switched 1 time)&amp;quot;. If the user than presses alt again it switched the text to &amp;quot;Freq: 1 (Switched 2 times)&amp;quot;. If the user presses page up it goes back to &amp;quot;Name: tux (Switched 0 times)&amp;quot;. Alt will then yield the text &amp;quot;Squad: Killers (Switched 1 time)&amp;quot;. Page down will go back to &amp;quot;Freq: 1 (Switched 2 times)&amp;quot;. Alt again will give us &amp;quot;Name: Bak (Switched 3 times)&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
So let's work off a basic module template:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Discretion Tutorial, goals:&lt;br /&gt;
// 1) display text on the screen with the Text module &lt;br /&gt;
// 2) show how to access shared per player data&lt;br /&gt;
// 3) listen and act upon key presses in Discretion&lt;br /&gt;
// 4) show how to register and use local per player data.&lt;br /&gt;
// April 2007&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;Module.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ModuleManager* mm = 0;&lt;br /&gt;
&lt;br /&gt;
void* getClassInstance(void* _mm, LoadMode lm)&lt;br /&gt;
{&lt;br /&gt;
	mm = (ModuleManager*)_mm;&lt;br /&gt;
&lt;br /&gt;
	if (lm == LOADMODE_Init)&lt;br /&gt;
	{&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
extern &amp;quot;C&amp;quot; &lt;br /&gt;
{&lt;br /&gt;
	EXPORT void* getInstance(void* mm, LoadMode lm)&lt;br /&gt;
	{&lt;br /&gt;
		return getClassInstance(mm,lm);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Let's display some text on the screen using the Text module. The text module can display text on the screen or on the map, on any layer. These layers are the same layers that are used to display images. The function we are interested in is displayTextScreen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Display this text for one frame, call during prerender, this in is screen coordinates&lt;br /&gt;
 * @param line the line of text to display&lt;br /&gt;
 * @param color the color string to display&lt;br /&gt;
 * @param layer the layer to display it on&lt;br /&gt;
 * @param topLeft the top left corner of where we should start drawing&lt;br /&gt;
 * @param blend how much to blend the text, 0 = transparent, 100 = opaque&lt;br /&gt;
 */&lt;br /&gt;
void (*displayTextScreen)(const char* line, const char* color, int layer, const Point* topLeft, int blend);&lt;br /&gt;
void (*displayTextScreen2)(const char* line, const char* color, int layer, const Point* topLeft);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So as in the images tutorial, we register a callback to CB_PRERENDER, which is when we call displayTextScreen2 to display the actual text. We also get the Text interface. Then, during the prerender callback, we call displayTextScreen2, which will display the text we want on the screen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Discretion Tutorial, goals:&lt;br /&gt;
// 1) display text on the screen with the Text module &lt;br /&gt;
// 2) show how to access shared per player data&lt;br /&gt;
// 3) listen and act upon key presses in Discretion&lt;br /&gt;
// 4) show how to register and use local per player data.&lt;br /&gt;
// April 2007&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;Module.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Text/Text.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Graphics/Graphics.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ModuleManager* mm = 0;&lt;br /&gt;
Text* t = 0;&lt;br /&gt;
&lt;br /&gt;
void preRender(void* param)&lt;br /&gt;
{&lt;br /&gt;
	Point topLeft(400,200);&lt;br /&gt;
&lt;br /&gt;
	t-&amp;gt;displayTextScreen2(&amp;quot;test string&amp;quot;, &amp;quot;yellow&amp;quot;, L_Chat, &amp;amp;topLeft);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void* getClassInstance(void* _mm, LoadMode lm)&lt;br /&gt;
{&lt;br /&gt;
	mm = (ModuleManager*)_mm;&lt;br /&gt;
&lt;br /&gt;
	if (lm == LOADMODE_LoadInterfaces)&lt;br /&gt;
	{&lt;br /&gt;
		t = (Text*)mm-&amp;gt;getInterface(__FILE__, I_TEXT);&lt;br /&gt;
&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__,CB_PRERENDER, CB_PRERENDER_VERSION, &amp;amp;preRender);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
extern &amp;quot;C&amp;quot; &lt;br /&gt;
{&lt;br /&gt;
	EXPORT void* getInstance(void* mm, LoadMode lm)&lt;br /&gt;
	{&lt;br /&gt;
		return getClassInstance(mm,lm);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see how we could use the text module to display various strings at various layers. Running this code makes the module display the string &amp;quot;test string&amp;quot; at position 400, 200:&lt;br /&gt;
&lt;br /&gt;
[[Image:Ss1.PNG]]&lt;br /&gt;
&lt;br /&gt;
Next, we want to be able to get data about the players. This data is stored as shared Per Player Data. This is gotten using the PerPlayerData interface's getSharedData function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
  * Get data that was shared by other modules with registerSharedData&lt;br /&gt;
  * @param pid the player's id we're concerned with&lt;br /&gt;
  * @param dataName the unique name of the data we want&lt;br /&gt;
  * @return a void* to the data we want. See the module documentation for the correct name and type&lt;br /&gt;
  */&lt;br /&gt;
void* (*getSharedData)(int pid, const char* dataName);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The parameter dataName refers to the name of the data, in this case &amp;quot;name&amp;quot;, &amp;quot;squad&amp;quot;, and &amp;quot;freq&amp;quot;. There currently isn't a global list of common shared data anywhere, but such a list probably will be made at some point.&lt;br /&gt;
&lt;br /&gt;
We can get the ticked player's id number using the PlayerList interface. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Get the Pid of the currently targeted player&lt;br /&gt;
 * @return the pid of the player currently &amp;quot;ticked&amp;quot; in the player list box&lt;br /&gt;
 */&lt;br /&gt;
int (*getTargetPID)();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now once we get the shared data, we receive a void*, which is a pointer that can point to any type of data. Again, a global list of common shared data types isn't yet available, so trust me that getting &amp;quot;name&amp;quot; will give you data of type char*, &amp;quot;squad&amp;quot; will get you data of type char*, and &amp;quot;freq&amp;quot; gets you data of type int*. With a pointer to the data you can modify the data, and this is the mechanism for doing that. You should cast the void* to the proper type of pointer, then use that pointer to get/set the data as one would with a normal pointer.&lt;br /&gt;
&lt;br /&gt;
So in our tutorial, in our prerender callback, we get the ticked player's id from the playerlist, use that with PerPlayerData to get the name of the ticked player, and display that on the screen using the Text Module.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Discretion Tutorial, goals:&lt;br /&gt;
// 1) display text on the screen with the Text module &lt;br /&gt;
// 2) show how to access shared per player data&lt;br /&gt;
// 3) listen and act upon key presses in Discretion&lt;br /&gt;
// 4) show how to register and use local per player data.&lt;br /&gt;
// April 2007&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;Module.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Text/Text.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Graphics/Graphics.h&amp;quot;&lt;br /&gt;
#include &amp;quot;PerPlayerData/PerPlayerData.h&amp;quot;&lt;br /&gt;
#include &amp;quot;PlayerList/PlayerList.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ModuleManager* mm = 0;&lt;br /&gt;
PerPlayerData* ppd = 0;&lt;br /&gt;
PlayerList* pl = 0;&lt;br /&gt;
Text* t = 0;&lt;br /&gt;
&lt;br /&gt;
void preRender(void* param)&lt;br /&gt;
{&lt;br /&gt;
	Point topLeft(400,200);&lt;br /&gt;
	int ticked_pid = pl-&amp;gt;getTargetPID();&lt;br /&gt;
	char* playerName = (char*)ppd-&amp;gt;getSharedData(ticked_pid, &amp;quot;name&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	t-&amp;gt;displayTextScreen2(playerName, &amp;quot;yellow&amp;quot;, L_Chat, &amp;amp;topLeft);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void* getClassInstance(void* _mm, LoadMode lm)&lt;br /&gt;
{&lt;br /&gt;
	mm = (ModuleManager*)_mm;&lt;br /&gt;
&lt;br /&gt;
	if (lm == LOADMODE_LoadInterfaces)&lt;br /&gt;
	{&lt;br /&gt;
		t = (Text*)mm-&amp;gt;getInterface(__FILE__, I_TEXT);&lt;br /&gt;
		pl = (PlayerList*)mm-&amp;gt;getInterface(__FILE__, I_PLAYERLIST);&lt;br /&gt;
		ppd = (PerPlayerData*)mm-&amp;gt;getInterface(__FILE__, I_PERPLAYERDATA);&lt;br /&gt;
&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__,CB_PRERENDER, CB_PRERENDER_VERSION, &amp;amp;preRender);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
extern &amp;quot;C&amp;quot; &lt;br /&gt;
{&lt;br /&gt;
	EXPORT void* getInstance(void* mm, LoadMode lm)&lt;br /&gt;
	{&lt;br /&gt;
		return getClassInstance(mm,lm);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When we run this code (you'll need to run a Discretion-compatible ASSS server to get a name), we get the expected result:&lt;br /&gt;
&lt;br /&gt;
[[Image:Ss2.PNG]]&lt;br /&gt;
&lt;br /&gt;
Now, in the tutorial, we will react to when the user presses alt to cycle through the name, squad, and freq. First, we modify our conf file to specify what keys correspond to our action. Throughout the code (and conf files) we refer to our action with a string. Let's use &amp;quot;cycle_data&amp;quot; as the name for our action. Then, we use the Controls module to specify a function to call when the key(s) for &amp;quot;cycle_data&amp;quot; are pressed. In this function, we will change the type of data we're displaying about the player in prerender.&lt;br /&gt;
&lt;br /&gt;
So first let's edit conf/modules/Controls.conf. Open this file (in notepad, for example), and add &amp;quot;cycle_data&amp;quot; to the list of controls in Controls::Name. Also, we set Controls::cycle_data to RALT. In general, the names of the controls (like &amp;quot;RALT&amp;quot; for us) are equal to the SDLK_ constants for the keys, which you can google for. Alternately, if you're curious, examine initKeys() at the bottom of Modules/KeyControls/SDL Key Controls/SDL_KeyControls.cpp. Usually they're pretty obvious, as was the case with &amp;quot;RALT&amp;quot;. If you wanted to allow either alt key to be pressed you could use &amp;quot;RALT, LALT&amp;quot;, or if you wanted both, &amp;quot;RALT + LALT&amp;quot;. There will eventually be a nice visual interface where the user can rebind all these keys to whatever values they want to use. Proceed to add the mentioned settings to the conf/modules/Controls.conf.&lt;br /&gt;
&lt;br /&gt;
[[Image:Ss3.PNG]]&lt;br /&gt;
&lt;br /&gt;
Now to figure out when the key is pressed, we need to tell the Controls module we're interested in a particular action (cycle_data). We first need to get the controls interface, and then register the callback CB_CONTROLSLOADED, which is when we should register key events.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// The controls loaded callback, parameter is null&lt;br /&gt;
// this callback occurs when we have loaded the controls bindings, at this point you can call regControlEvent&lt;br /&gt;
#define CB_CONTROLSLOADED			&amp;quot;CB_CONTROLSLOADED&amp;quot;&lt;br /&gt;
#define CB_CONTROLSLOADED_VERSION	&amp;quot;1&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In that callback, we use regControlEvent from the Controls module to tell the Controls module what function to call when your action occurs (the user presses alt).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * tell the Controls modules you want a function to be called when a certain control is pressed,&lt;br /&gt;
 * down is true iff we want the function to be called when the key is pressed down, if itâ€™s false it will be&lt;br /&gt;
 * called iff the key combo is lifted up.&lt;br /&gt;
 *&lt;br /&gt;
 * call this function in your handler for the CB_CONTROLSLOADED callback&lt;br /&gt;
 *&lt;br /&gt;
 * @param keyString the keyString corresponding to the event, as defined in the settings (like &amp;quot;repel&amp;quot;)&lt;br /&gt;
 * @param funcToCall the function to call when the event occurs, down = true iff we're pressing the key combination&lt;br /&gt;
 */&lt;br /&gt;
void (*regControlEvent)(const char* controlString, void (*funcToCall)(bool down, const char* controlString));&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
To do this, we need a function to call when the control is pressed down or released. The type of the function is void function taking parameters (bool down, const char* controlString), so we add such a function to our module (we named it cycleDataPressed). When this function is called, we change a global variable in our module which changes what we display. &lt;br /&gt;
&lt;br /&gt;
Note that once we #include &amp;quot;Controls/Controls.h&amp;quot;, we need to add Modules/Shared/StringManip.cpp to our project to avoid unresolved external symbol linker errors. This is done by going to File -&amp;gt; Add Existing Item, then selecting Modules/Shared/StringManip.cpp.&lt;br /&gt;
&lt;br /&gt;
[[Image:Ss4.PNG]]&lt;br /&gt;
&lt;br /&gt;
If you don't want to do that, or you're using Eclipse, you can include the following code at the top of our file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifdef HACK_EXTERNALS&lt;br /&gt;
#include &amp;quot;Shared/StringManip.cpp&amp;quot;&lt;br /&gt;
#endif HACK_EXTERNALS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Notice that this relies on the preprocessor macro HACK_EXTERNALS to be defined (by discretion convention). This is automatically defined for the template module in eclipse, however you can do it manually (in Eclipse), by going to project -&amp;gt; properties -&amp;gt; C/C++ Build -&amp;gt; Settings -&amp;gt; GCC C++ Compiler -&amp;gt; Preprocessor and working with the Defined Symbols listbox.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The resultant code should now be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Discretion Tutorial, goals:&lt;br /&gt;
// 1) display text on the screen with the Text module &lt;br /&gt;
// 2) show how to access shared per player data&lt;br /&gt;
// 3) listen and act upon key presses in Discretion&lt;br /&gt;
// 4) show how to register and use local per player data.&lt;br /&gt;
// April 2007&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;Module.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Text/Text.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Graphics/Graphics.h&amp;quot;&lt;br /&gt;
#include &amp;quot;PerPlayerData/PerPlayerData.h&amp;quot;&lt;br /&gt;
#include &amp;quot;PlayerList/PlayerList.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Controls/Controls.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ModuleManager* mm = 0;&lt;br /&gt;
PerPlayerData* ppd = 0;&lt;br /&gt;
PlayerList* pl = 0;&lt;br /&gt;
Text* t = 0;&lt;br /&gt;
Controls* c = 0;&lt;br /&gt;
&lt;br /&gt;
// 0 = name, 1 = squad, 2 = freq&lt;br /&gt;
int dataState = 0;&lt;br /&gt;
&lt;br /&gt;
void cycleDataPressed(bool down, const char* controlString)&lt;br /&gt;
{&lt;br /&gt;
	// if the key is pressed down (rather than released)&lt;br /&gt;
	if (down)&lt;br /&gt;
		dataState = (dataState + 1) % 3;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// callback below&lt;br /&gt;
void keyControlsLoaded(void* param)&lt;br /&gt;
{&lt;br /&gt;
	c-&amp;gt;regControlEvent(&amp;quot;cycle_data&amp;quot;,cycleDataPressed);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void preRender(void* param)&lt;br /&gt;
{&lt;br /&gt;
	Point topLeft(400,200);&lt;br /&gt;
	int ticked_pid = pl-&amp;gt;getTargetPID();&lt;br /&gt;
	&lt;br /&gt;
	char buf[128];&lt;br /&gt;
&lt;br /&gt;
	if (dataState == 0)&lt;br /&gt;
	{&lt;br /&gt;
		char* playerName = (char*)ppd-&amp;gt;getSharedData(ticked_pid, &amp;quot;name&amp;quot;);&lt;br /&gt;
		snprintf(buf,sizeof(buf),&amp;quot;Name: %s&amp;quot;,playerName);&lt;br /&gt;
	}&lt;br /&gt;
	else if (dataState == 1)&lt;br /&gt;
	{&lt;br /&gt;
		char* squadName = (char*)ppd-&amp;gt;getSharedData(ticked_pid, &amp;quot;squad&amp;quot;);&lt;br /&gt;
		snprintf(buf,sizeof(buf),&amp;quot;Squad: %s&amp;quot;,squadName);&lt;br /&gt;
	}&lt;br /&gt;
	else &lt;br /&gt;
	{&lt;br /&gt;
		int freq = *(int*)ppd-&amp;gt;getSharedData(ticked_pid, &amp;quot;freq&amp;quot;);&lt;br /&gt;
		snprintf(buf,sizeof(buf),&amp;quot;Freq: %i&amp;quot;,freq);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	t-&amp;gt;displayTextScreen2(buf, &amp;quot;yellow&amp;quot;, L_Chat, &amp;amp;topLeft);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// interface functions below&lt;br /&gt;
void* getClassInstance(void* _mm, LoadMode lm)&lt;br /&gt;
{&lt;br /&gt;
	mm = (ModuleManager*)_mm;&lt;br /&gt;
&lt;br /&gt;
	if (lm == LOADMODE_LoadInterfaces)&lt;br /&gt;
	{&lt;br /&gt;
		t = (Text*)mm-&amp;gt;getInterface(__FILE__, I_TEXT);&lt;br /&gt;
		pl = (PlayerList*)mm-&amp;gt;getInterface(__FILE__, I_PLAYERLIST);&lt;br /&gt;
		ppd = (PerPlayerData*)mm-&amp;gt;getInterface(__FILE__, I_PERPLAYERDATA);&lt;br /&gt;
		c = (Controls*)mm-&amp;gt;getInterface(__FILE__, I_CONTROLS);&lt;br /&gt;
&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__,CB_PRERENDER, CB_PRERENDER_VERSION, &amp;amp;preRender);&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__,CB_CONTROLSLOADED, CB_CONTROLSLOADED_VERSION, &amp;amp;keyControlsLoaded);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
extern &amp;quot;C&amp;quot; &lt;br /&gt;
{&lt;br /&gt;
	EXPORT void* getInstance(void* mm, LoadMode lm)&lt;br /&gt;
	{&lt;br /&gt;
		return getClassInstance(mm,lm);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this module, when we press the right alt key (assuming you used RALT in the conf file), it should cycle through the ticked player's data:&lt;br /&gt;
&lt;br /&gt;
[[Image:Ss5.PNG]]&lt;br /&gt;
&lt;br /&gt;
Finally, let's use some local per player data to count how many times we've toggled the state for each player. Our data will keep track of the current information we're displaying for each player, as well as how many times alt was pressed for the player.&lt;br /&gt;
&lt;br /&gt;
Each module is allowed to allocate one structure of per player data for local use. We are interested in the number of times the player presses alt, as well as the current data we're displaying. We also provide the PerPlayerData module with two functions, one to initialize the data, and one to deinitialize the data. You can skip either of these functions. In our case, we want to set the initial number of times the user pressed alt to 0, and set the initial display to 0 (which is the name). The function we make has to accept a void* which we cast to be a pointer to our structure. Here is our structure and initialization function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct MyPlayerData&lt;br /&gt;
{&lt;br /&gt;
	int dataState;&lt;br /&gt;
	int count;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
void initMyPlayerData(void* param)&lt;br /&gt;
{&lt;br /&gt;
	MyPlayerData* mpd = (MyPlayerData*)param;&lt;br /&gt;
&lt;br /&gt;
	mpd-&amp;gt;count = 0;&lt;br /&gt;
	mpd-&amp;gt;dataState = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We now have to tell the PerPlayerData module we want it to keep track of data for us. This is done during CB_LOADPERPLAYERDATA, which we listen for. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
When this callback occurs, you should register the per player data for your module&lt;br /&gt;
*/&lt;br /&gt;
#define CB_LOADPERPLAYERDATA		&amp;quot;Load Per Player Data&amp;quot;&lt;br /&gt;
#define CB_LOADPERPLAYERDATA_VERSION	&amp;quot;1&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
During this callback we want to call the interface function in PerPlayerData, reserveData. This allocates some space for every player. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
  * Call this during CB_LOADPERPLAYERDATA to reserve some per player data for your module.&lt;br /&gt;
  * @param interfaceName the I_ interface name that you're using&lt;br /&gt;
  * @param size the number of bytes to allocate, use sizeof(YourDataStruct)&lt;br /&gt;
  * @param initer the function to call with the data as the argument after we allocate (can be null)&lt;br /&gt;
  * @param deiniter the function to call with the data as the argument before we free (can be null)&lt;br /&gt;
  * @return key the key to use in GetData when we want to change / use the data&lt;br /&gt;
  */&lt;br /&gt;
int (*reserveData)(const char* interfaceName, unsigned int size, &lt;br /&gt;
								void (*initer)(void* data), void (*deiniter)(void* data));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this function, the interface name is the name of the interface, as when we're registering callbacks. Using __FILE__ like we have been will work. The size parameter should be set to the size of our data structure, we'll use sizeof(MyPlayerData) here. This function returns a key which we keep track of in order to get the data later on. To get the data, we use the GetData interface function from PerPlayerData:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
  * Get the Data which we've previously reserved with ReserveData for a particular player&lt;br /&gt;
  * @param pid the player id of the player whose data we want (often sent in packets)&lt;br /&gt;
  * @param key the key returned by ReserveData which we use to tell your data apart from a different module's&lt;br /&gt;
  */&lt;br /&gt;
void* (*getData)(int pid, int key);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This returns a void* which we can cast to be a pointer to our structure. We put getData into our CB_PRERENDER to get the state and number of times alt was pressed for the targeted player, and display that. We also increment the number of times alt was pressed every time cycleDataPressed is called when a key is pressed down.&lt;br /&gt;
&lt;br /&gt;
The final code is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Discretion Tutorial, goals:&lt;br /&gt;
// 1) display text on the screen with the Text module &lt;br /&gt;
// 2) show how to access shared per player data&lt;br /&gt;
// 3) listen and act upon key presses in Discretion&lt;br /&gt;
// 4) show how to register and use local per player data.&lt;br /&gt;
// April 2007&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;Module.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Text/Text.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Graphics/Graphics.h&amp;quot;&lt;br /&gt;
#include &amp;quot;PerPlayerData/PerPlayerData.h&amp;quot;&lt;br /&gt;
#include &amp;quot;PlayerList/PlayerList.h&amp;quot;&lt;br /&gt;
#include &amp;quot;Controls/Controls.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ModuleManager* mm = 0;&lt;br /&gt;
PerPlayerData* ppd = 0;&lt;br /&gt;
PlayerList* pl = 0;&lt;br /&gt;
Text* t = 0;&lt;br /&gt;
Controls* c = 0;&lt;br /&gt;
&lt;br /&gt;
int myPlayerDataKey = 0;&lt;br /&gt;
&lt;br /&gt;
struct MyPlayerData&lt;br /&gt;
{&lt;br /&gt;
	// 0 = name, 1 = squad, 2 = freq&lt;br /&gt;
	int dataState;&lt;br /&gt;
	int count;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
void initMyPlayerData(void* param)&lt;br /&gt;
{&lt;br /&gt;
	MyPlayerData* mpd = (MyPlayerData*)param;&lt;br /&gt;
&lt;br /&gt;
	mpd-&amp;gt;count = 0;&lt;br /&gt;
	mpd-&amp;gt;dataState = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cycleDataPressed(bool down, const char* controlString)&lt;br /&gt;
{&lt;br /&gt;
	// if the key is pressed down (rather than released)&lt;br /&gt;
	if (down)&lt;br /&gt;
	{&lt;br /&gt;
		int ticked_pid = pl-&amp;gt;getTargetPID();&lt;br /&gt;
&lt;br /&gt;
		MyPlayerData* data = (MyPlayerData*)ppd-&amp;gt;getData(ticked_pid, myPlayerDataKey);&lt;br /&gt;
&lt;br /&gt;
		data-&amp;gt;dataState = (data-&amp;gt;dataState + 1) % 3;&lt;br /&gt;
		++(data-&amp;gt;count);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// callbacks below&lt;br /&gt;
void keyControlsLoaded(void* param)&lt;br /&gt;
{&lt;br /&gt;
	c-&amp;gt;regControlEvent(&amp;quot;cycle_data&amp;quot;,cycleDataPressed);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loadPerPlayerData(void* param)&lt;br /&gt;
{&lt;br /&gt;
	myPlayerDataKey = ppd-&amp;gt;reserveData(__FILE__, sizeof(MyPlayerData), initMyPlayerData, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void preRender(void* param)&lt;br /&gt;
{&lt;br /&gt;
	Point topLeft(400,200);&lt;br /&gt;
	int ticked_pid = pl-&amp;gt;getTargetPID();&lt;br /&gt;
	MyPlayerData* data = (MyPlayerData*)ppd-&amp;gt;getData(ticked_pid, myPlayerDataKey);&lt;br /&gt;
	&lt;br /&gt;
	char buf[128];&lt;br /&gt;
&lt;br /&gt;
	if (data-&amp;gt;dataState == 0)&lt;br /&gt;
	{&lt;br /&gt;
		char* playerName = (char*)ppd-&amp;gt;getSharedData(ticked_pid, &amp;quot;name&amp;quot;);&lt;br /&gt;
		snprintf(buf,sizeof(buf),&amp;quot;Name: %s (Switched %i times)&amp;quot;, playerName, data-&amp;gt;count);&lt;br /&gt;
	}&lt;br /&gt;
	else if (data-&amp;gt;dataState == 1)&lt;br /&gt;
	{&lt;br /&gt;
		char* squadName = (char*)ppd-&amp;gt;getSharedData(ticked_pid, &amp;quot;squad&amp;quot;);&lt;br /&gt;
		snprintf(buf,sizeof(buf),&amp;quot;Squad: %s  (Switched %i times)&amp;quot;, squadName, data-&amp;gt;count);&lt;br /&gt;
	}&lt;br /&gt;
	else &lt;br /&gt;
	{&lt;br /&gt;
		int freq = *(int*)ppd-&amp;gt;getSharedData(ticked_pid, &amp;quot;freq&amp;quot;);&lt;br /&gt;
		snprintf(buf,sizeof(buf),&amp;quot;Freq: %i  (Switched %i times)&amp;quot;, freq, data-&amp;gt;count);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	t-&amp;gt;displayTextScreen2(buf, &amp;quot;yellow&amp;quot;, L_Chat, &amp;amp;topLeft);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// interface functions below&lt;br /&gt;
void* getClassInstance(void* _mm, LoadMode lm)&lt;br /&gt;
{&lt;br /&gt;
	mm = (ModuleManager*)_mm;&lt;br /&gt;
&lt;br /&gt;
	if (lm == LOADMODE_LoadInterfaces)&lt;br /&gt;
	{&lt;br /&gt;
		t = (Text*)mm-&amp;gt;getInterface(__FILE__, I_TEXT);&lt;br /&gt;
		pl = (PlayerList*)mm-&amp;gt;getInterface(__FILE__, I_PLAYERLIST);&lt;br /&gt;
		ppd = (PerPlayerData*)mm-&amp;gt;getInterface(__FILE__, I_PERPLAYERDATA);&lt;br /&gt;
		c = (Controls*)mm-&amp;gt;getInterface(__FILE__, I_CONTROLS);&lt;br /&gt;
&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__,CB_PRERENDER, CB_PRERENDER_VERSION, &amp;amp;preRender);&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__,CB_CONTROLSLOADED, CB_CONTROLSLOADED_VERSION, &amp;amp;keyControlsLoaded);&lt;br /&gt;
		mm-&amp;gt;regCallback(__FILE__,CB_LOADPERPLAYERDATA, CB_LOADPERPLAYERDATA_VERSION, &amp;amp;loadPerPlayerData);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
extern &amp;quot;C&amp;quot; &lt;br /&gt;
{&lt;br /&gt;
	EXPORT void* getInstance(void* mm, LoadMode lm)&lt;br /&gt;
	{&lt;br /&gt;
		return getClassInstance(mm,lm);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And we're done!&lt;br /&gt;
&lt;br /&gt;
[[Image:Ss6.PNG]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Discretion]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5907</id>
		<title>Obtaining the Discretion Source using Subversion</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5907"/>
				<updated>2008-03-16T07:02:27Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: format&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how to obtain the Discretion source code using subversion. It assumes you know nothing and have no tools already installed. It is part of the [[Discretion Module Tutorial]]. It assumes you are using Windows, although the process for other operating systems is very similar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Subversion is a version control system which allows many programmers to incrementally and concurrently work on a project. Basically is a common way of organizing large projects superior to the &amp;quot;e-mail your changes to everyone&amp;quot; method. It also has lots of other nifty tricks which aren't important for right now.&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
The tutorial video can be obtained here.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
svn link: [http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91|download subversion]&lt;br /&gt;
&lt;br /&gt;
discretion repository link: https://ss-discretion.svn.sourceforge.net/svnroot/ss-discretion/client/trunk&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_Eclipse&amp;diff=5906</id>
		<title>Creating and Testing a Simple Discretion Module in Eclipse</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_Eclipse&amp;diff=5906"/>
				<updated>2008-03-16T07:01:53Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: content&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how anyone can using minGW (and probably g++) and Eclipse to compile a simple module and put get it to run on [[Discretion]]. It assumes you're using Windows (although g++ may work) and you don't have any tools installed. However, you should have already gotten the source code (if not see the [[Obtaining the Discretion Source using Subversion]] tutorial). This tutorial is part of a series of tutorials consisting of the [[Discretion Module Tutorial]].&lt;br /&gt;
&lt;br /&gt;
minGW stands for minimalistic Gnu for Windows. It is an open source complier almost identical to gcc and g++, which are the compilers used for linux, among other things. The compiler produces native Windows exectuables, and best of all it's free! However, its interface isn't the best for the novice user. Thus, we use eclipse to help manage the minGW compiler for us.&lt;br /&gt;
&lt;br /&gt;
Eclipse, is an integrated development environment (IDE) which is also open-source and free. It is basically a program that makes it easier to make other programs. It was originally designed for Java development, but people made plugins to allow C++ development. These extensions are called the CDT (C/C++ Development Tooling). The CDT integrates nicely with minGW so these two make a good match. Discretion's modules come with Eclipse Projects when you get the source so modifications are easy to make. Eclipse is implemented in Java, so in order to use it you need the Java Runtime Environment. The good news is you probably already have this installed. Nonetheless, the tutorial covers downloading it if you don't already have it installed.&lt;br /&gt;
&lt;br /&gt;
==Videos==&lt;br /&gt;
&lt;br /&gt;
This tutorial is divided into three parts:&lt;br /&gt;
* Obtaining and Testing minGW&lt;br /&gt;
* Getting the Java Runtime Environment (90% of people can skip this step)&lt;br /&gt;
* Downloading Eclipse with CDT&lt;br /&gt;
* Creating and Testing a Simple Module within Discretion&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
&lt;br /&gt;
minGW: [http://sourceforge.net/project/showfiles.php?group_id=2435|Sourceforge File List]&lt;br /&gt;
&lt;br /&gt;
java runtime environment: [http://java.sun.com/javase/downloads/?intcmp=1281|Java Downloads]&lt;br /&gt;
&lt;br /&gt;
eclipse: [http://www.eclipse.org/downloads/|Eclipse Downloads]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&amp;lt;pre&amp;gt;// Sample Discretion Module Source File&lt;br /&gt;
#include &amp;quot;Module.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void* getClassInstance(void* _mm, LoadMode lm)&lt;br /&gt;
{&lt;br /&gt;
	if (lm == LOADMODE_Init)&lt;br /&gt;
		printf(&amp;quot;Test Module Initialized\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
extern &amp;quot;C&amp;quot; &lt;br /&gt;
{&lt;br /&gt;
	EXPORT void* getInstance(void* mm, LoadMode lm)&lt;br /&gt;
	{&lt;br /&gt;
		return getClassInstance(mm,lm);&lt;br /&gt;
	}&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module&amp;diff=5905</id>
		<title>Creating and Testing a Simple Discretion Module</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module&amp;diff=5905"/>
				<updated>2008-03-16T06:22:53Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: wording&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Once you obtain the [[Discretion]] source, you are ready to make a module for Discretion. If you haven't gotten the source yet, follow the instructions in [[Obtaining the Discretion Source using Subversion]]. This tutorial is part of the [[Discretion Module Tutorial]].&lt;br /&gt;
&lt;br /&gt;
There are three ways to make a module: 1. Eclipse with minGW, 2. MS Visual Studio, and 3. make. If you're new, the recommended way is to use minGW and Eclipse.&lt;br /&gt;
&lt;br /&gt;
== minGW and Eclipse ==&lt;br /&gt;
The way [[User:BaK|BaK]] works on Discretion is using minGW and Eclipse. Both pieces of software are free, and minGW is a lot like gcc so this might even work for Linux development. Eclipse is also BaK's favorite Integrated Development Environment (IDE). Currently the tutorial is oriented towards Windows users. If you want to try this method see the [[Creating and Testing a Simple Discretion Module in Eclipse]] tutorial.&lt;br /&gt;
&lt;br /&gt;
== Microsoft Visual Studio ==&lt;br /&gt;
Microsoft Visual Studio is an IDE produced by Microsoft that supports C++ development. I've used it for a few years and it's pretty good at what it does. Students also often get free licenses for Visual Studio from their school. Currently for Discretion, development is done in Eclipse so there aren't any current visual studio projects for you to use. Nonetheless, setting one up is a snap and is covered in the [[Creating and Testing a Simple Discretion Module in MS Visual Studio]] tutorial.&lt;br /&gt;
&lt;br /&gt;
== Make ==&lt;br /&gt;
Make is a tool that can build large projects. It relies on a compiler such as gcc. This one is typically used by the hardcore linux users, but it's also a very portable tool so it works great with multi-platform development. [[Goldeye]] is currently in charge of development using make (particularly interested in Mac OS X support), and may one day make (pun!) a [[Creating and Testing a Simple Discretion Module using Make]] tutorial. Send him a ?message in-game so he knows you appreciate him working on this and encourage him to write a tutorial for us!&lt;br /&gt;
&lt;br /&gt;
== Others ==&lt;br /&gt;
Outside of these three standard ways there are countless compilers and IDEs you can use to make any C++ project, including Discretion. However, officially we won't help you with these. Unofficially we probably will if you bug us enough ;).&lt;br /&gt;
&lt;br /&gt;
[[Category:Discretion]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Discretion_Module_Tutorial&amp;diff=5904</id>
		<title>Discretion Module Tutorial</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Discretion_Module_Tutorial&amp;diff=5904"/>
				<updated>2008-03-16T06:08:01Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: bullets!&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is divided into a few pieces. If you're completely new to [[Discretion]] development, you can view them in order, otherwise you can skip to the one you're interested in. If you go in order, they assume you have no knowledge and no tools installed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[Obtaining the Discretion Source using Subversion]]&lt;br /&gt;
* [[Creating and Testing a Simple Discretion Module]]&lt;br /&gt;
* [[Discretion Commands and Displaying Images]] (Also covers listening for callbacks and using interfaces)&lt;br /&gt;
* [[Listening for Key Presses, Displaying Text, and Per Player Data]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Discretion]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Discretion_Module_Tutorial&amp;diff=5903</id>
		<title>Discretion Module Tutorial</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Discretion_Module_Tutorial&amp;diff=5903"/>
				<updated>2008-03-16T06:07:18Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: wording&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is divided into a few pieces. If you're completely new to [[Discretion]] development, you can view them in order, otherwise you can skip to the one you're interested in. If you go in order, they assume you have no knowledge and no tools installed.&lt;br /&gt;
&lt;br /&gt;
[[Obtaining the Discretion Source using Subversion]]&lt;br /&gt;
&lt;br /&gt;
[[Creating and Testing a Simple Discretion Module]]&lt;br /&gt;
&lt;br /&gt;
[[Discretion Commands and Displaying Images]] (Also covers listening for callbacks and using interfaces)&lt;br /&gt;
&lt;br /&gt;
[[Listening for Key Presses, Displaying Text, and Per Player Data]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Discretion]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5902</id>
		<title>Obtaining the Discretion Source using Subversion</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5902"/>
				<updated>2008-03-16T06:05:23Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: wiki'd&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how to obtain the Discretion source code using subversion. It assumes you know nothing and have no tools already installed. It is part of the [[Discretion Module Tutorial]]. It assumes you are using Windows, although the process for other operating systems is very similar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Subversion is a version control system which allows many programmers to incrementally and concurrently work on a project. Basically is a common way of organizing large projects superior to the &amp;quot;e-mail your changes to everyone&amp;quot; method. It also has lots of other nifty tricks which aren't important for right now.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The tutorial video can be obtained here.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Links used within the tutorial:&lt;br /&gt;
&lt;br /&gt;
svn link: [http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91|download subversion]&lt;br /&gt;
&lt;br /&gt;
discretion repository link: https://ss-discretion.svn.sourceforge.net/svnroot/ss-discretion/client/trunk&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5901</id>
		<title>Obtaining the Discretion Source using Subversion</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5901"/>
				<updated>2008-03-16T06:04:44Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how to obtain the Discretion source code using subversion. It assumes you know nothing and have no tools already installed. It is part of the [[Discretion Module Tutorial]]. It assumes you are using Windows, although the process for other operating systems is very similar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Subversion is a version control system which allows many programmers to incrementally and concurrently work on a project. Basically is a common way of organizing large projects superior to the &amp;quot;e-mail your changes to everyone&amp;quot; method. It also has lots of other nifty tricks which aren't important for right now.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The tutorial video can be obtained here.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Links used within the tutorial:&lt;br /&gt;
&lt;br /&gt;
svn link: [download subversion|http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91]&lt;br /&gt;
&lt;br /&gt;
discretion repository link: https://ss-discretion.svn.sourceforge.net/svnroot/ss-discretion/client/trunk&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5900</id>
		<title>Obtaining the Discretion Source using Subversion</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5900"/>
				<updated>2008-03-16T06:04:05Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: spacing&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how to obtain the Discretion source code using subversion. It assumes you know nothing and have no tools already installed. It is part of the [[Discretion Module Tutorial]]. It assumes you are using Windows, although the process for other operating systems is very similar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Subversion is a version control system which allows many programmers to incrementally and concurrently work on a project. Basically is a common way of organizing large projects superior to the &amp;quot;e-mail your changes to everyone&amp;quot; method. It also has lots of other nifty tricks which aren't important for right now.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The tutorial video can be obtained here.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Links used within the tutorial:&lt;br /&gt;
&lt;br /&gt;
svn link: [http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91]&lt;br /&gt;
&lt;br /&gt;
discretion repository link: https://ss-discretion.svn.sourceforge.net/svnroot/ss-discretion/client/trunk&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5899</id>
		<title>Obtaining the Discretion Source using Subversion</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5899"/>
				<updated>2008-03-16T06:03:42Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: spacing&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how to obtain the Discretion source code using subversion. It assumes you know nothing and have no tools already installed. It is part of the [[Discretion Module Tutorial]]. It assumes you are using Windows, although the process for other operating systems is very similar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Subversion is a version control system which allows many programmers to incrementally and concurrently work on a project. Basically is a common way of organizing large projects superior to the &amp;quot;e-mail your changes to everyone&amp;quot; method. It also has lots of other nifty tricks which aren't important for right now.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The tutorial video can be obtained here.&lt;br /&gt;
&lt;br /&gt;
Links used within the tutorial:&lt;br /&gt;
svn link: [http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91]&lt;br /&gt;
discretion repository link: https://ss-discretion.svn.sourceforge.net/svnroot/ss-discretion/client/trunk&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5898</id>
		<title>Obtaining the Discretion Source using Subversion</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5898"/>
				<updated>2008-03-16T06:03:16Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: wording&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how to obtain the Discretion source code using subversion. It assumes you know nothing and have no tools already installed. It is part of the [[Discretion Module Tutorial]]. It assumes you are using Windows, although the process for other operating systems is very similar.&lt;br /&gt;
&lt;br /&gt;
Subversion is a version control system which allows many programmers to incrementally and concurrently work on a project. Basically is a common way of organizing large projects superior to the &amp;quot;e-mail your changes to everyone&amp;quot; method. It also has lots of other nifty tricks which aren't important for right now.&lt;br /&gt;
&lt;br /&gt;
The tutorial video can be obtained here.&lt;br /&gt;
&lt;br /&gt;
Links used within the tutorial:&lt;br /&gt;
svn link: [http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91]&lt;br /&gt;
discretion repository link: https://ss-discretion.svn.sourceforge.net/svnroot/ss-discretion/client/trunk&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5897</id>
		<title>Obtaining the Discretion Source using Subversion</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5897"/>
				<updated>2008-03-16T06:02:45Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: bold'd (or would it be bold'?)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a '''video''' tutorial describing how to obtain the Discretion source code using subversion. It assumes you know nothing and have nothing installed. It is part of the [[Discretion Module Tutorial]]. It assumes you are using Windows, although the process for other operating systems is very similar.&lt;br /&gt;
&lt;br /&gt;
Subversion is a version control system which allows many programmers to incrementally and concurrently work on a project. Basically is a common way of organizing large projects superior to the &amp;quot;e-mail your changes to everyone&amp;quot; method. It also has lots of other nifty tricks which aren't important for right now.&lt;br /&gt;
&lt;br /&gt;
The tutorial video can be obtained here.&lt;br /&gt;
&lt;br /&gt;
Links used within the tutorial:&lt;br /&gt;
svn link: [http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91]&lt;br /&gt;
discretion repository link: https://ss-discretion.svn.sourceforge.net/svnroot/ss-discretion/client/trunk&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5896</id>
		<title>Obtaining the Discretion Source using Subversion</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Obtaining_the_Discretion_Source_using_Subversion&amp;diff=5896"/>
				<updated>2008-03-16T06:02:04Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: content&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is a video tutorial describing how to obtain the Discretion source code using subversion. It assumes you know nothing and have nothing installed. It is part of the [[Discretion Module Tutorial]]. It assumes you are using Windows, although the process for other operating systems is very similar.&lt;br /&gt;
&lt;br /&gt;
Subversion is a version control system which allows many programmers to incrementally and concurrently work on a project. Basically is a common way of organizing large projects superior to the &amp;quot;e-mail your changes to everyone&amp;quot; method. It also has lots of other nifty tricks which aren't important for right now.&lt;br /&gt;
&lt;br /&gt;
The tutorial video can be obtained here.&lt;br /&gt;
&lt;br /&gt;
Links used within the tutorial:&lt;br /&gt;
svn link: [http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91]&lt;br /&gt;
discretion repository link: https://ss-discretion.svn.sourceforge.net/svnroot/ss-discretion/client/trunk&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module&amp;diff=5895</id>
		<title>Creating and Testing a Simple Discretion Module</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module&amp;diff=5895"/>
				<updated>2008-03-16T05:54:39Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: added link to main tutorial at top&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Once you obtain the [[Discretion]] source, you are ready to make a module for Discretion. If you haven't gotten the source yet, follow the instructions in [[Obtaining the Discretion Source using Subversion]]. This tutorial is part of the [[Discretion Module Tutorial]].&lt;br /&gt;
&lt;br /&gt;
There are three ways to make a module: 1. Eclipse with minGW, 2. MS Visual Studio, and 3. make. If you're new, the recommended way is to use minGW and Eclipse.&lt;br /&gt;
&lt;br /&gt;
== minGW and Eclipse ==&lt;br /&gt;
The way [[User:BaK|BaK]] works on Discretion is using minGW and Eclipse. Both pieces of software are free, and minGW is a lot like gcc so this might even work for Linux development. Eclipse is also BaK's favorite Integrated Development Environment (IDE). Currently the tutorial is oriented towards Windows users. If you want to try this method see the [[Creating and Testing a Simple Discretion Module in Eclipse]] tutorial.&lt;br /&gt;
&lt;br /&gt;
== Microsoft Visual Studio ==&lt;br /&gt;
Microsoft Visual Studio is an IDE produced by Microsoft that supports C++ development. I've used it for a few years and it's pretty good at what it does. Students also often get free licenses for Visual Studio from their school. Currently for Discretion, development is done in Eclipse so there aren't any current visual studio projects for you to use. Nonetheless, setting one up is a snap and is covered in the [[Creating and Testing a Simple Discretion Module in MS Visual Studio]] tutorial.&lt;br /&gt;
&lt;br /&gt;
== Make ==&lt;br /&gt;
Make is a tool that can build large projects. It relies on a compiler such as gcc. This one is typically used by the hardcore linux users, but it's also a very portable tool so it works great with cross platform development. [[Goldeye]] is currently in charge of development using make (particularly interested in Mac OS X support), and may one day make (pun!) a [[Creating and Testing a Simple Discretion Module using Make]] tutorial. Send him a ?message in-game so he knows you appreciate him working on this and encourage him to write a tutorial for us!&lt;br /&gt;
&lt;br /&gt;
== Others ==&lt;br /&gt;
Outside of these three standard ways there are countless compilers and IDEs you can use to make any C++ project, including Discretion. However, officially we won't help you with these. Unofficially we probably will if you bug us enough ;).&lt;br /&gt;
&lt;br /&gt;
[[Category:Discretion]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Discretion_Module_Tutorial&amp;diff=5894</id>
		<title>Discretion Module Tutorial</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Discretion_Module_Tutorial&amp;diff=5894"/>
				<updated>2008-03-16T05:53:50Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: added svn link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This tutorial is divided into a few pieces. If you're completely new to Discretion, you can view them in order, otherwise you can skip to the one you're interested in. It assumes you have no knowledge and nothing installed.&lt;br /&gt;
&lt;br /&gt;
[[Obtaining the Discretion Source using Subversion]]&lt;br /&gt;
&lt;br /&gt;
[[Creating and Testing a Simple Discretion Module]]&lt;br /&gt;
&lt;br /&gt;
[[Discretion Commands and Displaying Images]] (Also covers listening for callbacks and using interfaces)&lt;br /&gt;
&lt;br /&gt;
[[Listening for Key Presses, Displaying Text, and Per Player Data]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Discretion]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module&amp;diff=5893</id>
		<title>Creating and Testing a Simple Discretion Module</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module&amp;diff=5893"/>
				<updated>2008-03-16T05:52:23Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: hmm, forgot what i changed&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Once you obtain the [[Discretion]] source, you are ready to make a module for Discretion. If you haven't gotten the source yet, follow the instructions in [[Obtaining the Discretion Source using Subversion]].&lt;br /&gt;
&lt;br /&gt;
There are three ways to make a module: 1. Eclipse with minGW, 2. MS Visual Studio, and 3. make. If you're new, the recommended way is to use minGW and Eclipse.&lt;br /&gt;
&lt;br /&gt;
== minGW and Eclipse ==&lt;br /&gt;
The way [[User:BaK|BaK]] works on Discretion is using minGW and Eclipse. Both pieces of software are free, and minGW is a lot like gcc so this might even work for Linux development. Eclipse is also BaK's favorite Integrated Development Environment (IDE). Currently the tutorial is oriented towards Windows users. If you want to try this method see the [[Creating and Testing a Simple Discretion Module in Eclipse]] tutorial.&lt;br /&gt;
&lt;br /&gt;
== Microsoft Visual Studio ==&lt;br /&gt;
Microsoft Visual Studio is an IDE produced by Microsoft that supports C++ development. I've used it for a few years and it's pretty good at what it does. Students also often get free licenses for Visual Studio from their school. Currently for Discretion, development is done in Eclipse so there aren't any current visual studio projects for you to use. Nonetheless, setting one up is a snap and is covered in the [[Creating and Testing a Simple Discretion Module in MS Visual Studio]] tutorial.&lt;br /&gt;
&lt;br /&gt;
== Make ==&lt;br /&gt;
Make is a tool that can build large projects. It relies on a compiler such as gcc. This one is typically used by the hardcore linux users, but it's also a very portable tool so it works great with cross platform development. [[Goldeye]] is currently in charge of development using make (particularly interested in Mac OS X support), and may one day make (pun!) a [[Creating and Testing a Simple Discretion Module using Make]] tutorial. Send him a ?message in-game so he knows you appreciate him working on this and encourage him to write a tutorial for us!&lt;br /&gt;
&lt;br /&gt;
== Others ==&lt;br /&gt;
Outside of these three standard ways there are countless compilers and IDEs you can use to make any C++ project, including Discretion. However, officially we won't help you with these. Unofficially we probably will if you bug us enough ;).&lt;br /&gt;
&lt;br /&gt;
[[Category:Discretion]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Discretion&amp;diff=5892</id>
		<title>Discretion</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Discretion&amp;diff=5892"/>
				<updated>2008-03-16T05:50:32Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: added tutorial higher up&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:discretionss.PNG|thumb|A Screenshot of SubSpace Discretion.]]&lt;br /&gt;
&lt;br /&gt;
Discretion[http://ss-discretion.sf.net] is a [[SubSpace]] client created by [[User:BaK|BaK]]. It is open source, like [[ASSS]], and is released under the [http://en.wikipedia.org/wiki/GPL GPL]. Discretion was developed because of the limitations of the in-use client, [[Continuum]]. Furthermore, the lack of development of Continuum led to a situation where limitations in the client would never be overcome. Making heavy use of [http://en.wikipedia.org/wiki/Simple_DirectMedia_Layer SDL], Discretion is cross-platform, and is currently supported under Windows and Linux, with Mac OS X support on the way. Discretion is intended to be secure through design, rather than through obscurity like Continuum. It is designed to make cheating is impossible, rather than just difficult. There is also an extensive [[Discretion Module Tutorial]] on this wiki for those interested in helping out.&lt;br /&gt;
&lt;br /&gt;
Since cheating is to be made impossible, the server must check the data players send it for cheating. This requires modifying the server, which rules out using [[Subgame]]. There is, however, a modified ASSS Server that allows Discretion clients to connect. &lt;br /&gt;
&lt;br /&gt;
In order to encourage client development, Discretion is designed with a modular system similar to ASSS. There are interfaces which define actions for modules (such as &amp;quot;draw ship at 50,50&amp;quot;), and callbacks which signal when events occur (such as &amp;quot;player has been killed&amp;quot;). Where ever possible, magic values have been removed and are instead loaded from plain-text settings files. The goal of this is to eliminate any built-in constraints present in VIE SubSpace and Continuum. These magic values include the location / color of the FPS counter, 1024x1024 tiles in maps, each tile being 16x16 pixels, each ship image having 40 frames thus 9 degree turns, the number of fly over tiles, two sets of doors four tiles each per map, the 0x01 type packet corresponding to an arena login, friendly players showing up yellow in the stat box, the colors in the font file, the number of frames in the wormhole animation, the text that shows up when you press ESC, the number of ships, as well as all the settings Continuum does allow you to change such as the ship images, the game play settings, and the controls. The server is intended to be able to modify most of these, thus giving [[Zone]] developers maximum creativity and flexibility.&lt;br /&gt;
&lt;br /&gt;
==Modules==&lt;br /&gt;
Discretion is divided up into several modules, dynamically linked into the main program much like ASSS. These modules are desired to be as generic as possible, with their Continuum-like actions coming from the settings, rather than the modules themselves. Thus Discretion is like a 2D grid game engine, with settings and graphics which make it look like SubSpace. The module interfaces are documented in the corresponding header files using Javadoc-style documentation. There are currently over 30 modules in the Discretion release. Some of the main ones are discussed below.&lt;br /&gt;
&lt;br /&gt;
===Settings Handler===&lt;br /&gt;
The '''SettingsHandler''' modules loads the settings from ini-like plain text files. The main settings file is located in conf/MAIN.CONF, which #includes many other settings files. All these settings files are plain text, meaning they can be edited using a utility like pico or notepad. Individual settings can be specified in several formats, depending on how they should be interpreted. Supported types include integers (''50'', ''0x30'', ''0777''), strings (''hello person''), points/vectors/dimensions (''(100,200)''), rgb colors (''(255,255,255)'', ''(0,128,128)''), and [[LVZ]]-style screen locations (''(C+50,50)'', ''(B-10,C+25)''). There also exists a helper function to parse comma separated a list of strings from a single sting in shared/StringManip.h. This module interface also allows modules to load their own conf files, or save a group of settings to a file which the program can then read out of.&lt;br /&gt;
&lt;br /&gt;
The front end program, '''cskinviewer''' uses the saving capability of '''SettingsHandler''' to keep track of zone data between program executions.&lt;br /&gt;
&lt;br /&gt;
===Module Manager===&lt;br /&gt;
The '''Module Manger''' itself is a module which is loaded by the program, which then proceeds to load any other modules. This uses the setting Modules::Names which is a comma separated list of strings to figure out which modules to load. It loads module files, '.dll's in Windows and '.so's in Linux, from the bin/ directory. Modules are loaded in stages. During the first stage, LOADMODE_Init, modules register their interface, if any, with the '''Module Manager''' and register any callbacks they want to listen for. During the next stage, LOADMODE_LoadInterfaces, modules load any interfaces they plan to use. Finally, during LOADMODE_PostLoadInterfaces, modules can use their loaded interfaces to other modules to initialize themselves. Upon successful program termination, LOADMODE_Unload is invoked which allows the module to free any data or resources it's using. The module manager also facilitates callbacks. Where possible, C++ exception handling is used to aid in catching errors in a non-fatal way and reports the cause of the problem.&lt;br /&gt;
&lt;br /&gt;
Note that some initialization tasks should not be done in LOADMODE_PostLoadInterfaces since they require modules be initialized in a specific order. For example, the '''Text''' module, which writes text to the screen should not be initialized before the ''Graphics'' module is, since it would be unable to load the text image. Thus some initialization tasks are be done in callbacks, CB_LOADIMAGES in this instance.&lt;br /&gt;
&lt;br /&gt;
===Graphics===&lt;br /&gt;
The '''Graphics''' module allows one to load images and draw them to the screen or map. When an image is loaded through the interface, an image handle is given to the calling module which is used to refer to the image. This handle can also be used to get the image size (taking into account that some images are framed animations), or free the image when it's no longer needed. Blank images can also be created and drawn on, thus allowing one to predraw complex images instead of redrawing them every frame. Images, when drawn to the screen, are drawn in layers. This allows several modules to queue up images to be drawn out of order and still result in a correct drawing. Some layers include L_Tiles, L_Weapons, L_AfterWeapons, L_Gauges, L_Chat and L_TopMost. Images can be drawn relative to the screen, or relative to the map. Images can also be blended such that they appear translucent, as long as the user has Graphics::UseBlending set to 1. Rectangles of a constant color can also be drawn to the screen or on to another image. The images are queued up to be drawn during the CB_PRERENDER callback.&lt;br /&gt;
&lt;br /&gt;
Although providing a basic interface, it is uncommon to '''Graphics''' module directly for loading images. Instead the '''UniqueImage''' module allows one to specify an image in the settings and refer to it in code by a name. This is much easier than loading the image yourself, and easily allows a single graphic to contain many different images, which is not uncommon in SubSpace images (the bullets image, for example, contains images for all sorts of bullets rather than just a single type). The '''UniqueImage''' module makes sure to only keep a single copy of the image in memory at all times. The '''UniqueImage''' module, in turn, is used by the '''Animations''' module to provide simple access to SubSpace-style animations. Thus, a programmer can code something like 'draw animation &amp;quot;bullet explosion&amp;quot; at 512,512' and it will handle loading the image, figuring out how many frames there are, the speed of the animation, and how long to display it for.&lt;br /&gt;
&lt;br /&gt;
===Controls===&lt;br /&gt;
The '''Controls''' module permits the programmer to provide actions(&amp;quot;move forward&amp;quot;), while the settings specify exactly what keyboard or joystick input they correspond to(&amp;quot;up arrow key&amp;quot;). Controls should be registered in the CB_CONTROLSLOADED callback. Also, since this a generic module it does not capture any of the physical controls itself, instead relying on other modules to handle that aspect.&lt;br /&gt;
&lt;br /&gt;
The '''SDL Key Controls''' module handles capturing keyboard input and sending it to the '''Controls''' module. The '''Mouse''' module does not use the '''Controls''' module directly, instead providing its own interface which allows one to create mouse hotspots and be notified of mouse clicks or movements within these hotspots.&lt;br /&gt;
&lt;br /&gt;
===Timers===&lt;br /&gt;
Similar to how ASSS has timers implemented in the mainloop module, Discretion has a '''Timers''' module that provides a timer functionality. One can register a function to be called in X milliseconds, or every X milliseconds until it's canceled. Discretion is currently not multithreaded beyond SDL, so that a timer in an infinite loop (or any piece of code that gets to run, for that matter), will result in the program freezing up. Thus you should not use blocking calls in timers or take up too much processing time which will degrade performance.&lt;br /&gt;
&lt;br /&gt;
The '''Net''' module uses a timer to send and receive packets.&lt;br /&gt;
&lt;br /&gt;
===Text===&lt;br /&gt;
The '''Text''' module provides an easy way to draw text on the screen. This is the standard subspace text and can be specfied by color. This module draws the text on one line for a single frame. Therefore, you must call the appropriate functions in this interface during CB_PRERENDER every frame for however long you wish to display the text. There is support for drawing text relative to the screen or to the map, as well as blending text and drawing on any layer.&lt;br /&gt;
&lt;br /&gt;
The '''Textbox''' module uses '''Text''' to draw its text, but provides additional features such as drawing textbox borders and allowing easy textbox loading from files. '''EscapeBox''' and '''PlayerList''', in turn, use '''Textbox'''. '''Chat''' also makes use of the '''Text''' module when it draws player chat to the screen. The '''Flash''' module, which handles messages similar to SubSpace's kill and prize messages, also uses the '''Text''' module. Pretty much anywhere you see text, the '''Text''' module is at work.&lt;br /&gt;
&lt;br /&gt;
===Physics===&lt;br /&gt;
The '''Physics''' module provides functions which can give you a particle's new position given its initial position, velocity, and time elapsed. This is used for ships as well as weapons. The position can be advanced in such a way that is affected by the map (such as bombs going around a wormhole), or not. Particles can bounce off the level or explode on contact.&lt;br /&gt;
&lt;br /&gt;
The '''SelfShip''' module uses '''Physics''' to compute the new position of the player over time. '''SS_Items''' uses '''Physics''' to find the position of a bullet after a certain amount of time.&lt;br /&gt;
&lt;br /&gt;
===PerPlayerData===&lt;br /&gt;
The '''PerPlayerData''' module provides a simple way to have data that is common to every player. This is similar to ASSS' PlayerData module in that a struct of memory can be allocated for every player and referred to using a key. The module also facilitates simple sharing of per player data between module such as &amp;quot;name&amp;quot;, &amp;quot;x&amp;quot;, or &amp;quot;y&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
The '''PlayerList''' module uses the sharing facility of '''PerPlayerData''' to get the names of the players on the player list.&lt;br /&gt;
&lt;br /&gt;
===Level===&lt;br /&gt;
The '''Level''' module provides a simple interface to possibly many different types of level formats. Modules can load levels through the interface, as well as get the map or tile size. Furthermore, forces on the level, such as wormholes, friction, or gravity can be applied through the interface.&lt;br /&gt;
&lt;br /&gt;
Currently, the only map format implemented is '''oldlvl''' which supports regular SubSpace [[LVL]] files. This provides a somewhat more generic implementation, which a customizable amount of doors or custom animation tiles (wormholes, space station, and asteriods), as well as having wormholes with different properties on the same map.&lt;br /&gt;
&lt;br /&gt;
===Front End===&lt;br /&gt;
The front end, not exactly a module, is implemented as its own program, '''cskinviewer''', contributed by [[User:Smong|Smong]]. This program allows one to download a list of ASSS servers from a [[Directory Server]], and choose one and login. It uses the '''SettingsHandler''' to save the current zone list to the settings. Custom zones can not be added through the interface yet, but can be added by hand by editing conf/profiles/ZoneList.conf. &lt;br /&gt;
&lt;br /&gt;
The front end executes '''in_game''', which in turn loads the '''Module Manager''' which runs '''Main SDL''' which runs callbacks to load the various SDL Subsystems and starts the program's main loop.&lt;br /&gt;
&lt;br /&gt;
==Contribute==&lt;br /&gt;
Development for Discretion is ongoing and everyone is encouraged to contribute. Graphics are always helpful, and if you have an idea feel free to make it. In the spirit of free software, it would be best if eventually all VIE owned graphics were replaced, as their copyright status is unknown. This includes the ships, bullets, default tileset, and all other graphics from VIE SubSpace or Continuum. Also, a Discretion [[skin]] is yet to be made for the front end (the format follows that of Continuum's, see the skins directory in your Continuum folder). Additionally, many features are in development or unimplemented. If one wanted to help out, just contact [[User:BaK|BaK]], or start working on graphics or a module. There is also a [[Discretion Module Tutorial]] which shows you how to create a simple module. Some planned modules include:&lt;br /&gt;
&lt;br /&gt;
====Star Background====&lt;br /&gt;
A '''StarBackground''' module that draws stars and planets similar to how Continuum does it. It would be great it this looked better than Continuum as it would really lead to the immersion necessary for a fun experience. This could also be used to draw all sorts of backgrounds, such as grass for earth-based zones, to provide an alternate to tiling LVZ all over the map. This would be a good module to make to get introduced to Discretion development.&lt;br /&gt;
&lt;br /&gt;
====LVZ====&lt;br /&gt;
A reverse compatible LVZ module is desired to allow current zones to easily switch over to Discretion without remaking their lvz files. This could provide additional functionality not present in current lvz such as lvz that depend on ship locations to allow animations within shipsets. The easier way to make this is probably to make a static image/animation module which uses the settings and '''UniqueImage''' and '''Animations''' to draw images on the map and screen. Then, an lvz compatibility layer module would be made which translates an lvz file into a .conf file and uses '''SettingsHandler''' to load in the images from the generated file.&lt;br /&gt;
&lt;br /&gt;
====Radar====&lt;br /&gt;
Subspace and Continuum include a radar for locating enemies. This will have to be implemented in Discretion. The users should also be able to make the radar bigger by pressing a key (alt).&lt;br /&gt;
&lt;br /&gt;
====File Transfer====&lt;br /&gt;
This module is currently being worked on. This will allow file transfer using STP (SubSpace Transfer Protocol) as well as HTTP. This will permit quicker downloads as servers can put their files on the net instead of forcing everyone to download off the slow servers. Files transferred will include the settings, maps, and lvz files.&lt;br /&gt;
&lt;br /&gt;
====Sound====&lt;br /&gt;
Sound provides immersion in video games and gives them an authentic feel. We need a way to play sounds when certain actions occur such as a bullet being fired or player bouncing off a wall. WAV sounds will have to be implemented for reverse compatibility, but mp3 is not out of the question for longer sounds such as victory music or just music in general. After this is done, a built in mp3 player could be made to allow players to change songs from within the game. SDL_mixer[http://www.libsdl.org/projects/SDL_mixer/] provides mp3 capabilities and may be used.&lt;br /&gt;
&lt;br /&gt;
====Weapons====&lt;br /&gt;
Currently, only non-bouncing bullets are implemented. There are many items SubSpace uses which must be implemented. Care must be taken here to prevent cheating. For example, it would not be difficult to write a program to detect right before a player is about to get hit and automatically portal out or repel. Thus, these items may have to be modified to be on a timer, so that using a portal might require your ship to take a second to &amp;quot;charge up&amp;quot; instead of instantly warping. Also, it would be great if weapons didn't have to follow boring straight lines and instead could turn. Thus I could specify in the settings the direction a weapon would travel if the ship were facing straight up and it would happen. So a straight line would be (0,t), a curvy shot may be (sin(t),t), a shot that speeds up over time may be (0,2^t).&lt;br /&gt;
&lt;br /&gt;
====Custom Client Side Code====&lt;br /&gt;
The server should be able to provide code that can be executed client side. There are two types of code that will be provided: updated versions of modules, and game play related code. This is especially dangerous since a malicious server owner should not be permitted to compromise players' computers. The module updates can be done by providing a RSA signature with the binary .dll or .so which can be checked before executing any downloaded files. As for game play related code, a Java virtual machine could be used with a Security Manager that allows nothing beyond basic functions. Then, an interface could be provided to the game code that could be used by the code. Thus, binary .class file could be distributed for an arena that aren't allowed to delete files off your computer, but are allowed to access the game play relayed interface thus permitting graphics to be drawn or players to be warped around.&lt;br /&gt;
&lt;br /&gt;
==External links==&lt;br /&gt;
*[http://ss-discretion.sf.net Main Discretion Website]&lt;br /&gt;
&lt;br /&gt;
[[Category: Clients]]&lt;br /&gt;
[[Category: Discretion]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module&amp;diff=5891</id>
		<title>Creating and Testing a Simple Discretion Module</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module&amp;diff=5891"/>
				<updated>2008-03-16T05:48:27Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: added category&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Once you obtain the [[Discretion]] source, you are ready to make a module for Discretion. If you haven't gotten the source yet, follow the instructions in [[Obtaining the Discretion Source using Subversion]].&lt;br /&gt;
&lt;br /&gt;
There are three ways to make a module: 1. Eclipse with minGW, 2. MS Visual Studio, and 3. make. If you're new, the recommended way is to use minGW and Eclipse.&lt;br /&gt;
&lt;br /&gt;
== minGW and Eclipse ==&lt;br /&gt;
The way [[BaK]] works on Discretion is using minGW and Eclipse. Both pieces of software are free, and minGW is a lot like gcc so this might even work for Linux development. Eclipse is also BaK's favorite Integrated Development Environment (IDE). Currently the tutorial is oriented towards Windows users. If you want to try this method see the [[Creating and Testing a Simple Discretion Module in Eclipse]] tutorial.&lt;br /&gt;
&lt;br /&gt;
== Microsoft Visual Studio ==&lt;br /&gt;
Microsoft Visual Studio is an IDE produced by Microsoft that supports C++ development. I've used it for a few years and it's pretty good at what it does. Students also often get free licenses for Visual Studio from their school. Currently for Discretion, development is done in Eclipse so there aren't any current visual studio projects for you to use. Nonetheless, setting one up is a snap and is covered in the [[Creating and Testing a Simple Discretion Module in MS Visual Studio]] tutorial.&lt;br /&gt;
&lt;br /&gt;
== Make ==&lt;br /&gt;
Make is a tool that can build large projects. It relies on a compiler such as gcc. This one is typically used by the hardcore linux users, but it's also a very portable tool so it works great with cross platform development. [[Goldeye]] is currently in charge of development using make (particularly interested in Mac OS X support), and may one day make (pun!) a [[Creating and Testing a Simple Discretion Module using Make]] tutorial. Send him a ?message in-game so he knows you appreciate him working on this and encourage him to write a tutorial for us!&lt;br /&gt;
&lt;br /&gt;
== Others ==&lt;br /&gt;
Outside of these three standard ways there are countless compilers and IDEs you can use to make any C++ project, including Discretion. However, officially we won't help you with these. Unofficially we probably will if you bug us enough ;).&lt;br /&gt;
&lt;br /&gt;
[[Category:Discretion]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module&amp;diff=5890</id>
		<title>Creating and Testing a Simple Discretion Module</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module&amp;diff=5890"/>
				<updated>2008-03-16T05:47:52Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: content&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Once you obtain the [[Discretion]] source, you are ready to make a module for Discretion. If you haven't gotten the source yet, follow the instructions in [[Obtaining the Discretion Source using Subversion]].&lt;br /&gt;
&lt;br /&gt;
There are three ways to make a module: 1. Eclipse with minGW, 2. MS Visual Studio, and 3. make. If you're new, the recommended way is to use minGW and Eclipse.&lt;br /&gt;
&lt;br /&gt;
== minGW and Eclipse ==&lt;br /&gt;
The way [[BaK]] works on Discretion is using minGW and Eclipse. Both pieces of software are free, and minGW is a lot like gcc so this might even work for Linux development. Eclipse is also BaK's favorite Integrated Development Environment (IDE). Currently the tutorial is oriented towards Windows users. If you want to try this method see the [[Creating and Testing a Simple Discretion Module in Eclipse]] tutorial.&lt;br /&gt;
&lt;br /&gt;
== Microsoft Visual Studio ==&lt;br /&gt;
Microsoft Visual Studio is an IDE produced by Microsoft that supports C++ development. I've used it for a few years and it's pretty good at what it does. Students also often get free licenses for Visual Studio from their school. Currently for Discretion, development is done in Eclipse so there aren't any current visual studio projects for you to use. Nonetheless, setting one up is a snap and is covered in the [[Creating and Testing a Simple Discretion Module in MS Visual Studio]] tutorial.&lt;br /&gt;
&lt;br /&gt;
== Make ==&lt;br /&gt;
Make is a tool that can build large projects. It relies on a compiler such as gcc. This one is typically used by the hardcore linux users, but it's also a very portable tool so it works great with cross platform development. [[Goldeye]] is currently in charge of development using make (particularly interested in Mac OS X support), and may one day make (pun!) a [[Creating and Testing a Simple Discretion Module using Make]] tutorial. Send him a ?message in-game so he knows you appreciate him working on this and encourage him to write a tutorial for us!&lt;br /&gt;
&lt;br /&gt;
== Others ==&lt;br /&gt;
Outside of these three standard ways there are countless compilers and IDEs you can use to make any C++ project, including Discretion. However, officially we won't help you with these. Unofficially we probably will if you bug us enough ;).&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_MS_Visual_Studio&amp;diff=5888</id>
		<title>Creating and Testing a Simple Discretion Module in MS Visual Studio</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module_in_MS_Visual_Studio&amp;diff=5888"/>
				<updated>2008-03-16T05:19:19Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: Creating and Testing a Simple Discretion Module moved to Creating and Testing a Simple Discretion Module in MS Visual Studio: adding an eclipse version&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a tutorial for module creation in [[Discretion]]. For other tutorials, see the [[Discretion Module Tutorial]].&lt;br /&gt;
&lt;br /&gt;
Making a module is easy pie once you know what to do, so let's get to it.&lt;br /&gt;
&lt;br /&gt;
==Windows with MSVC==&lt;br /&gt;
&lt;br /&gt;
First step: make a new VS.net C++ Project. &lt;br /&gt;
&lt;br /&gt;
1. File -&amp;gt; New Project&lt;br /&gt;
&lt;br /&gt;
2. Win32 Console Project&lt;br /&gt;
&lt;br /&gt;
3. Give your project a name (&amp;quot;TestModule&amp;quot; in the picture)&lt;br /&gt;
&lt;br /&gt;
4. Press Ok&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module1.PNG]]&lt;br /&gt;
&lt;br /&gt;
5. Click on application settings on the left &lt;br /&gt;
&lt;br /&gt;
6. Click DLL from the list of radio buttons&lt;br /&gt;
&lt;br /&gt;
7. Press the Empty Project checkbox&lt;br /&gt;
&lt;br /&gt;
8. Press Finish&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module2.PNG]]&lt;br /&gt;
&lt;br /&gt;
9. File -&amp;gt; Add New Item&lt;br /&gt;
&lt;br /&gt;
10. Select C++ Source File (.cpp)&lt;br /&gt;
&lt;br /&gt;
11. Name your source file (&amp;quot;testmodule.cpp&amp;quot; in the picture)&lt;br /&gt;
&lt;br /&gt;
12. Press Open&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module3.PNG]]&lt;br /&gt;
&lt;br /&gt;
13. Paste the following code into your source file&lt;br /&gt;
&amp;lt;pre&amp;gt;// Sample Discretion Module Source File&lt;br /&gt;
#include &amp;quot;Module.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void* getClassInstance(void* _mm, LoadMode lm)&lt;br /&gt;
{&lt;br /&gt;
	if (lm == LOADMODE_Init)&lt;br /&gt;
		printf(&amp;quot;Test Module Initialized\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
extern &amp;quot;C&amp;quot; &lt;br /&gt;
{&lt;br /&gt;
	EXPORT void* getInstance(void* mm, LoadMode lm)&lt;br /&gt;
	{&lt;br /&gt;
		return getClassInstance(mm,lm);&lt;br /&gt;
	}&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
14. Right Click your project in the Solution Explorer and go to Properties (You can also access this through the Project Menu, Project -&amp;gt; Properties)&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module4.PNG]]&lt;br /&gt;
&lt;br /&gt;
15. In the properties window, from the drop down menu select &amp;quot;All Configurations&amp;quot;&lt;br /&gt;
&lt;br /&gt;
16. Select C++, General from the tree view on the left&lt;br /&gt;
&lt;br /&gt;
17. Type the directory to the Modules directory (the one with Module.h in it, not the one with only .dlls!) that comes with the full version of Discretion in the Additional Include Directory property (&amp;quot;E:/client/modules&amp;quot; in the picture)&lt;br /&gt;
&lt;br /&gt;
18. Press Ok&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module5.PNG]]&lt;br /&gt;
&lt;br /&gt;
19. Go to Buld -&amp;gt; Build &amp;lt;project name&amp;gt; (&amp;quot;TestModule&amp;quot; in the pictue)&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module6.PNG]]&lt;br /&gt;
&lt;br /&gt;
If all goes well, you code should compile and a .dll should be produced that is a Discretion module! Now let's put the module into Discretion to see it at work. &lt;br /&gt;
&lt;br /&gt;
20. Copy the produced .dll into your Discretion executable's Module folder (the one with the .dlls in it, not the one with Module.h in it).&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module7.PNG]]&lt;br /&gt;
&lt;br /&gt;
21. Edit conf/MAIN.CONF with a program such as Notepad&lt;br /&gt;
&lt;br /&gt;
22. Add the name of your dll to the Modules::Names setting (it's a comma seperated list of module names, order doesn't matter)&lt;br /&gt;
&lt;br /&gt;
23. Save the file&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module8.PNG]]&lt;br /&gt;
&lt;br /&gt;
24. Run Discretion, Select Practice Offline&lt;br /&gt;
&lt;br /&gt;
25. Observe your modules initialization in the console window&lt;br /&gt;
&lt;br /&gt;
[[Image:disc_module9.PNG]]&lt;br /&gt;
&lt;br /&gt;
Now you might say, rightfully so, that this module doesn't do anything. The way to do real things in Discretion is by using other modules. Want to react to user key presses? Use the KeyControls module. Want to display some images? Use the Graphics module. I'll gladly write additional tutorials for how to use each of these as needed. Tell me what you want to do and I'll write a tutorial with how to use the existing modules to accomplish what you want to do.&lt;br /&gt;
&lt;br /&gt;
[[Category:Discretion]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module&amp;diff=5889</id>
		<title>Creating and Testing a Simple Discretion Module</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=Creating_and_Testing_a_Simple_Discretion_Module&amp;diff=5889"/>
				<updated>2008-03-16T05:19:19Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: Creating and Testing a Simple Discretion Module moved to Creating and Testing a Simple Discretion Module in MS Visual Studio: adding an eclipse version&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Creating and Testing a Simple Discretion Module in MS Visual Studio]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	<entry>
		<id>http://wiki.minegoboom.com/index.php?title=UDP_Game_Protocol&amp;diff=5858</id>
		<title>UDP Game Protocol</title>
		<link rel="alternate" type="text/html" href="http://wiki.minegoboom.com/index.php?title=UDP_Game_Protocol&amp;diff=5858"/>
				<updated>2008-01-11T02:44:19Z</updated>
		
		<summary type="html">&lt;p&gt;BaK: all those websites were down lol&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a document outlining the UDP protocol used by game clients ([[Continuum]], [[SubSpace]], and all of the [[Bots]] in use today).  This is not exhaustive but has been compiled from [[LogicBot|LogicBot++]], [[MERVBot]], and various other places.  All clients also use the [[core protocol]]. '''It is, as of right now, incomplete. This guide is not complete; some packets do not have their contents filled out.''' See the [[Game Protocol FAQ]] article for additional information.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Full Packet List (Consolidated Subspace and Continuum Packet List)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 //====================\\&lt;br /&gt;
||          C2S         ||&lt;br /&gt;
 \\====================//&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ID	CLASS	HANDLER		PKT DESC&lt;br /&gt;
-		OFFSET	LEN	CONTENTS&lt;br /&gt;
-				[Type	Meaning]&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x01	Game	0x40B750	Arena Login&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
-		1	1	Ship type&lt;br /&gt;
-		2	2	Allow audio?&lt;br /&gt;
-		4	2	X resolution&lt;br /&gt;
-		6	2	Y resolution&lt;br /&gt;
-		8	2	Main arena number 0xFFFF for random pub, 0xFFFD for sub.&lt;br /&gt;
-		10	16	Arena name (optional, if offset 8 is 0xFFFD)&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x02	Game	0x40B3C1	Leave arena&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x03	Game	0x409BA9	Position&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
-		1	1	Direction&lt;br /&gt;
-		2	4	Timestamp&lt;br /&gt;
-		6	2	X velocity&lt;br /&gt;
-		8	2	Y pixels&lt;br /&gt;
-		10	1	Checksum&lt;br /&gt;
-		11	1	Togglables&lt;br /&gt;
-		12	2	X pixels&lt;br /&gt;
-		14	2	Y velocity&lt;br /&gt;
-		16	2	Bounty&lt;br /&gt;
-		18	2	Energy&lt;br /&gt;
-		20	2	Weapon info&lt;br /&gt;
-		22	2	Energy			(Optional)&lt;br /&gt;
-		24	2	S2C latency		(Optional)&lt;br /&gt;
-		26	2	Timer			(Optional)&lt;br /&gt;
-		28	4	Item info		(Optional)&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x04	Game	0x40CAA1	Packet tampering&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x05	Game	0x40A15B	Death message&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x06	Chat	0x40B67C	Chat&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
-		1	1	Chat type &lt;br /&gt;
-				0x00	Arena&lt;br /&gt;
-				0x01	Public macro&lt;br /&gt;
-				0x02	Public message&lt;br /&gt;
-				0x03	Team message&lt;br /&gt;
-				0x04	Freq&lt;br /&gt;
-				0x05	Private message&lt;br /&gt;
-				0x06	Moderator warning&lt;br /&gt;
-				0x07	Remote private message&lt;br /&gt;
-				0x09	Channel message&lt;br /&gt;
-		2	1	Sound code&lt;br /&gt;
-		3	2	Target player's player ID&lt;br /&gt;
-		5	-	Text&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x07	Game	0x40AC3B	Take green&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x08	Game	0x40B26E	Spectate request&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
-		1	2	Player ID&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x09	Game	0x40C0E7	Password/Login&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
-		1	1	Boolean: New user (1 = New, 0 = Not New)&lt;br /&gt;
-		2	32	Name&lt;br /&gt;
-		34	32	Password&lt;br /&gt;
-		66	4	Machine ident (drive serial number - can be random for bots)&lt;br /&gt;
-		70	1	ConnectType (0x00 is a good idea)&lt;br /&gt;
-		71	2	Timezone bias&lt;br /&gt;
-		73	2	Unkown&lt;br /&gt;
-		75	2	Client version (0x24 = Ctm, 0x86 = SS)&lt;br /&gt;
-		77	4	Unkown, memory checksum, Set to = 444&lt;br /&gt;
-		81	4	Unkown, memory checksum, Set to = 555&lt;br /&gt;
-		85	4	Permission ident&lt;br /&gt;
-		89	12	Unkown&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x0A	Game	0x40CAA1	Packet tampering&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x0B	Game	0x409EA9	SSUpdate.EXE request&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x0C	Game	0x409A6F	Map Request&lt;br /&gt;
&lt;br /&gt;
-		0	1	 Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x0D	Game	0x409A9F	news.txt request&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x0E	Game	0x40B4D7	Voice message&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x0F	Game	0x40AEF5	Frequency change&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x10	Game	0x40BF47	Attach request&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x11	Game	0x40CAA1	Packet tampering&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x12	Game	0x40CAA1	Packet tampering&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x13	Game	0x40ADDC	Flag request&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x14	Game	0x40B183	Drop all attached pilots&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x15	Game	0x40B1EB	Drop flags&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x16	Game	0x40B8C7	File transfer&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x17	Game	0x40B645	Registration information response&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x18	Game	0x40AF19	Set ship type&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x19	Game	0x40B41E	Set personal banner&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x1A	Game	0x4097BA	Security checksum&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type Byte 0x1A&lt;br /&gt;
-		1	4	Weapon Count&lt;br /&gt;
-		5	4	Settings Checksum *2&lt;br /&gt;
-		9	4	Subspace.EXE Checksum&lt;br /&gt;
-		13	4	Map.LVL Checksum&lt;br /&gt;
-		17	4	S2CSlowTotal&lt;br /&gt;
-		21	4	S2CFastTotal&lt;br /&gt;
-		25	2	S2CSlowCurrent&lt;br /&gt;
-		27	2	S2CFastCurrent&lt;br /&gt;
-		29	2	S2CRelOut (?Unsure?)&lt;br /&gt;
-		31	2	Ping&lt;br /&gt;
-		33	2	Ping Average&lt;br /&gt;
-		35	2	Ping Low&lt;br /&gt;
-		37	2	Ping High&lt;br /&gt;
-		39	1	Slow Frame Detected (Boolean)&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x1B	Game	0x4096C9	Security violation&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x1C	Game	0x409626	Drop brick&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x1D	Game	0x40948B	?setsettings&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x1E	Game			KotH Timer drop&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x1F	Game	0x408EBD	Fire a ball&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x20	Game	0x409322	Ball request&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x21	Game	0x408F95	Soccer goal scored&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x22	Game	0x4096E2	? Task switch ?&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
				*Logged packets:&lt;br /&gt;
				22 59 B8 13 03 3A 9E 96 60 48 C9 1C 28 0E 00 00 00 00&lt;br /&gt;
				22 1D 51 DD 00 9A 58 3C 89 48 C9 1C 28 AB 00 00 00 00&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x23	CTMGame	0x40C0E7	Continuum login&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x24	CTMGame	0x40C0E7	Continuum login&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x25	CTMGame	0x40C0E7	Continuum login&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x26	CTMGame	0x40C0E7	Continuum login&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x27	CTMGame	0x40C0E7	Continuum login&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x28	CTMGame	0x40C0E7	Continuum login&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x29	CTMGame	0x40C0E7	Continuum login&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x2A	CTMGame	0x40C0E7	Continuum login&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x2B	CTMGame	0x40C0E7	Continuum login&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 //====================\\&lt;br /&gt;
||          S2C         ||&lt;br /&gt;
 \\====================//&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ID	CLASS	Handler		DESC&lt;br /&gt;
-		OFFSET	LEN	CONTENTS&lt;br /&gt;
-				[Type	Meaning]&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x01	Game	0x402A7E	UID notification&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
-		1	2	ID&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x02	Game	0x402A24	In game /* We are in the arena */&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x03	Game	0x402B43	Player Entering&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
-		1	1	Ship type&lt;br /&gt;
-		2	1	Accepts audio messages&lt;br /&gt;
-		3	20	Player name (confirmed ASCIIZ)&lt;br /&gt;
-		23	20	Squad name (confirmed ASCIIZ)&lt;br /&gt;
-		43	4	Flag points&lt;br /&gt;
-		47	4	Kill points&lt;br /&gt;
-		51	2	Player ident&lt;br /&gt;
-		53	2	Team&lt;br /&gt;
-		55	2	Wins&lt;br /&gt;
-		57	2	Losses&lt;br /&gt;
-		59	2	Turretee ident&lt;br /&gt;
-		61	2	Flags carried&lt;br /&gt;
-		63	1	Boolean: Has KoTH&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x04	Game	0x402C58	Player leaving&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
-		1	1	Player ID&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x05	Game	0x402D34	Player fired a weapon&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x06	Game	0x402CFC	Player died&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
-		1	1	Death green&lt;br /&gt;
-		2	2	Killer ident&lt;br /&gt;
-		4	2	Killed ident&lt;br /&gt;
-		6	2	Bounty&lt;br /&gt;
-		8	2	? Flags&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x07	Chat	0x40303D	Chat&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
-		1	1	Message Type&lt;br /&gt;
-				0x00	Arena&lt;br /&gt;
-				0x01	Public macro&lt;br /&gt;
-				0x02	Public message&lt;br /&gt;
-				0x03	Team message&lt;br /&gt;
-				0x04	Freq&lt;br /&gt;
-				0x05	Private message&lt;br /&gt;
-				0x06	Moderator warning&lt;br /&gt;
-				0x07	Remote private message&lt;br /&gt;
-				0x08	Red server errors, without a name tag (S2C only)&lt;br /&gt;
-				0x09	Channel message&lt;br /&gt;
-		2	1	Sound Code&lt;br /&gt;
-		3	2	PlayerID&lt;br /&gt;
-		5	-	Message&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x0A	Game	0x40306F	Password response&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type byte&lt;br /&gt;
-		1	1	Accept response meaning&lt;br /&gt;
-				0	Login OK.&lt;br /&gt;
-				1	Unknown user.&lt;br /&gt;
-				2	Bad password.&lt;br /&gt;
-				3	Full arena.&lt;br /&gt;
-				4	Locked out.&lt;br /&gt;
-				5	Perission only.&lt;br /&gt;
-				6	Spectate only.&lt;br /&gt;
-				7	Too many points.&lt;br /&gt;
-				8	Connection too slow.&lt;br /&gt;
-				9	Perission only arena.&lt;br /&gt;
-				10	Server full.&lt;br /&gt;
-				11	Invalid name.&lt;br /&gt;
-				12	Offensive name.&lt;br /&gt;
-				13	No biller (not saving scores).&lt;br /&gt;
-				14	Server busy&lt;br /&gt;
-				15	Restricted zone (insufficient usage)&lt;br /&gt;
-				16	Demo Version &amp;lt;- If you get this, theres a serious problem.&lt;br /&gt;
-				17	Too many Demo Users (Same as above applys)&lt;br /&gt;
-				18	No Demo Players Allowed (again same as the above two)&lt;br /&gt;
-				255	Mod Access Required (An invalid value, used only in CEBot)&lt;br /&gt;
-		2	4	Server version&lt;br /&gt;
-		6	4	?&lt;br /&gt;
-		10	4	EXE checksum&lt;br /&gt;
-		14	4	? unused&lt;br /&gt;
-		18	1	? boolean&lt;br /&gt;
-		19	1	Boolean: Request registration form&lt;br /&gt;
-		20	4	? memory checksum&lt;br /&gt;
-		24	4	News checksum (0 = no news file)&lt;br /&gt;
-		28	4	? time/date&lt;br /&gt;
-		32	4	? time/date&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x09	Game	0x402C22	Player score changed&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x0A	Game	0x4033AB	Password packet response&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x0B	Game	0x403386	Soccer goal&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x0C	Game	0x402BEF	Player voice&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x0D	Game	0x402C7C	Set player frequency&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
-		1	2	Player ID&lt;br /&gt;
-		3	2	New Freq&lt;br /&gt;
-               5       1       Unknown (0xFF)&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x0E	Game	0x402BC6	Create turret link&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type byte&lt;br /&gt;
-		1	2	Turreter ident (gunner)&lt;br /&gt;
-		3	2	Turretee ident (driver)(when -1, detaching)&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x0F	Game	0x402A43	Arena settings&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x10	Game	0x4027CD	File transfer&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x11	Game	0x4033AB	No-op&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x12	Game	0x4031D4	Flag position&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x13	Game	0x403233	Flag claim&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x14	Game	0x4030D5	Flag victory&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x15	Game	0x40325C	Destroy turret link&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type byte&lt;br /&gt;
-		1	2	Player ident&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x16	Game	0x403280	Drop flag&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x17	Game	0x4033AB	No-op&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x18	Game	0x4030A6	Synchronization&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x19	Game	0x4028FB	Request file&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x1A	Game	0x4032A4	Reset score(s)&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x1B	Game	0x4032C8	Personal ship reset&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x1C	Game	0x4032E4	Put player in spectator mode / change extra info flag&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x1D	Game	0x402CC1	Player team and ship changed&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type byte&lt;br /&gt;
-		1	1	Ship type&lt;br /&gt;
-		2	2	Player ident&lt;br /&gt;
-		4	2	Team&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x1E	Game	0x4033AB	Banner flag&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x1F	Game	0x403209	Player banner changed&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x20	Game	0x402ABF	Collected prize&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x21	Game	0x403302	Brick dropped&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
repeated until the end of the message&lt;br /&gt;
-		1	2	X1 tiles&lt;br /&gt;
-		3	2	Y1 tiles&lt;br /&gt;
-		5	2	X2 tiles&lt;br /&gt;
-		7	2	Y2 tiles&lt;br /&gt;
-		9	2	Team&lt;br /&gt;
-		11	2	Brick ident (sent more than once)&lt;br /&gt;
-		13	4	Timestamp&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x22	Game	0x40316E	Turf flag update&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
repeated until the end of the message&lt;br /&gt;
-		1	2	Team for flag X	&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x23	Game	0x403192	Flag reward granted&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
repeated until the end of the message&lt;br /&gt;
-		1	2	Team&lt;br /&gt;
-		3	2	Points&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x24	Game	0x402AEA	Speed zone statistics&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x25	Game	0x402B1F	Toggle UFO ship&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x26	Game	0x4033AB	No-op&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x27	Game	0x4033AB	Keep-alive&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x28	Game	0x402EE3	Player position update&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x29	Game	0x4030FD	Map information&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x2A	Game	0x402867	Compressed map file&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x2B	Game	0x402787	Set personal KoTH timer&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x2C	Game	0x402762	KoTH game reset&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x2D	Game	0x4027AA	? Some other timer change ?&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x2E	Game 	0x402741	Power-ball position update&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x2F	Game	0x403364	Arena directory listing&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x30	Game	0x402707	Got zone banner advertisements&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x31	Game	0x4033A6	Login Finished&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x31	CTMGame			You are now past the login sequence&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x32	CTMGame			Change personal ship coordinates&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x33	CTMGame			Custom login failure message&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x34	CTMGame			Continuum version packet&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
0x35	CTMGame			Object toggling&lt;br /&gt;
&lt;br /&gt;
-		0	1	Type&lt;br /&gt;
&lt;br /&gt;
----------------------------------------&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Category: Protocol]]&lt;/div&gt;</summary>
		<author><name>BaK</name></author>	</entry>

	</feed>