___ __ _____ _
/ \___ / _| ___ _ __ ___ __/__ \_ _ _ __ _ __ ___| |_
/ /\ / _ \ |_ / _ \ '_ \/ __|/ _ \/ /\/ | | | '__| '__/ _ \ __|
/ /_// __/ _| __/ | | \__ \ __/ / | |_| | | | | | __/ |_
/___,' \___|_| \___|_| |_|___/\___\/ \__,_|_| |_| \___|\__|
A Tribes2 anti-cheat program by TheRoDent.
Who could have guessed?
This is the documentation for DefenseTurret version 1.15.
->>Download version 1.15. (win32)
->>Download version 1.15. (linux)
->>Download version 1.15. (SERVER)
The latest version of DefenseTurret is always available from the homepage:
2. Supported Operating Systems
3. Supported Processors
5. Starting it up
6. Advanced startup options
7. Revision history
8. Scripting related fixes & plugs
9. EXE Patching cheats
10. Other cheats
11. A word about the disabling of some script functions
13. Public Disclosure of vulnerabilities
15. (+) Quotes
16. (-) Quotes
17. Email conversation with xxxx about createClientTarget
19. Copyright and License
20. Documentation on the documentation :)
DefenseTurret fixes a number of scripting vulnerabilities within the Tribes2 engine, and also
hardens the client side executable against .exe hacks such as HappyMod2, and l33thacks.
The general principle behind DefenseTurret is that clients check each other up.
This distributed model means that the server needs to do nothing more than relay information
Whenever clients disagree with each other, the server notes this fact. The server can
be configured to drop a client who has disagreed with others too many times. The nett effect
of this is that DefenseTurret should be compatible with any mod.
Other than that, some very specific vulnerabilities are fixed by DefenseTurret. They are
documented in the next section.
Supported Operating Systems:
 Windows 95, 98, 98SE, ME, Windows 2000, Windows XP.
 Window NT 3.5x and 4.0 are NOT officially supported.
 Linux, 2.4 series kernel, and GLIBC 2.2+
Intel Pentium Pro and instructionset compatible (ala AMD) only. If you still have
an earlier CPU, you probably can't play Tribes2 usefully in any case. Sorry.
On windows, installation is as simple as running the installer, and choosing the directory
where your tribes2.exe is located.
You will have to untar the defenseturret-linux-x.y.z.tgz file (Replace x.y.z with the version).
The tar file contains "dt" "dtdll.so" and "dtquery.cs", and some documentation files.
dt, and dtdll.so must be copied to wherever you installed Tribes2 on your linux system.
This is typically /usr/local/games/tribes. The dtquery.cs script file should go into your
scripts/autoexec directory. On linux this is typically located at ~/.loki/tribes2/scripts/autoexec
tar xvfz defenseturret-linux-x.y.z.tgz
cp dt /usr/local/games/tribes2
cp dtdll.so /usr/local/games/tribes2
cp dtquery.cs ~/.loki/tribes2/scripts/autoexec
Starting it up:
If the installation went according to plan, you should end up with a file called dt.exe in
your c:\dynamix\tribes2\gamedata directory. Simply run dt.exe to start up Tribes2 in 'online'
Most people will simply use the supplied desktop/start bar shortcuts to start it up.
On linux, simply run the dt binary as you normally would tribes2.
Advanced startup options.
Some of you will say, "But wait, I had a '-login xyz foo' command line, and I'd like
to use that still!"
No problem. Just add those parameters to the end of the shortcut you use to start
DefenseTurret. DefenseTurret passes these strings directly through to tribes2.exe
Example: "dt.exe -online -login foo bar -w" will run Tribes2 online, and
automatically login as 'foo', with password 'bar'. Note, this is just an example.
You will have to replace "foo bar" with your Tribes2 login details.
1.0: First internal test release
1.1: Internal update, fixing more exploits.
1.2: Major overhaul of communications mechanism.
1.3: First public testing.
1.4: Resolved issues around .NET framework and non-relocatable DLLs.
Resolved Win98 crashes due to it's lame stack, and memory management.
Patched out automissile, and autoflare exploits.
Added additional texture checks, and cloak pack audio checks.
Added initial startup checks that will verify your textures, and
exe and warn you if something is amiss. Mostly useful for figuring
out what's wrong with your setup, BEFORE joining a game.
1.5: Fixed a number of Windows 98 problems.
More WinXP Pro fixes.
First closed beta testing.
1.6 Semi-finalized version for public beta.
1.7 Added texture validation of liquidTiles. Only textures.vl2 tiles are checked.
Map pack authors' tiles are not checked. xpack2, and euro2 only includes 1
tile each so it's really not worth it.
Disabled interpolation variables for Players
Added a client-side mechanism for viewing the Consensus. Press alt-\ to
display the DefenseTurret consensus status. So don't bother hacking
the scorescreen. It's pointless.
This is the first closed beta version.
1.8 Completely new way of handling createClientTarget. The maximum waypoint height
is now a server-side configurable option, allowing server admins to choose to allow
spam, or not.
1.9 Some internal fixes.
Changed createClientTarget behaviour to not completely disable
waypoints after attempts to set them above server configured maximum height.
Abuse of waypoints above maximum height will result in a 5 second penalty, and all
waypoints reset. Max wpt height is server configurable.
1.10 Added throttle of 3 seconds to sendLOSTarget to curb LOStarget exploit.
Fixed alt-\ Consensus GUI problems.
1.11 First public "test" release
Changed Consensus GUI binding to NumLock
1.12 Internal release
1.13 Internal release
1.14 Internal release
Major overhaul of the codebase, to split out platform specific code.
Inclusion of dtquery.cs, and example script to query all clients' DT
Linux version released.
Removal of TargetID spam exploit.
Stricter texture checking.
Removal of all script functions, and variables that return SimObject
positional, or rotational data. This makes a DT enabled T2 unable to host
a listen-server game, unfortunately.
set.listObjects() disabled, entirely.
obj.save() is now selectively disabled only, for "dangerous" simobjects
Addition, of a texture health indicator (win32 only)
Addition of vertical healthbars (win32 only)
Missile events/sounds, alternate method.
Fixed issue with DTServer deactivating in Arena
Fixed DefenseTurret::GetClientStatus function.
Much <3 to Ilys, for all his help, in both areas.
Scripting related fixes & plugs:
This section describes the changes to the T2 scripting environment:
obj.Save() is selectively disabled for certain SimObjects.
There are a number of scripting vulnerabilities that make use of obj.Save to store
information on disk that would otherwise not be accessible through scripting methods.
obj.Save() has been reenabled for general objects, such as script-created
simsets, so that certain "scripters" don't have to fix their scripts.
The mission editor, gui editor, or AI editor will probably not function whilst
DT is active, but since you won't need them playing in competitive games, it's no real
If you do need to edit missions, simply start up T2 in offline mode, without DefenseTurret.
createClientTarget() function disabled
createClientTarget has been used to create so called "spam" scripts. HO would
use a spam script to setup waypoints in the air, that would allow them to drop
mortars with precision on enemy targets. This has been tolerated up to now, since
nothing could really be done to stop this from happening.
createClientTarget's disabling effectively stops all spam scripts. It does not
stop you from using the Command Circuit to create team tasks, and target enemy
players within sensor range. This is how the game was intended to be.
createClienTarget hasn't been completely disabled. It will disallow targets created
above a certain height. The height is determined from the terrain height at the actual
requested waypoint position. This is a server configurable option. The default DT
height for waypoints is 10 metres.
For those that will whine that spam is their staple diet: There is still a means to spam.
Use the CC to target an enemy asset. You will receive a waypoint to the enemy asset,
indicating the distance. Now, use a range finding reticle such as Kerb's mortar reticles
and line up to your target with the distance indicated by your waypoint. Spam away.
This method is obviously not as accurate as using a spam script, which is a good thing.
It means that you won't find precision base-to-base spam, from an HO sitting 450 metres
away through a base window, right onto your generator/vpad/inventories.
I have to make it very clear that createClientTarget is only found in a single script
that comes with T2. Training4.cs, which is a training mission. Dynamix
obviously did not intend this function to be used by client-side scripts, since it is
not used anywhere else in the game.
GuiTreeViewCtrl is disabled
The GuiTreeViewCtrl is used by the mission editor, and the built-in tree() command.
This allows developers to explore the root SimSet, and is also the source of a number
of cheats. The tree() command was disabled during online play, but it could be easily
circumvented by just doing the same things as the original script command did by
manually instantiating a GuiTreeViewCtrl.
This stops scripts from acessing rotational/positional data they are not supposed to
be able to get to.
This fix stops variants of turrethack.cs which is used to waypoint enemy assets/players.
This fix does not affect scripts that allow you to edit the chat menu. They will still
work normally. These scripts use a control named GuiChatMenuTreeCtrl which is not disabled
by this fix.
Inspector is disabled
This disables most of what's been made public of <some-name-here>mod.
Exe patching cheats.
HappyMod 2 specific cheats:
The T2 engine allows one to set the visible distance via a slider in the options menu.
The variable gets stored in clientprefs.cs as $prefs::visibleDistanceMod. The normal
(default) range for this value is between 0.5, and 1.0
This setting allows players to reduce their visible distance from the default of 1.0
to a lower level, in an effort to increase FPS. The lower the visible distance, the
better FPS a slower machine can achieve, albeit with the disadvantage of not being able
to see so far. Effectively this variable controls where the "fog" starts. "fog" is the blurriness
you start seeing when items such as hills, or buildings are outside your visible distance.
Some maps, such as Quagmire (a very foggy map), overrides this value in map-script, to
give the map a more "foggy" feel. The map-variable isn't directly tied to the visibleDistanceMod
though, but by increasing the visibileDistanceMod beyond it's 0.5-1.0 range, it's possible to
negate the effect of the map's visible distance variable. For instance, to get good visibility
on Quagmire one would need to set the variable to a value of around 6.0.
HappyMod2, modifies the engine to allow values of bigger than 1.0 to be set on this variable, from
script. Normally, setting the variable to a value of more than 1.0 would result in it being ignored.
The nett effect of this cheat, is that by tweaking the visibleDistanceMod you can see "forever"
This comes with a huge FPS hit, of course, but it might be useful for instance to see what the enemy
are doing at their base from 1000 metres, or even for snipers.
DefenseTurret stops this cheat.
This is more of a "proof of concept" feature in HappyMod than a useful cheat. With hitscan
(instant weapons) such as the Laser rifle, or the ShockLance, this cheat basically does the targetting
for you, and fires the trigger. It's usefulness is however very limited, because you have to constantly
tweak the fire, and rotation timing of autoaim to compensate for your lag, and FPS. It also misses more
often than not. This is mostly due to the variables of lag, fps, etc.
Most players are probably better than this client-side aide, in any case. It is the sign of a well
designed game where there are only 2 weapons that can actually make use of any kind of autoaim feature.
The other weapons in T2 are all projectile based, so the only real way to cheat using say, the disc
is to just practice until you are ungodly good at it. The HappyMod2 auto-aim could probably be refined
to take more information into account but it would still probably never be as good as a veteran.
DefenseTurret stops this cheat.
This might come as news to you, but T2, with CRC disabled on the server STILL does CRC checking.
It does random CRC checks for all the models (shapes) in the game, such as the shape of a turret,
a pack, or a player. This happens regardless of whether "$Host::CRCTextures = 0;" is set in the
ServerPrefs.cs file of a dedicated server. That is the reason the variable is called CRCTextures, and
not just CRCChecking. Enabling CRCTextures tells the engine to also do random checks on the "skins"
of all objects, but the objects themselves are ALWAYS CRC checked regardless of the setting.
Due to the size of textures in comparison to models, CRC calculations of textures take more
time to calculate than models. This is probably the reason why people complained about "lag" when
CRC is enabled on a server. It isn't lag though. It's just your machine having to do more work
than normal, to calculate the CRC checksums of textures. Dynamix could probably have done better
here, by only checking "critical" textures such as mines, remote inventories, and deployables.
HappyMod however, can spoof the CRC checks that occur on MODELS. This means that if you run
HappyMod, you can have a shape called "weapon_sniperrifle.dts" (a shape file) on your machine that
looks totally different from the version on the server. HappyMod achieves this by hooking into
the CRC checking routines, and responding to the server with a "correct" CRC, when it is challenged.
The nett effect of this cheat, is that the sniper rifle (for instance) in your T2 can look totally
different than the sniper rifle anyone else sees. The HappyMod version of "weapon_sniperrifle.dts"
looks like a normal sniper rifle, except that it also creates a huge blue-ish halo around the player.
An offensive sniper sitting on a faraway hill, hidden behind a tree, will be easily spottable by a
HappyMod cheater, since he will have a huge glowing halo around his model (not that the incessant red
line from a hidden position isn't spottable either :) )
HappyMod changes the models for beacons, ris, sensors (motion/pulse), flag, mines, packs, turrets,
shrikes, and the sniper rifle. It does this to make these items more visible to a player. This isn't
your typical 'red mine' cheat. The mines, turrets, packs, etc. actually LOOKS different than the
normal models. This makes them easier to spot, and thus easier to avoid/destroy.
DefenseTurret stops this cheat.
HappyMod in the "wild"
Happy went to a lot of trouble to protect HM2 from spreading like wildfire.
He created a key-system, which would check if you had a valid key for your T2 login. Without the key file
HM2 wouldn't work. This was a clever move on Happy's part, and probably the top reason why
HM2 didn't proliferate so quickly.
However, when I did my testing with HM2, I received a link to a version that doesn't require the
keycheck. And it was found on a very public place. So be assured that there are plenty of copies
of it around, without requiring keys.
Continually calling SendLOSTarget allows a player to see a task wpt, which will turn red
whenever an enemy target is in LOS. Exploited towards ends such as long distance autosnipe
and some chaingunning. It would also cause serious lag for any players on the server.
SendLOSTarget is now limited to 1 call every 3 seconds, making this cheat useless.
It is possible to predict, targetid's in Tribes2. Using sendTargetToServer, it is possible
to receive task markers to tasks/targets that you wouldn't normally be able to using the
DT fixes this exploit, by limiting the rate of calls to this function. It effectively makes
the cheat useless.
Often, the skins for remote inventory station, mines, and deployable turrets are replaced to
make them more visible, to Offense players.
DefenseTurret checks your copies of these skins to make sure that you are using the original
Dynamix skins for these models.
DefenseTurret checks the skins of a number of deployables, turrets, packs, and the audio
for the cloak pack.
The debate around CRC checking of textures always has been, and will be an endless one. My
suggestion is that servers running DefenseTurret have CRCTextures=0, since DefenseTurret
will make sure that players aren't using incorrect skins for the above models.
textures/liquidTiles are also checked to be "stock standard" so "clearwater" is no more.
I will gladly accept requests for additional textures to be checked by DefenseTurret, but these
are really major ones that should not be touched, or modified by a client. But that's just my
opinion. Mail http://email@example.com if you would like to petition for more skins to be checked.
The current list of textures being checked by DefenseTurret is:
AutoMissile and AutoFlare
Dynamix took a shortcut when implementing the notification to the script engine for events
suchs as onTargetLock (for the missile launcher) and onHomeWarning for when missiles are
homing in on you. All these functions really do, is play a sound, whenever the event
happens. Scripts are available that will automatically fire, or throw a flare when these
events happen. These functions should rather have been properties, which can be configured
with a sound to play, when the event occurs. I guess it was just easier to call alxPlay
from script, rather than from C++ itsself. Unfortunately, this left a rather wide script
DefenseTurret disables these script events, but continues to play the sounds as they
normally would be played. An unfortunate side-effect of this is that scripts that used
HUDs to popup "Missile Lock" warnings on-screen, will no longer function.
Unfortunately there's no easy way to distinguish between harmless script, and "cheat"
scripts that autoflares, or automissiles.
This isn't a huge cheat in my opinion, but a lot of people frown upon it.
A word about the disabling of some script functions.
Some of the script functions that have been disabled may have been used by the
third party scripts that you run on your system. I've tested DefenseTurret on my
system quite intensely, and haven't run across any serious problems with my third
Your mileage may vary. If your Tribes2 suddenly starts receiving Unhandled Exception
errors, go through your third party scripts carefully to try and isolate the problem.
Contact the script author for a workaround or an update to your script, before blaming
Dual Processor systems
Tribes2 is apparently unstable on Dual Processor systems if the CPU affinity for the
process has not been set. Some people get around this by quickly setting the CPU
affinity using task manager to a specific CPU after launching T2.
When running DefenseTurret, you will be unable to change the processor affinity.
A workaround for this, is to flag your tribes2.exe's processor affinity using
ImageCfg. This allows you to permanently flag/modify the CPU affinity for your
This will not cause DT to consider your executable as tainted, since it is a PE
header flag change, and not an actual change to your tribes2.exe's code.
Public Disclosure of vulnerabilities:
I have taken a lot of flak from people about publicly disclosing scripting
vulnerabilities in Tribes2. Some have called me naive in my approach, and even
more have flamed me, and summarily deleted my posts about vulnerabilities in T2
Here is my retort:
I am a computer security, and development professional. I've been in the IT
industry for over 16 years. And in that time, not ONCE have I seen a situation
where public disclosure of a vulnerability did not lead to a good resolution.
Disclosure of vulnerabilities either lead to vendors patching the software product,
someone else patching the software product, or at least gives administrators
and users the information needed to detect and manage these vulnerabilities.
Read this ComputerWorld article to see why public disclosure is being supported
so widely in the whole of the IT industry, and not just the small area of
hacking/cracking called "computer game cheats"...
Full disclosure is the only way of evening the odds in the "Siege" between cheaters
and vendors/anti-cheat developers.
There is a possibility that somebody knowing the details will publish them
for personal fame, but there is never a chance that any of the cheaters will give
them to the vendors just to be nice.
Yes, there should be some restrictions on public disclosure. The following are
what I believe to be the key restrictions that should be placed on vulnerability
information prior to disclosure, and I believe I handled it fairly.
- "The vendor should be given a reasonable chance to provide a patch or new version
before the vulnerabiliry details are made public. Normally, if a vendor knows that
vulnerability details have been, or will be made public, they will hurry up to
address the problem."
Every vulnerability that I have disclosed has been submitted to Sierra, with a
lead time before publication of a month or more. The information has simply
'vanished' into the system, or has been flatly ignored.
I believe that Sierra has proven that they were incapable of even adressing the
basic engine BUGS, never mind the actual vulnerabilities.
- "When releasing the vulnerability details they should be released completely.
The attackers usually have a lot of spare time to figure out the missing parts,
but the often very busy good guys usually don't."
I have always released enough information about a vulnerability, so as to
inform, and disclose the problem, but never giving out a full implementation.
I have never diseminated complete scripts, or implementatations that are packaged.
You can say what you want. The fact is that no problem ever got solved by hiding
information under a rock, and pretending that a problem doesn't exist.
That's called procrastination, and it invariably leads to big blowouts.
As you can see, public disclosure is not Richard Stallman syndrome, and neither is
it a naive approach to cheats. Public disclosure is widely accepted methodology
for the management and resolution of software vulnerabilities.
A cheat in a game engine is NOTHING more than a software vulnerability.
I have adressed in DefenseTurret all the cheats that I have been made aware of,
or known about. If you know of any others, please feel free to disclose them, and
I will do my best to handle them in the next update of DefenseTurret.
Alpha testing, and general guinea pig behaviour:
Katarn, nDorfin, MrYETI, uberkru
.za T2 players
Directional and Organisational Support:
Jeff Tunnell, Tim Gift, Rick Overman, Mark Frohnmayer
The original Dynamix team: It's a pity Vivendi were so lame...
Scripting and Exploit discussions
Other Anonymous Teamleaders, and players.
Some people will just always remain awesome friends, and Tribers:
"and all you win98 users can thank Katarn else you wouldn't be playing this!! send donations to... "
"I would like to offer my full cooperation in your endeavour."
"Official DefenseTurret fanboi"
"Hey lou man, you talk about things kept private ect... But why did you seek to have hm2 cracked
in the first place? And doesnt that make you ground zero for it's public release? Maybe I read
everything wrong, but all these whiners should really be whining at you.
Personally Id love to see how your work was done, and I could care less about public releases.
But I jsut found it funny you were ground zero for round 2 of Happy's mod. "
"But the idea that TheRoDent is the guy with the "need to be informed" is laughable.
To think he's worthy of trust with any expoits or cheats is ridiculous."
"6 months from now when "Defense Turret" is still vaporware, you can blame me.
Should give you an easy out."
"This is a guy who found one variable that's displayed in strings, and tab
completion, and figured out what it did. For that he gets "Savior of Tribes 2", mkay."
"This is the guy who some people here apparently think will do anything to fix cheats."
"Fortunately those who have aren't like TheRoDent who goes posting code and exploits everywhere."
"Oh yeah, it's my mission to ruin Tribes 2, a game I love and play everyday.
That's why I hate guys like TheRoDent who claim they're going to fix cheats. "
"when you get out of your usual Richard Stallman type nievety, you might find that
public disclosure of exploits doesn't invariably lead to problems being solved"
"So this is mainly a pie in the sky thing that is like a placebo pill that does
nothing but you think it makes you feel better."
Email conversation with xxxx about createClientTarget
Sent: Tuesday, June 03, 2003 4:16 AM
Subject: defense turret
Isn't there a better way to handle the autopoints/autobeacon/turretfinder/beaconfinder/etc. than disabling
createclienttarget can be called with the first parameter as -1 when it's not attached to any target, i.e. to
create stationary waypoints. Scripts that use this are Qfiremissions, PJ Waypoints, jsut Waypoints, and Artifical
Horizon. I can see the first 3 being justifiably called cheats, but I don't think being able to
determine the location of the horizontal plane in Dessicator while flying shrike qualifies as a cheat. I also
think that if the devs had intended for navigational waypoints to not be possible, they would have patched
this out long ago. Stationary Waypoint scripts were available several months after the inital T2 release, but
autopoints and the like did not turn up in widespread use for a long time afterwards. So why not just
disallow createclienttarget when it is going for a targetid instead?
Yes I understand your point. However, clientTarget's don't need a targetID to classify them as cheats.
bdTurrethack for instance, creates waypoints without using targetID's. Autopoints is actually
not really a cheat in my opinion, since if you target enemy players, and scroll up and down your task
list (just bring it up using 'm') you can highlight them all, and get an 'autopoints' like feature. Of
course you'd have to press m, and scroll constantly but that's doable if you bind the tasklist
up/down buttons to your mouse scroll button.
The problem is that createClientTarget is just about the only way for any kind of cheat script, to
get the information to the player usefully. In fact, I can't think of any other mechanism that can
be used to give a player advantage using rotation/position data. Even if you did get the rotation/position,
what would you do with it if you didn't have a wpt capability? Nothing....
In fact, from a search thru the engine code, there's no other CLIENT side script function that takes ""
coordinates, which makes createClientTarget stand out even MORE as a glaring problem. Dynamix
obviously coded vary carefully around xyz coordinates, but this one slipped through.
Plugging createClientTarget will stop almost any cheat that glean position/rotation information
through what ever means possible. The cheats might be able to get hold of the data through other
means, but nothing useful could be made of it without createClientTarget
I've thought about this hard, and looked at all the scripts that use createclientTarget, and I haven't
been able to figure out any way to distinguish between a clandestine wpt, or an evil one.
As for Sierra's attempts at fixing cheats. That's been totally nonexistant imo. They had their hands
full just trying to get the basic game stable, and couldn't be bothered with cheats.
From the Torque source, I can actually see that this function was 'hacked' in by afterwards
to get around a scripting issue in the training mission. The wanted to create a wpt in the training
mission, that just identified a general location, instead of an actual object (which would have had
a targetID). The only properly coded uses for waypoints, is in association with targets themselves
and these are used internally by the CC, and the TargetManager for "Potential Tasks", or
"Assigned tasks" (e.g VCA, or VAT).
createClientTarget never should have been in the engine, it doesn't even fit properly in the code
for the TargetManager, it's just slapped on from what I can see...
It's unfortunate, but I don't see any other way around the issue, besides removing it.
email : firstname.lastname@example.org
web : http://themasters.co.za/rodent/
Tribes2 : TheRoDent
Copyright and License:
Please see the file "dt_license.txt" included with the DefenseTurret installation for
details about the software license, copyright and distribution rights.
Documentation on the documentation :)
The text below is no longer true. MHTML is dead. I converted this doc to plain HTML, but the
original text below has been kept for posterity. I did this because I hate things disappearing
on the web.
This document is built using the MHTML standard. Hence the ".mhtml" extension of the file.
It is entirely self-contained, and doesn're require any other files apart from itsself. All
the images you see in this document has been base-64 encoded and attached to the document
as MIME attachments. The HTML then refers to the internally embedded image attachments.
Actually, there's only one attachment, the DT logo, but more can be added if need be...
You will need a browser or email client that understands MHTML to be able read the documentation
or you can open up this file using your favorite text editor and gronk the html yourself.
Examples of MHTML compliant browsers/clients:
Microsoft Internet Explorer 4+
I handcrafted it so that I wouldn't have to distribute the images seperately. It also contains
a plain, text-only version of itsself at the beginning of the document, so that people that
can't handle MHTML are capable of reading the documentation too.