Index: README
===================================================================
--- README	(revision 965)
+++ README	(working copy)
@@ -95,6 +95,7 @@
   USE_CURL          - use libcurl for http/ftp download support
   USE_CURL_DLOPEN   - link with libcurl at runtime
   USE_CODEC_VORBIS  - enable Ogg Vorbis support
+  USE_CODEC_MP3     - enable MP3 support. Requires libmad to be installed.
   USE_LOCAL_HEADERS - use headers local to ioq3 instead of system ones
   USE_CCACHE        - use ccache compiler caching tool
   COPYDIR           - the target installation directory
Index: README-EF.txt
===================================================================
--- README-EF.txt	(revision 0)
+++ README-EF.txt	(revision 0)
@@ -0,0 +1,372 @@
+README for StarTrek Voyager - Elite Force engine release
+Project page: http://thilo.kickchat.com/efport-progress/
+   - last updated 09.11.2006
+
+This project is a modification to the icculus.org maintained quake3 engine
+to make it possible to run EliteForce holomatch. This means: you can *not*
+play single player missions with this project.
+This engine has full compatibility for the newer _and_ the original
+EliteForce protocol, clients using the original engine can use
+newer servers, and clients using my engine can use old servers, too.
+
+Now, the next few paragraphs are just some random blabla about the
+advantages of this release, but if you want to you can just skip it and go
+right to the installation instructions.
+
+What was the motivation for me doing this project?
+It actually started pretty small.. The Quake3 source has been released more
+than half a year ago and I got the crazy idea to try the quake3 engine with
+EliteForce on my trusted Gentoo Linux.
+When I started the program first the screen went black and nothing
+happened... nearly nothing. I heard some sounds and when I moved the cursor
+I heard random click-clicks from the mouse going over some menu buttons.
+This meant this stuff is not completely incompatible after all, it didn't
+crash right away though that was exactly what I expected it to do.
+I digged in Raven's multiplayer source that they released (only the virtual
+machine stuff, to allow for building modifications) and compared it to
+quake3's virtual machines and realized that there was a small
+incompatibility in one of the data structures used to pass information
+between engine and virtual machine. It was nothing big and after fixing this
+the menu worked!
+There were some quirks here or there, but most of the menu really worked.
+So it got me thinking: If I fix all these incompatibilities.. maybe I can
+finally play my beloved multiplayer game I've been clinging to for over 5
+years on my favorite OS natively.. and IPv6 support for EliteForce would be
+pretty cool too...
+So a crazy idea was turned into a serious project. I had to add support for
+Raven's models, playing mp3s, EliteForce's own network protocol. My goal was
+to make this release as close to the original as possible. Most of the time,
+I only could guess what names and functions would mean to the engine or I
+had to compare the original game and then try to make it work the same way
+in my engine.
+
+The quake3 game relies heavily on floating point operations. Unfortunately,
+the original EliteForce engine does non-ISO compliant rounding of floating
+point numbers to integers in the VMs.
+The game VM uses that flaw which will result in higher jumping for certain
+com_maxfps settings. As with the new engine there are many platforms that
+can be supported, there are probably many different ways one has to take to
+revert the rounding to the old behaviour. This is nearly impossible to do,
+so I had to use a different approach: build new VMs.
+
+############
+### NEW! ###
+############
+
+Version 1.37:
+- Sound attenuation has been changed to nearly the original behaviour.
+
+- Ogg vorbis sound format is now supported natively by the engine.
+
+- The Ioquake3 project has included a download redirect option! Server
+  admins can now point with an URL where to download files from and the
+  client can download them. See the README-IO.txt file for more info on how
+  to use this.
+
+- Antiwarp feature: Makes movement of people with wrong packet settings
+  smooth. Enable it by setting cvar sv_antiWarp to 1.
+  It comes in two flavours:
+  sv_antiWarpBias 0 will hardly affect response to
+  user commands (shoot, move, etc.), but will lead to many prediction
+  errors.
+  sv_antiWarpBias 1 won't have the problem with prediction errors but will
+  add *a lot* of latency on misconfigured clients and slightly noticeable
+  latency even on correctly configured client.
+  A constant framerate and good connection is a must. This ensures that all
+  players appear smoothly and those that do not - if their command rate is
+  too unstable to compensate for - gain no advantage.
+  A correctly configured client is one that uses the same value or a divider
+  of com_maxfps for cl_maxpackets.
+
+Version 1.36:
+
+- There now is the possibility to revert the fastsky to EF's original color.
+  set cvar r_origfastsky and the color of fastsky will be the normal beige
+  you know.
+
+- Ignore system. This is actually not specific to my engine but included in
+  the VM updates in pak91.pk3. You can use it to ignore chat messages from
+  abusive players. The ingame menu has been extended so you can conveniently
+  add/remove players to/from your ignore list.
+  Three new commands have been introduced: ignore, unignore and unignoreall,
+  their names pretty much speak out for themselves.
+  If the ignore or unignore command is called without playername, the person
+  the crosshair is pointing at is affected. If you run it like:
+  "/ignore evil 1", all players with the string "evil" in their name are
+  affected. Colors in names will be stripped and don't affect the result at
+  all.
+  Of course, the ignore system is only available if the server has been
+  updated with the pak91.pk3.
+
+- On Windows, the settings and user specific data are saved in the "Document
+  and Settings" folder. The fs_homepath cvar indicates the exact position.
+  On most english systems, the folder is called:
+  C:\Documents and Settings\<username>\Local Settings\Application Data\STVEF
+  See README-IO.txt for more information.
+
+############################
+### GENERAL INSTRUCTIONS ###
+############################
+
+All players and server admins, no matter whether users of the old or new
+EliteForce engine should add the pak92.pk3 to their baseEF directories.
+If you have old pak files from older versions of this engine, delete them.
+The files to be deleted - if present - are:
+pak9.pk3, pak90.pk3 and pak91.pk3
+If this README is from an archive (zip or bzip2) or an automated installer
+the pak92.pk3 will already be included.. You can also find the file here:
+http://thilo.kickchat.com/efport-progress/bin/vm/
+Dedicated servers using my engine will yield a greatly impaired movement if
+this pak file is not installed.
+This pak only fixes a few obvious bugs but otherwise doesn't change gameplay
+at all.
+Modders please read information about this further below.
+
+#########################################
+### WINDOWS INSTALLATION INSTRUCTIONS ###
+#########################################
+
+Installing this on windows is pretty straightforward.
+If you don't have it already on your harddrive, you can install EliteForce
+using Raven's original installer. You must also install either the expansion
+pack or the official patch to upgrade your installation to version 1.2.
+
+Once you have done all this, run the windows installer.  The installer
+will ask you for an installation path.  This path should be where your
+stvoyHM.exe file resides.  The default is to the Elite Force default
+installation folder.  The installer will also double check to be sure
+you've chosen the correct location.  Once the installer completes you
+will find a new group in your start menu called "Elite Force Holomatch 1.37"
+With shortcuts to run the game using the new patch and shortcuts to this
+read me file.
+
+After installing, a new file named iostvoyHM-1.37.exe has been created. If
+you want to use my improved engine you must start this one instead of the
+original stvoyHM.exe.
+
+This release comes with OpenAL support for sound which improves sound for
+most users. The two .dll files OpenAL32.dll and wrap_oal.dll are included
+with the installer and are automatically unpacked to your EliteForce
+directory if you did everything correctly.
+The OpenAL driver included is based on svn revision 1348 that you can get
+from www.openal.org if you're interested in the source code.
+If there is a new official release with more recent drivers you can always
+remove the two sound dlls from this project and install the vanilla OpenAL
+drivers from www.openal.org.
+Keep in mind, that OpenAL support is still somewhat experimental. For alot
+of people OpenAL gives a dramatical improvement in sound.
+Still, depending on the hardware and drivers in use, sound may be unusual or
+even worse with OpenAL. If you don't like it, you can always turn off OpenAL
+support by disabling it in the sound settings.
+Since version 1.35 some changes have happened in the way OpenAL gets used.
+Default settings will now make OpenAL work well on most hardware setups. If
+you had sound problems with previous versions, this release will likely fix
+them for you. Device enumeration support has been implemented, so you now
+have the choice between different devices.
+For most people, two devices are available: "Generic Hardware" and
+"Generic Software". Previous versions had "Generic Hardware" as default
+which uses DirectSound 3D and was often causing troubles with OpenAL. If you
+don't belong to these users, you can switch back by selecting the device in
+the sound configuration menu.
+
+#######################################
+### LINUX INSTALLATION INSTRUCTIONS ###
+#######################################
+
+Prerequisites:
+ * A working hardware accelerated OpenGL setup 
+   (DRI, fireglx, nvidia-glx...)
+ * libSDL - Simple Direct Layer libraries
+ * libmad - MPEG Audio Decoder (also known as MAD sometimes).
+ * libvorbis, libogg, libvorbisfile - OGG Vorbis audio decoder
+Optional:
+ * OpenAL - OpenAL sound libraries
+ * libcurl - FTP/HTTP download support.
+
+You can fullfill these dependencies by installing the correct packages from
+your favorite distribution's packet manager.
+
+There's a loki installer available that installs all the relevant files for
+you in an automated manner. The installer covers both, binaries for 64 bit
+and 32 bit systems so there's no split-up into two archives anymore.
+The installer offers you to copy the pak*.pk3 files from the original
+EliteForce CDs. If you don't want this to happen for some reason, see the
+.pk3 file copying instructions in the manual installation instructions a few
+lines down.
+
+This is the location of the installer:
+http://thilo.kickchat.com/efport-progress/bin/linux/io_eliteforce-1.37.run
+Run it in a shell like:
+sh iostvoyHM-1.37.run
+
+If you have an old hmconfig.cfg from windows, don't add it to baseef but to
+your home directory in ~/.stvef/baseEF/
+Speaking of that dir, the hidden directory where user specific config
+files/maps/mods will be stored is - as you may have guessed by now -
+.stvef in your home directory.
+
+Should the installer fail for some reason you can still install manually:
+
+Create a new eliteforce directory, you will probably want to use a dir like:
+/usr/local/games/stvef
+
+Copy a build of this engine that you can get from
+http://thilo.kickchat.com/efport-progress/bin/
+into the new directory.
+Also copy any directories from MODs you installed previously on windows to
+this directory.
+
+Create a subdirectory named "baseEF" (case sensitive!!) and copy the
+pak0.pk3, pak1.pk3 and pak2.pk3 from the original eliteforce
+release in there and don't forget the new pak91.pk3!
+pak1.pk3 and pak2.pk3 are files that have been released after the game went
+gold. You must either get them by installing the latest official EF patch on
+windows or you can get them from the expansion pack cd.
+pak3.pk3 can only be found on the expansion pack CD. If you want to have the
+maps and additions from the expension pack, you must copy this file as well.
+
+########################
+### For MOD creators ###
+########################
+
+I spoke about modifications necessary to get the old movement.
+Unfortunately, you will have to do these modifications to your mods too if
+you want your mod to run on my dedicated server version and don't want the
+users to get too frustrated over slowness.
+
+The problem is in the SnapVector macro located in q_shared.h:
+It uses casting a float to int using the (int) cast. The ISO standard
+requires the decimal places to be cut off and the number truncated. Thus,
+3,4 is converted to 3 or 5,9 is converted to 5.
+This is what happens in my engine.
+In EliteForce though, a 5,9 will be converted to 6 which is not standard
+compliant and will ultimately result in faster movement. This - among other
+factors - is the cause for framerate dependent jumping out of tranches, etc.
+What one could see as flaw many players now have learnt to rely upon.
+
+I have started a codebase where all modders can start from that fixes some
+known bugs and the movement so that everything works like in the original
+EF. Even if you have already changed much code, there is a way you can
+quickly insert the changes into your MOD, too. I created sourcecode patches
+that take care of the bugs.
+
+At this time, there are already a couple of bugfixes that have been added to
+the codebase. For instance, bots can now join password protected servers,
+the demo selection menu now has scrollbars (thanks to TiM), the EF LCARS
+patch from Lt. Cmdr. Salinga has been applied. A more complete
+list can be found here:
+http://svn.kickchat.com/index.cgi/stvoy/trunk/ChangeLog?view=log
+
+The patch can be found here:
+http://thilo.kickchat.com/efport-progress/patches/stvoyVM-bugfixes-1.37.diff
+You can also check out my source code on
+http://svn.kickchat.com/index.cgi/stvoy/trunk/
+
+The patch can be applied using the "patch" tool under Linux. For Windows,
+I recommend that you install TortoiseSVN which is an excellent tool for
+accessing subversion projects. It has also got the ability to create and
+merge patches:
+http://tortoisesvn.tigris.org/
+
+Quick instructions for Windows users to integrate my improvements into your
+mod:
+
+- Check out the repository at revision 1:
+  svn co svn://kickchat.com/stvoy/trunk stvoy
+  You must make sure that you really check out the very first revision!
+- Overwrite all source files in that newly checked out directory with the
+  source files from your mod. Make sure the ".svn" directories are left
+  intact.
+- Create a patch using the TortoiseSVN context menu in Windows Explorer. The
+  patch should then contain all modifications you did to Raven's original
+  VMs.
+- Check out the same repository into a new directory, but this time the
+  latest revision (HEAD).
+- Apply the patch you created to the new dir using TortoiseSVN.
+  If you're lucky and didn't change too much, everything will work fine. If
+  you're unlucky, there will be conflicts that you have to resolve manually.
+  For that you need to go into the conflicted files with an editor and
+  search for the string "mine". It will first show you your version, then
+  the one from the repository. Try to integrate these changes into your MOD.
+- Build
+- Be sure to add the language .dat files (you find them in baseef/ext_data
+  in the subversion repository) in your pk3.
+
+That's pretty much all you have to do. If you see that there are more
+bugfixes included in my repository at a later time, you can use TortoiseSVN
+to upgrade to this version. All changes are automatically merged into your
+mod.
+
+########################################################################
+## For Engine fiddlers and Gentoo-I-compile-everything-myself-freaks ###
+########################################################################
+
+Since icculus.org's quake3 engine is GPL'ed, all my modifications are freely
+available in the form of patches.
+
+a) You must get a recent revision of ioquake3
+   - see http://www.icculus.org/quake3
+
+b) Download the most recent patch that modifies the code
+   - see http://thilo.kickchat.com/efport-progress/patches/
+
+c) Apply the patch
+   - Linux users do: patch -p0 < thepatchname.diff in the main sourcedir
+   - Windows users must install seperate tools like TortoiseSVN that have
+     the ability to apply unix-style patches.
+
+Linux users:
+d) Make sure you got all packages needed, especially the -dev packages.
+   You need the header files for libmad, libSDL, libopenal and libGL
+   
+e) You may need to edit the Makefile to make use of a gcc version < 4.
+   gcc 4.0.x is not advisable if you need stability.
+
+f) Type in "make debug" for a version with debugging symbols or "make" for a
+   release version. If all goes well, the new binaries will be found in the
+   build/ subdir.
+
+Windows users (will take a bit longer, experienced coders only):
+d) Open up the project (project files can be found in code\win32\msvc\)
+e) You need to compile the libmad library from:
+   http://sourceforge.net/projects/mad
+   so that you have a .lib file you can link against
+f) If you compile and it complains about a missing dinput.h you need the
+   DirectX SDK
+g) If you want to have OpenAL you need the OpenAL SDK, too.
+h) Back to your MSVC environment:
+   look at the renderer and botlib subproject and modify the preprocessor
+   definitions in a way so that ELITEFORCE is defined (#define ELITEFORCE),
+   remove _DEBUG in the release version and add NDEBUG (only in release)
+i) Same goes to the main quake3 subproject, also add the define:
+   USE_CODEC_MP3=1 and USE_OPENAL=1;USE_OPENAL_DLOPEN=1 (the last two ones
+   only when you want OpenAL support).
+j) Add all include and library directories to the compiler/linker like
+   OpenAL include/library dir, MAD include/library dir, etc...
+k) You may need to specify additional libraries in the linker dependencies
+   like user32.lib Advapi32.lib ole32.lib etc...
+l) Build.
+
+Good luck!
+
+###############
+### Credits ###
+###############
+
+My thanks go out to alot of people who were helpful in creating my mod:
+
+ - A special thanks goes to TiM from the RPG-X project who helped with alot
+   of information
+
+ - The guys on the RPG-X board (Sharky, Scooter...)
+
+ - CoreFusion for a bit of testing in the beginning :)
+
+ - Skinner&Neural Link for infos about the MDR model format.
+
+ - Thomas Sahling aka Lt. Cmdr. Salinga for the source code to his LCARS
+   patch.
+
+ - Brian Shaffer aka Shafe for the windows installer.
+
+ -- Thilo Schulz (arny@ats.s.bawue.de)
Index: Makefile.local
===================================================================
--- Makefile.local	(revision 0)
+++ Makefile.local	(revision 0)
@@ -0,0 +1,11 @@
+BUILD_GAME_SO=0
+BUILD_GAME_QVM=0
+BUILD_CLIENT_SMP=0
+#BUILD_CLIENT=0
+USE_CODEC_VORBIS=1
+USE_CODEC_MP3=1
+USE_OPENAL=1
+USE_OPENAL_DLOPEN=1
+USE_CURL=1
+USE_CURL_DLOPEN=1
+BUILD_ELITEFORCE=1
Index: code/unix/unix_shared.c
===================================================================
--- code/unix/unix_shared.c	(revision 965)
+++ code/unix/unix_shared.c	(working copy)
@@ -390,10 +390,18 @@
             
 	if ((p = getenv("HOME")) != NULL) {
 		Q_strncpyz(homePath, p, sizeof(homePath));
-#ifdef MACOS_X
+#ifdef ELITEFORCE
+  #ifdef MACOS_X
+		Q_strcat(homePath, sizeof(homePath), "/Library/Application Support/STVEF");
+  #else
+		Q_strcat(homePath, sizeof(homePath), "/.stvef");
+  #endif
+#else
+  #ifdef MACOS_X
 		Q_strcat(homePath, sizeof(homePath), "/Library/Application Support/Quake3");
-#else
+  #else
 		Q_strcat(homePath, sizeof(homePath), "/.q3a");
+  #endif
 #endif
 		if (mkdir(homePath, 0777)) {
 			if (errno != EEXIST) 
Index: code/win32/win_shared.c
===================================================================
--- code/win32/win_shared.c	(revision 965)
+++ code/win32/win_shared.c	(working copy)
@@ -311,7 +311,11 @@
 		return NULL;
 	}
 	Q_strncpyz( path, szPath, sizeof(path) );
+#ifdef ELITEFORCE
+	Q_strcat( path, sizeof(path), "\\STVEF" );
+#else
 	Q_strcat( path, sizeof(path), "\\Quake3" );
+#endif
 	FreeLibrary(shfolder);
 	if( !CreateDirectory( path, NULL ) )
 	{
Index: code/win32/msvc/quake3.vcproj
===================================================================
--- code/win32/msvc/quake3.vcproj	(revision 965)
+++ code/win32/msvc/quake3.vcproj	(working copy)
@@ -1916,6 +1916,9 @@
 				RelativePath="..\..\client\snd_codec_wav.c">
 			</File>
 			<File
+				RelativePath="..\..\client\snd_codec_mp3.c">
+			</File>
+			<File
 				RelativePath="..\..\client\snd_codec_ogg.c">
 			</File>
 			<File
Index: code/server/sv_world.c
===================================================================
--- code/server/sv_world.c	(revision 965)
+++ code/server/sv_world.c	(working copy)
@@ -222,28 +222,88 @@
 	// encode the size into the entityState_t for client prediction
 	if ( gEnt->r.bmodel ) {
 		gEnt->s.solid = SOLID_BMODEL;		// a solid_box will never create this value
+#ifdef ELITEFORCE
+	} else if ( gEnt->r.contents & ( CONTENTS_SOLID | CONTENTS_BODY | CONTENTS_SHOTCLIP ) ) {
+		if(gEnt->r.svFlags & SVF_SHIELD_BBOX)
+		{
+			if(gEnt->s.time2 & (1 << 24))
+			{
+				i = gEnt->r.maxs[0];
+				if (i<1)
+					i = 1;
+					if (i>255)
+					i = 255;
+
+				// z is not symetric
+				j = -gEnt->r.mins[0];
+				if (j<1)
+					j = 1;
+				if (j>255)
+					j = 255;
+
+				// and z maxs can be negative...
+				k = gEnt->r.maxs[2];
+				if (k<1)
+					k = 1;
+				if (k>255)
+					k = 255;
+
+				gEnt->s.eFlags |= EF_SHIELD_BOX_X;
+			}
+			else
+			{
+				i = gEnt->r.maxs[1];
+				if (i<1)
+					i = 1;
+					if (i>255)
+					i = 255;
+
+				// z is not symetric
+				j = -gEnt->r.mins[1];
+				if (j<1)
+					j = 1;
+				if (j>255)
+					j = 255;
+
+				// and z maxs can be negative...
+				k = gEnt->r.maxs[2];
+				if (k<1)
+					k = 1;
+				if (k>255)
+					k = 255;
+
+				gEnt->s.eFlags |= EF_SHIELD_BOX_Y;
+			}
+		}
+		else
+		{
+#else
 	} else if ( gEnt->r.contents & ( CONTENTS_SOLID | CONTENTS_BODY ) ) {
-		// assume that x/y are equal and symetric
-		i = gEnt->r.maxs[0];
-		if (i<1)
-			i = 1;
-		if (i>255)
-			i = 255;
+#endif
+			// assume that x/y are equal and symetric
+			i = gEnt->r.maxs[0];
+			if (i<1)
+				i = 1;
+			if (i>255)
+				i = 255;
 
-		// z is not symetric
-		j = (-gEnt->r.mins[2]);
-		if (j<1)
-			j = 1;
-		if (j>255)
-			j = 255;
+			// z is not symetric
+			j = (-gEnt->r.mins[2]);
+			if (j<1)
+				j = 1;
+			if (j>255)
+				j = 255;
 
-		// and z maxs can be negative...
-		k = (gEnt->r.maxs[2]+32);
-		if (k<1)
-			k = 1;
-		if (k>255)
-			k = 255;
-
+			// and z maxs can be negative...
+			k = (gEnt->r.maxs[2]+32);
+			if (k<1)
+				k = 1;
+			if (k>255)
+				k = 255;
+#ifdef ELITEFORCE
+		}
+#endif
+		
 		gEnt->s.solid = (k<<16) | (j<<8) | i;
 	} else {
 		gEnt->s.solid = 0;
Index: code/server/sv_game.c
===================================================================
--- code/server/sv_game.c	(revision 965)
+++ code/server/sv_game.c	(working copy)
@@ -351,9 +351,10 @@
 		return 0;
 	case G_FS_GETFILELIST:
 		return FS_GetFileList( VMA(1), VMA(2), VMA(3), args[4] );
+#ifndef ELITEFORCE
 	case G_FS_SEEK:
 		return FS_Seek( args[1], args[2], args[3] );
-
+#endif
 	case G_LOCATE_GAME_DATA:
 		SV_LocateGameData( VMA(1), args[2], args[3], VMA(4), args[5] );
 		return 0;
@@ -373,14 +374,18 @@
 		return SV_AreaEntities( VMA(1), VMA(2), VMA(3), args[4] );
 	case G_ENTITY_CONTACT:
 		return SV_EntityContact( VMA(1), VMA(2), VMA(3), /*int capsule*/ qfalse );
+#ifndef ELITEFORCE
 	case G_ENTITY_CONTACTCAPSULE:
 		return SV_EntityContact( VMA(1), VMA(2), VMA(3), /*int capsule*/ qtrue );
+#endif
 	case G_TRACE:
 		SV_Trace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], /*int capsule*/ qfalse );
 		return 0;
+#ifndef ELITEFORCE
 	case G_TRACECAPSULE:
 		SV_Trace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], /*int capsule*/ qtrue );
 		return 0;
+#endif
 	case G_POINT_CONTENTS:
 		return SV_PointContents( VMA(1), args[2] );
 	case G_SET_BRUSH_MODEL:
@@ -439,12 +444,13 @@
 	case G_DEBUG_POLYGON_DELETE:
 		BotImport_DebugPolygonDelete( args[1] );
 		return 0;
+#ifndef ELITEFORCE
 	case G_REAL_TIME:
 		return Com_RealTime( VMA(1) );
 	case G_SNAPVECTOR:
 		Sys_SnapVector( VMA(1) );
 		return 0;
-
+#endif
 		//====================================
 
 	case BOTLIB_SETUP:
@@ -456,6 +462,10 @@
 	case BOTLIB_LIBVAR_GET:
 		return botlib_export->BotLibVarGet( VMA(1), VMA(2), args[3] );
 
+#ifdef ELITEFORCE
+	case BOTLIB_DEFINE:
+		return botlib_export->PC_AddGlobalDefine( VMA(1) );
+#else
 	case BOTLIB_PC_ADD_GLOBAL_DEFINE:
 		return botlib_export->PC_AddGlobalDefine( VMA(1) );
 	case BOTLIB_PC_LOAD_SOURCE:
@@ -466,7 +476,7 @@
 		return botlib_export->PC_ReadTokenHandle( args[1], VMA(2) );
 	case BOTLIB_PC_SOURCE_FILE_AND_LINE:
 		return botlib_export->PC_SourceFileAndLine( args[1], VMA(2), VMA(3) );
-
+#endif
 	case BOTLIB_START_FRAME:
 		return botlib_export->BotLibStartFrame( VMF(1) );
 	case BOTLIB_LOAD_MAP:
@@ -483,13 +493,14 @@
 	case BOTLIB_USER_COMMAND:
 		SV_ClientThink( &svs.clients[args[1]], VMA(2) );
 		return 0;
-
+#ifndef ELITEFORCE
 	case BOTLIB_AAS_BBOX_AREAS:
 		return botlib_export->aas.AAS_BBoxAreas( VMA(1), VMA(2), VMA(3), args[4] );
 	case BOTLIB_AAS_AREA_INFO:
 		return botlib_export->aas.AAS_AreaInfo( args[1], VMA(2) );
 	case BOTLIB_AAS_ALTERNATIVE_ROUTE_GOAL:
 		return botlib_export->aas.AAS_AlternativeRouteGoals( VMA(1), args[2], VMA(3), args[4], args[5], VMA(6), args[7], args[8] );
+#endif
 	case BOTLIB_AAS_ENTITY_INFO:
 		botlib_export->aas.AAS_EntityInfo( args[1], VMA(2) );
 		return 0;
@@ -504,8 +515,10 @@
 
 	case BOTLIB_AAS_POINT_AREA_NUM:
 		return botlib_export->aas.AAS_PointAreaNum( VMA(1) );
+#ifndef ELITEFORCE
 	case BOTLIB_AAS_POINT_REACHABILITY_AREA_INDEX:
 		return botlib_export->aas.AAS_PointReachabilityAreaIndex( VMA(1) );
+#endif
 	case BOTLIB_AAS_TRACE_AREAS:
 		return botlib_export->aas.AAS_TraceAreas( VMA(1), VMA(2), VMA(3), VMA(4), args[5] );
 
@@ -527,11 +540,12 @@
 
 	case BOTLIB_AAS_AREA_TRAVEL_TIME_TO_GOAL_AREA:
 		return botlib_export->aas.AAS_AreaTravelTimeToGoalArea( args[1], VMA(2), args[3], args[4] );
+#ifndef ELITEFORCE
 	case BOTLIB_AAS_ENABLE_ROUTING_AREA:
 		return botlib_export->aas.AAS_EnableRoutingArea( args[1], args[2] );
 	case BOTLIB_AAS_PREDICT_ROUTE:
 		return botlib_export->aas.AAS_PredictRoute( VMA(1), args[2], VMA(3), args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11] );
-
+#endif
 	case BOTLIB_AAS_SWIMMING:
 		return botlib_export->aas.AAS_Swimming( VMA(1) );
 	case BOTLIB_AAS_PREDICT_CLIENT_MOVEMENT:
@@ -548,9 +562,11 @@
 		botlib_export->ea.EA_Command( args[1], VMA(2) );
 		return 0;
 
+#ifndef ELITEFORCE
 	case BOTLIB_EA_ACTION:
 		botlib_export->ea.EA_Action( args[1], args[2] );
 		break;
+#endif
 	case BOTLIB_EA_GESTURE:
 		botlib_export->ea.EA_Gesture( args[1] );
 		return 0;
@@ -680,7 +696,11 @@
 		botlib_export->ai.BotSetChatGender( args[1], args[2] );
 		return 0;
 	case BOTLIB_AI_SET_CHAT_NAME:
+#ifdef ELITEFORCE
+		botlib_export->ai.BotSetChatName( args[1], VMA(2));
+#else
 		botlib_export->ai.BotSetChatName( args[1], VMA(2), args[3] );
+#endif
 		return 0;
 
 	case BOTLIB_AI_RESET_GOAL_STATE:
@@ -730,9 +750,11 @@
 		return botlib_export->ai.BotGetMapLocationGoal( VMA(1), VMA(2) );
 	case BOTLIB_AI_AVOID_GOAL_TIME:
 		return FloatAsInt( botlib_export->ai.BotAvoidGoalTime( args[1], args[2] ) );
+#ifndef ELITEFORCE
 	case BOTLIB_AI_SET_AVOID_GOAL_TIME:
 		botlib_export->ai.BotSetAvoidGoalTime( args[1], args[2], VMF(3));
 		return 0;
+#endif
 	case BOTLIB_AI_INIT_LEVEL_ITEMS:
 		botlib_export->ai.BotInitLevelItems();
 		return 0;
@@ -762,9 +784,11 @@
 	case BOTLIB_AI_RESET_MOVE_STATE:
 		botlib_export->ai.BotResetMoveState( args[1] );
 		return 0;
+#ifndef ELITEFORCE
 	case BOTLIB_AI_ADD_AVOID_SPOT:
 		botlib_export->ai.BotAddAvoidSpot( args[1], VMA(2), VMF(3), args[4] );
 		return 0;
+#endif
 	case BOTLIB_AI_MOVE_TO_GOAL:
 		botlib_export->ai.BotMoveToGoal( VMA(1), args[2], VMA(3), args[4] );
 		return 0;
@@ -852,7 +876,23 @@
 	case TRAP_CEIL:
 		return FloatAsInt( ceil( VMF(1) ) );
 
-
+#ifdef ELITEFORCE
+	case BOTLIB_EA_USE_ITEM:
+		botlib_export->ea.EA_UseItem(args[1], VMA(2));
+		return 0;
+	case BOTLIB_EA_DROP_ITEM:
+		botlib_export->ea.EA_DropItem(args[1], VMA(2));
+		return 0;
+	case BOTLIB_EA_USE_INV:
+		botlib_export->ea.EA_UseInv(args[1], VMA(2));
+		return 0;
+	case BOTLIB_EA_DROP_INV:
+		botlib_export->ea.EA_DropInv(args[1], VMA(2));
+		return 0;
+	case BOTLIB_EA_ALT_ATTACK:
+		botlib_export->ea.EA_Attack( args[1] );
+		return 0;
+#endif
 	default:
 		Com_Error( ERR_DROP, "Bad game system trap: %i", args[0] );
 	}
Index: code/server/sv_client.c
===================================================================
--- code/server/sv_client.c	(revision 965)
+++ code/server/sv_client.c	(working copy)
@@ -88,6 +88,17 @@
 		return;
 	}
 
+#ifdef ELITEFORCE
+	NET_OutOfBandPrint( NS_SERVER, challenge->adr, 
+		"challengeResponse %i", challenge->challenge );
+#else	
+	// if they are on a lan address, send the challengeResponse immediately
+	if ( Sys_IsLANAddress( from ) ) {
+		challenge->pingTime = svs.time;
+		NET_OutOfBandPrint( NS_SERVER, from, "challengeResponse %i", challenge->challenge );
+		return;
+	}
+
 	// look up the authorize server's IP
 	if ( !svs.authorizeAddress.ip[0] && svs.authorizeAddress.type != NA_BAD ) {
 		Com_Printf( "Resolving %s\n", AUTHORIZE_SERVER_NAME );
@@ -133,6 +144,7 @@
 			"getIpAuthorize %i %i.%i.%i.%i %s 0 %s",  svs.challenges[i].challenge,
 			from.ip[0], from.ip[1], from.ip[2], from.ip[3], game, sv_strictAuth->string );
 	}
+#endif
 }
 
 /*
@@ -247,7 +259,12 @@
 	Q_strncpyz( userinfo, Cmd_Argv(1), sizeof(userinfo) );
 
 	version = atoi( Info_ValueForKey( userinfo, "protocol" ) );
-	if ( version != PROTOCOL_VERSION ) {
+#ifdef ELITEFORCE
+	if(version != EFPROTOCOL_VERSION && version != PROTOCOL_VERSION)
+#else
+	if ( version != PROTOCOL_VERSION )
+#endif
+	{
 		NET_OutOfBandPrint( NS_SERVER, from, "print\nServer uses protocol version %i.\n", PROTOCOL_VERSION );
 		Com_DPrintf ("    rejected connect from version %i\n", version);
 		return;
@@ -408,6 +425,7 @@
 	ent = SV_GentityNum( clientNum );
 	newcl->gentity = ent;
 
+
 	// save the challenge
 	newcl->challenge = challenge;
 
@@ -416,6 +434,15 @@
 	// init the netchan queue
 	newcl->netchan_end_queue = &newcl->netchan_start_queue;
 
+#ifdef ELITEFORCE
+	if(version == EFPROTOCOL_VERSION)
+	{
+		newcl->compat = qtrue;
+		newcl->netchan.compat = qtrue;
+	}
+#endif
+
+
 	// save the userinfo
 	Q_strncpyz( newcl->userinfo, userinfo, sizeof(newcl->userinfo) );
 
@@ -509,7 +536,12 @@
 	VM_Call( gvm, GAME_CLIENT_DISCONNECT, drop - svs.clients );
 
 	// add the disconnect command
-	SV_SendServerCommand( drop, "disconnect \"%s\"", reason);
+#ifdef ELITEFORCE
+	if(drop->compat)
+		SV_SendServerCommand( drop, "disconnect %s", reason);
+	else
+#endif
+		SV_SendServerCommand( drop, "disconnect \"%s\"", reason);
 
 	if ( drop->netchan.remoteAddress.type == NA_BOT ) {
 		SV_BotFreeClient( drop - svs.clients );
@@ -560,11 +592,23 @@
 	// gamestate message was not just sent, forcing a retransmit
 	client->gamestateMessageNum = client->netchan.outgoingSequence;
 
-	MSG_Init( &msg, msgBuffer, sizeof( msgBuffer ) );
+#ifdef ELITEFORCE
+	if(client->compat)
+		MSG_InitOOB(&msg, msgBuffer, sizeof( msgBuffer ) );
+	else
+#endif
+		MSG_Init( &msg, msgBuffer, sizeof( msgBuffer ) );
 
+#ifdef ELITEFORCE
+	msg.compat = client->compat;
+#endif
+
 	// NOTE, MRE: all server->client messages now acknowledge
 	// let the client know which reliable clientCommands we have received
-	MSG_WriteLong( &msg, client->lastClientCommand );
+#ifdef ELITEFORCE
+	if(!msg.compat)
+#endif
+		MSG_WriteLong( &msg, client->lastClientCommand );
 
 	// send any server commands waiting to be sent first.
 	// we have to do this cause we send the client->reliableSequence
@@ -596,9 +640,17 @@
 		MSG_WriteDeltaEntity( &msg, &nullstate, base, qtrue );
 	}
 
-	MSG_WriteByte( &msg, svc_EOF );
+#ifdef ELITEFORCE
+	if(msg.compat)
+		MSG_WriteByte(&msg, 0);
+	else
+#endif	
+		MSG_WriteByte( &msg, svc_EOF );
 
-	MSG_WriteLong( &msg, client - svs.clients);
+#ifdef ELITEFORCE
+	if(!msg.compat)
+#endif
+		MSG_WriteLong( &msg, client - svs.clients);
 
 	// write the checksum feed
 	MSG_WriteLong( &msg, sv.checksumFeed);
@@ -760,7 +812,10 @@
 	int curindex;
 	int rate;
 	int blockspersnap;
-	int idPack = 0, missionPack = 0, unreferenced = 1;
+	int idPack = 0, unreferenced = 1;
+#ifndef ELITEFORCE
+	int missionPack = 0;
+#endif
 	char errorMessage[1024];
 	char pakbuf[MAX_QPATH], *pakptr;
 	int numRefPaks;
@@ -795,8 +850,12 @@
 
 						// now that we know the file is referenced,
 						// check whether it's legal to download it.
+						#ifdef ELITEFORCE
+						idPack = FS_idPak(pakbuf, BASEGAME);
+						#else
 						missionPack = FS_idPak(pakbuf, "missionpack");
 						idPack = missionPack || FS_idPak(pakbuf, BASEGAME);
+						#endif
 
 						break;
 					}
@@ -816,6 +875,10 @@
 				Com_sprintf(errorMessage, sizeof(errorMessage), "File \"%s\" is not referenced and cannot be downloaded.", cl->downloadName);
 			}
 			else if (idPack) {
+#ifdef ELITEFORCE
+				Com_Printf("clientDownload: %d : \"%s\" cannot download Raven pk3 files\n", cl - svs.clients, cl->downloadName);
+				Com_sprintf(errorMessage, sizeof(errorMessage), "Cannot autodownload Raven pk3 file \"%s\"", cl->downloadName);
+#else
 				Com_Printf("clientDownload: %d : \"%s\" cannot download id pk3 files\n", cl - svs.clients, cl->downloadName);
 				if (missionPack) {
 					Com_sprintf(errorMessage, sizeof(errorMessage), "Cannot autodownload Team Arena file \"%s\"\n"
@@ -824,6 +887,7 @@
 				else {
 					Com_sprintf(errorMessage, sizeof(errorMessage), "Cannot autodownload id pk3 file \"%s\"", cl->downloadName);
 				}
+#endif
 			}
 			else if ( !(sv_allowDownload->integer & DLF_ENABLE) ||
 				(sv_allowDownload->integer & DLF_NO_UDP) ) {
@@ -848,7 +912,10 @@
 			MSG_WriteByte( msg, svc_download );
 			MSG_WriteShort( msg, 0 ); // client is expecting block zero
 			MSG_WriteLong( msg, -1 ); // illegal file size
-			MSG_WriteString( msg, errorMessage );
+			#ifdef ELITEFORCE
+				if(!msg->compat)
+			#endif
+					MSG_WriteString( msg, errorMessage );
 
 			*cl->downloadName = 0;
 			return;
@@ -1022,21 +1089,28 @@
 		// start at arg 2 ( skip serverId cl_paks )
 		nCurArg = 1;
 
-		pArg = Cmd_Argv(nCurArg++);
-		if(!pArg) {
-			bGood = qfalse;
-		}
-		else
+		#ifdef ELITEFORCE
+		if(!cl->compat)
 		{
-			// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=475
-			// we may get incoming cp sequences from a previous checksumFeed, which we need to ignore
-			// since serverId is a frame count, it always goes up
-			if (atoi(pArg) < sv.checksumFeedServerId)
+		#endif
+			pArg = Cmd_Argv(nCurArg++);
+			if(!pArg) {
+				bGood = qfalse;
+			}
+			else
 			{
-				Com_DPrintf("ignoring outdated cp command from client %s\n", cl->name);
-				return;
+				// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=475
+				// we may get incoming cp sequences from a previous checksumFeed, which we need to ignore
+				// since serverId is a frame count, it always goes up
+				if (atoi(pArg) < sv.checksumFeedServerId)
+				{
+					Com_DPrintf("ignoring outdated cp command from client %s\n", cl->name);
+					return;
+				}
 			}
+		#ifdef ELITEFORCE
 		}
+		#endif
 	
 		// we basically use this while loop to avoid using 'goto' :)
 		while (bGood) {
@@ -1383,7 +1457,10 @@
 ==================
 */
 static void SV_UserMove( client_t *cl, msg_t *msg, qboolean delta ) {
-	int			i, key;
+	int			i;
+#ifndef ELITEFORCE
+	int			key;
+#endif
 	int			cmdCount;
 	usercmd_t	nullcmd;
 	usercmd_t	cmds[MAX_PACKET_USERCMDS];
@@ -1407,6 +1484,7 @@
 		return;
 	}
 
+	#ifndef ELITEFORCE
 	// use the checksum feed in the key
 	key = sv.checksumFeed;
 	// also use the message acknowledge
@@ -1414,11 +1492,17 @@
 	// also use the last acknowledged server command in the key
 	key ^= Com_HashKey(cl->reliableCommands[ cl->reliableAcknowledge & (MAX_RELIABLE_COMMANDS-1) ], 32);
 
+	#endif
+
 	Com_Memset( &nullcmd, 0, sizeof(nullcmd) );
 	oldcmd = &nullcmd;
 	for ( i = 0 ; i < cmdCount ; i++ ) {
 		cmd = &cmds[i];
+		#ifdef ELITEFORCE
+		MSG_ReadDeltaUsercmd( msg, oldcmd, cmd );
+		#else
 		MSG_ReadDeltaUsercmdKey( msg, key, oldcmd, cmd );
+		#endif
 		oldcmd = cmd;
 	}
 
@@ -1498,7 +1582,10 @@
 	int			c;
 	int			serverId;
 
-	MSG_Bitstream(msg);
+#ifdef ELITEFORCE
+	if(!msg->compat)
+		MSG_Bitstream(msg);
+#endif
 
 	serverId = MSG_ReadLong( msg );
 	cl->messageAcknowledge = MSG_ReadLong( msg );
@@ -1563,9 +1650,12 @@
 	// read optional clientCommand strings
 	do {
 		c = MSG_ReadByte( msg );
-		if ( c == clc_EOF ) {
+		#ifdef ELITEFORCE
+		if(msg->compat && c == -1)
+			c = clc_EOF;
+		#endif
+		if ( c == clc_EOF )
 			break;
-		}
 		if ( c != clc_clientCommand ) {
 			break;
 		}
Index: code/server/sv_net_chan.c
===================================================================
--- code/server/sv_net_chan.c	(revision 965)
+++ code/server/sv_net_chan.c	(working copy)
@@ -24,6 +24,7 @@
 #include "../qcommon/qcommon.h"
 #include "server.h"
 
+#ifndef ELITEFORCE
 /*
 ==============
 SV_Netchan_Encode
@@ -125,6 +126,7 @@
 		*(msg->data + i) = *(msg->data + i) ^ key;
 	}
 }
+#endif
 
 /*
 =================
@@ -144,7 +146,9 @@
 			netchan_buffer_t *netbuf;
 			Com_DPrintf("#462 Netchan_TransmitNextFragment: popping a queued message for transmit\n");
 			netbuf = client->netchan_start_queue;
+			#ifndef ELITEFORCE
 			SV_Netchan_Encode( client, &netbuf->msg );
+			#endif
 			Netchan_Transmit( &client->netchan, netbuf->msg.cursize, netbuf->msg.data );
 			// pop from queue
 			client->netchan_start_queue = netbuf->next;
@@ -172,7 +176,11 @@
 */
 
 void SV_Netchan_Transmit( client_t *client, msg_t *msg) {	//int length, const byte *data ) {
-	MSG_WriteByte( msg, svc_EOF );
+	#ifdef ELITEFORCE
+	if(!msg->compat)
+	#endif
+		MSG_WriteByte( msg, svc_EOF );
+	
 	if (client->netchan.unsentFragments) {
 		netchan_buffer_t *netbuf;
 		Com_DPrintf("#462 SV_Netchan_Transmit: unsent fragments, stacked\n");
@@ -186,7 +194,9 @@
 		// emit the next fragment of the current message for now
 		Netchan_TransmitNextFragment(&client->netchan);
 	} else {
+#ifndef ELITEFORCE
 		SV_Netchan_Encode( client, msg );
+#endif
 		Netchan_Transmit( &client->netchan, msg->cursize, msg->data );
 	}
 }
@@ -201,7 +211,9 @@
 	ret = Netchan_Process( &client->netchan, msg );
 	if (!ret)
 		return qfalse;
+#ifndef ELITEFORCE
 	SV_Netchan_Decode( client, msg );
+#endif
 	return qtrue;
 }
 
Index: code/server/sv_snapshot.c
===================================================================
--- code/server/sv_snapshot.c	(revision 965)
+++ code/server/sv_snapshot.c	(working copy)
@@ -154,6 +154,12 @@
 
 	MSG_WriteByte (msg, svc_snapshot);
 
+	#ifdef ELITEFORCE
+        if(msg->compat)
+        #endif
+		MSG_WriteLong( msg, client->lastClientCommand );
+                        
+
 	// NOTE, MRE: now sent at the start of every message from server to client
 	// let the client know which reliable clientCommands we have received
 	//MSG_WriteLong( msg, client->lastClientCommand );
@@ -417,6 +423,7 @@
 
 		// if its a portal entity, add everything visible from its camera position
 		if ( ent->r.svFlags & SVF_PORTAL ) {
+#ifndef ELITEFORCE
 			if ( ent->s.generic1 ) {
 				vec3_t dir;
 				VectorSubtract(ent->s.origin, origin, dir);
@@ -424,6 +431,7 @@
 					continue;
 				}
 			}
+#endif
 			SV_AddEntitiesVisibleFromPoint( ent->s.origin2, frame, eNums, qtrue );
 		}
 
@@ -636,12 +644,23 @@
 		return;
 	}
 
-	MSG_Init (&msg, msg_buf, sizeof(msg_buf));
+#ifdef ELITEFORCE
+	if(client->compat)
+	{
+		MSG_InitOOB(&msg, msg_buf, sizeof(msg_buf));
+		msg.compat = qtrue;
+	}
+	else
+#endif
+		MSG_Init (&msg, msg_buf, sizeof(msg_buf));
 	msg.allowoverflow = qtrue;
 
 	// NOTE, MRE: all server->client messages now acknowledge
 	// let the client know which reliable clientCommands we have received
-	MSG_WriteLong( &msg, client->lastClientCommand );
+#ifdef ELITEFORCE
+	if(!client->compat)
+#endif
+		MSG_WriteLong( &msg, client->lastClientCommand );
 
 	// (re)send any reliable server commands
 	SV_UpdateServerCommandsToClient( client, &msg );
Index: code/server/server.h
===================================================================
--- code/server/server.h	(revision 965)
+++ code/server/server.h	(working copy)
@@ -169,6 +169,8 @@
 
 	int				oldServerTime;
 	qboolean			csUpdated[MAX_CONFIGSTRINGS+1];	
+
+	qboolean		compat;		// compatibility mode for original EliteForce
 } client_t;
 
 //=============================================================================
Index: code/server/sv_init.c
===================================================================
--- code/server/sv_init.c	(revision 965)
+++ code/server/sv_init.c	(working copy)
@@ -625,7 +625,11 @@
 	Cvar_Get ("timelimit", "0", CVAR_SERVERINFO);
 	sv_gametype = Cvar_Get ("g_gametype", "0", CVAR_SERVERINFO | CVAR_LATCH );
 	Cvar_Get ("sv_keywords", "", CVAR_SERVERINFO);
+#ifdef ELITEFORCE
+	Cvar_Get ("protocol", va("%i", EFPROTOCOL_VERSION), CVAR_SERVERINFO | CVAR_ROM);
+#else
 	Cvar_Get ("protocol", va("%i", PROTOCOL_VERSION), CVAR_SERVERINFO | CVAR_ROM);
+#endif
 	sv_mapname = Cvar_Get ("mapname", "nomap", CVAR_SERVERINFO | CVAR_ROM);
 	sv_privateClients = Cvar_Get ("sv_privateClients", "0", CVAR_SERVERINFO);
 	sv_hostname = Cvar_Get ("sv_hostname", "noname", CVAR_SERVERINFO | CVAR_ARCHIVE );
@@ -649,7 +653,11 @@
 	// server vars
 	sv_rconPassword = Cvar_Get ("rconPassword", "", CVAR_TEMP );
 	sv_privatePassword = Cvar_Get ("sv_privatePassword", "", CVAR_TEMP );
+	#ifdef ELITEFORCE
+	sv_fps = Cvar_Get ("sv_fps", "20", CVAR_SYSTEMINFO | CVAR_TEMP);
+	#else
 	sv_fps = Cvar_Get ("sv_fps", "20", CVAR_TEMP );
+	#endif
 	sv_timeout = Cvar_Get ("sv_timeout", "200", CVAR_TEMP );
 	sv_zombietime = Cvar_Get ("sv_zombietime", "2", CVAR_TEMP );
 	Cvar_Get ("nextmap", "", CVAR_TEMP );
@@ -657,8 +665,13 @@
 	sv_allowDownload = Cvar_Get ("sv_allowDownload", "0", CVAR_SERVERINFO);
 	Cvar_Get ("sv_dlURL", "", CVAR_SERVERINFO | CVAR_ARCHIVE);
 	sv_master[0] = Cvar_Get ("sv_master1", MASTER_SERVER_NAME, 0 );
+	#ifdef ELITEFORCE
+	sv_master[1] = Cvar_Get ("sv_master2", "master.thewizclan.com", CVAR_ARCHIVE );
+	sv_master[2] = Cvar_Get ("sv_master3", "efmaster.kickchat.com", CVAR_ARCHIVE );
+	#else
 	sv_master[1] = Cvar_Get ("sv_master2", "", CVAR_ARCHIVE );
 	sv_master[2] = Cvar_Get ("sv_master3", "", CVAR_ARCHIVE );
+	#endif
 	sv_master[3] = Cvar_Get ("sv_master4", "", CVAR_ARCHIVE );
 	sv_master[4] = Cvar_Get ("sv_master5", "", CVAR_ARCHIVE );
 	sv_reconnectlimit = Cvar_Get ("sv_reconnectlimit", "3", 0);
@@ -698,7 +711,13 @@
 				// don't send a disconnect to a local client
 				if ( cl->netchan.remoteAddress.type != NA_LOOPBACK ) {
 					SV_SendServerCommand( cl, "print \"%s\n\"\n", message );
-					SV_SendServerCommand( cl, "disconnect" );
+					
+					#ifdef ELITEFORCE
+					if(cl->compat)
+						SV_SendServerCommand(cl, "disconnect Server shutdown.");
+					else
+					#endif
+						SV_SendServerCommand( cl, "disconnect" );
 				}
 				// force a snapshot to be sent
 				cl->nextSnapshotTime = -1;
Index: code/server/sv_main.c
===================================================================
--- code/server/sv_main.c	(revision 965)
+++ code/server/sv_main.c	(working copy)
@@ -222,7 +222,11 @@
 ================
 */
 #define	HEARTBEAT_MSEC	300*1000
+#ifdef ELITEFORCE
+#define HEARTBEAT_GAME "STEF1"
+#else
 #define	HEARTBEAT_GAME	"QuakeArena-1"
+#endif
 void SV_MasterHeartbeat( void ) {
 	static netadr_t	adr[MAX_MASTER_SERVERS];
 	int			i;
@@ -272,7 +276,12 @@
 		Com_Printf ("Sending heartbeat to %s\n", sv_master[i]->string );
 		// this command should be changed if the server info / status format
 		// ever incompatably changes
+		#ifdef ELITEFORCE
+		NET_OutOfBandPrint(NS_SERVER, adr[i], "\\heartbeat\\%d\\gamename\\%s\\",
+				   Cvar_VariableIntegerValue("net_port"),  HEARTBEAT_GAME);
+		#else
 		NET_OutOfBandPrint( NS_SERVER, adr[i], "heartbeat %s\n", HEARTBEAT_GAME );
+		#endif
 	}
 }
 
@@ -402,17 +411,22 @@
 
 	infostring[0] = 0;
 
-	// echo back the parameter to status. so servers can use it as a challenge
-	// to prevent timed spoofed reply packets that add ghost servers
-	Info_SetValueForKey( infostring, "challenge", Cmd_Argv(1) );
-
+#ifdef ELITEFORCE
+	Info_SetValueForKey( infostring, "protocol", va("%i", EFPROTOCOL_VERSION) );
+#else
 	Info_SetValueForKey( infostring, "protocol", va("%i", PROTOCOL_VERSION) );
+#endif
 	Info_SetValueForKey( infostring, "hostname", sv_hostname->string );
 	Info_SetValueForKey( infostring, "mapname", sv_mapname->string );
 	Info_SetValueForKey( infostring, "clients", va("%i", count) );
 	Info_SetValueForKey( infostring, "sv_maxclients", 
 		va("%i", sv_maxclients->integer - sv_privateClients->integer ) );
 	Info_SetValueForKey( infostring, "gametype", va("%i", sv_gametype->integer ) );
+
+	// echo back the parameter to status. so servers can use it as a challenge
+	// to prevent timed spoofed reply packets that add ghost servers
+	Info_SetValueForKey( infostring, "challenge", Cmd_Argv(1) );
+
 	Info_SetValueForKey( infostring, "pure", va("%i", sv_pure->integer ) );
 
 	if( sv_minPing->integer ) {
@@ -426,7 +440,15 @@
 		Info_SetValueForKey( infostring, "game", gamedir );
 	}
 
+	// echo back the parameter to status. so servers can use it as a challenge
+	// to prevent timed spoofed reply packets that add ghost servers
+	Info_SetValueForKey( infostring, "challenge", Cmd_Argv(1) );
+
+#ifdef ELITEFORCE
+	NET_OutOfBandPrint( NS_SERVER, from, "infoResponse \"%s\"", infostring );
+#else
 	NET_OutOfBandPrint( NS_SERVER, from, "infoResponse\n%s", infostring );
+#endif
 }
 
 /*
@@ -525,9 +547,11 @@
 	MSG_BeginReadingOOB( msg );
 	MSG_ReadLong( msg );		// skip the -1 marker
 
+#ifndef ELITEFORCE
 	if (!Q_strncmp("connect", (char *) &msg->data[4], 7)) {
 		Huff_Decompress(msg, 12);
 	}
+#endif
 
 	s = MSG_ReadStringLine( msg );
 	Cmd_TokenizeString( s );
@@ -603,6 +627,10 @@
 			cl->netchan.remoteAddress.port = from.port;
 		}
 
+		#ifdef ELITEFORCE
+		msg->compat = cl->compat;
+		#endif
+
 		// make sure it is a valid, in sequence packet
 		if (SV_Netchan_Process(cl, msg)) {
 			// zombie clients still need to do the Netchan_Process
Index: code/renderer/tr_scene.c
===================================================================
--- code/renderer/tr_scene.c	(revision 965)
+++ code/renderer/tr_scene.c	(working copy)
@@ -304,7 +304,9 @@
 		ri.Error (ERR_DROP, "R_RenderScene: NULL worldmodel");
 	}
 
+	#ifndef ELITEFORCE
 	Com_Memcpy( tr.refdef.text, fd->text, sizeof( tr.refdef.text ) );
+	#endif
 
 	tr.refdef.x = fd->x;
 	tr.refdef.y = fd->y;
Index: code/renderer/tr_local.h
===================================================================
--- code/renderer/tr_local.h	(revision 965)
+++ code/renderer/tr_local.h	(working copy)
@@ -149,7 +149,8 @@
 	GF_SAWTOOTH, 
 	GF_INVERSE_SAWTOOTH, 
 
-	GF_NOISE
+	GF_NOISE,
+	GF_RANDOM
 
 } genFunc_t;
 
@@ -962,6 +963,7 @@
 	float					triangleTable[FUNCTABLE_SIZE];
 	float					sawToothTable[FUNCTABLE_SIZE];
 	float					inverseSawToothTable[FUNCTABLE_SIZE];
+	float                                   noiseTable[FUNCTABLE_SIZE];
 	float					fogTable[FOG_TABLE_SIZE];
 } trGlobals_t;
 
@@ -1018,6 +1020,9 @@
 
 extern cvar_t	*r_inGameVideo;				// controls whether in game video should be draw
 extern cvar_t	*r_fastsky;				// controls whether sky should be cleared or drawn
+#ifdef ELITEFORCE
+extern cvar_t	*r_origfastsky;				// controls whether fastsky color is like in original EF.
+#endif
 extern cvar_t	*r_drawSun;				// controls drawing of sun quad
 extern cvar_t	*r_dynamiclight;		// dynamic lights enabled/disabled
 extern cvar_t	*r_dlightBacks;			// dlight non-facing surfaces for continuity
@@ -1108,6 +1113,7 @@
 //====================================================================
 
 float R_NoiseGet4f( float x, float y, float z, float t );
+int R_RandomOn( float t );
 void  R_NoiseInit( void );
 
 void R_SwapBuffers( int );
@@ -1235,6 +1241,9 @@
 qhandle_t		 RE_RegisterShaderLightMap( const char *name, int lightmapIndex );
 qhandle_t		 RE_RegisterShader( const char *name );
 qhandle_t		 RE_RegisterShaderNoMip( const char *name );
+#ifdef ELITEFORCE
+qhandle_t		 RE_RegisterShader3D( const char *name );
+#endif
 qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_t *image, qboolean mipRawImage);
 
 shader_t	*R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImage );
Index: code/renderer/tr_model.c
===================================================================
--- code/renderer/tr_model.c	(revision 965)
+++ code/renderer/tr_model.c	(working copy)
@@ -154,7 +154,9 @@
 		filesize = ri.FS_ReadFile(name, (void **) &buf);
 		if(!buf)
 		{
+			#ifdef _DEBUG
 			ri.Printf (PRINT_WARNING,"RE_RegisterModel: couldn't load %s\n", name);
+			#endif
 			mod->type = MOD_BAD;
 			return 0;
 		}
Index: code/renderer/tr_init.c
===================================================================
--- code/renderer/tr_init.c	(revision 965)
+++ code/renderer/tr_init.c	(working copy)
@@ -59,6 +59,9 @@
 
 cvar_t	*r_inGameVideo;
 cvar_t	*r_fastsky;
+#ifdef ELITEFORCE
+cvar_t	*r_origfastsky;
+#endif
 cvar_t	*r_drawSun;
 cvar_t	*r_dynamiclight;
 cvar_t	*r_dlightBacks;
@@ -210,6 +213,10 @@
 		
 		GLimp_Init();
 
+#ifdef ELITEFORCE
+		glConfig.textureFilterAnisotropicAvailable = textureFilterAnisotropic;
+#endif
+
 		strcpy( renderer_buffer, glConfig.renderer_string );
 		Q_strlwr( renderer_buffer );
 
@@ -957,7 +964,11 @@
 	r_displayRefresh = ri.Cvar_Get( "r_displayRefresh", "0", CVAR_LATCH );
 	AssertCvarRange( r_displayRefresh, 0, 200, qtrue );
 	r_fullbright = ri.Cvar_Get ("r_fullbright", "0", CVAR_LATCH|CVAR_CHEAT );
+#ifdef ELITEFORCE
+	r_mapOverBrightBits = ri.Cvar_Get ("r_mapOverBrightBits", "1", CVAR_LATCH );
+#else
 	r_mapOverBrightBits = ri.Cvar_Get ("r_mapOverBrightBits", "2", CVAR_LATCH );
+#endif
 	r_intensity = ri.Cvar_Get ("r_intensity", "1", CVAR_LATCH );
 	r_singleShader = ri.Cvar_Get ("r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH );
 
@@ -971,6 +982,9 @@
 	AssertCvarRange( r_znear, 0.001f, 200, qtrue );
 	r_ignoreGLErrors = ri.Cvar_Get( "r_ignoreGLErrors", "1", CVAR_ARCHIVE );
 	r_fastsky = ri.Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE );
+#ifdef ELITEFORCE
+	r_origfastsky = ri.Cvar_Get( "r_origfastsky", "0", CVAR_ARCHIVE );
+#endif
 	r_inGameVideo = ri.Cvar_Get( "r_inGameVideo", "1", CVAR_ARCHIVE );
 	r_drawSun = ri.Cvar_Get( "r_drawSun", "0", CVAR_ARCHIVE );
 	r_dynamiclight = ri.Cvar_Get( "r_dynamiclight", "1", CVAR_ARCHIVE );
@@ -1070,10 +1084,17 @@
 	Com_Memset( &backEnd, 0, sizeof( backEnd ) );
 	Com_Memset( &tess, 0, sizeof( tess ) );
 
+#ifdef ELITEFORCE
+	if(sizeof(glconfig_t) != 5192)
+	{
+		ri.Error( ERR_FATAL, "Mod ABI incompatible: sizeof(glconfig_t) == %zd != 5192", sizeof(glconfig_t));
+	}
+#else
 	if(sizeof(glconfig_t) != 11332)
 	{
 		ri.Error( ERR_FATAL, "Mod ABI incompatible: sizeof(glconfig_t) == %zd != 11332", sizeof(glconfig_t));
 	}
+#endif
 
 //	Swap_Init();
 
@@ -1082,6 +1103,8 @@
 	}
 	Com_Memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) );
 
+	R_NoiseInit();
+
 	//
 	// init function tables
 	//
@@ -1091,6 +1114,7 @@
 		tr.squareTable[i]	= ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f;
 		tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE;
 		tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i];
+		tr.noiseTable[i] = R_NoiseGet4f(0, 0, 0, i);
 
 		if ( i < FUNCTABLE_SIZE / 2 )
 		{
@@ -1111,8 +1135,6 @@
 
 	R_InitFogTable();
 
-	R_NoiseInit();
-
 	R_Register();
 
 	max_polys = r_maxpolys->integer;
@@ -1237,6 +1259,9 @@
 	re.RegisterSkin = RE_RegisterSkin;
 	re.RegisterShader = RE_RegisterShader;
 	re.RegisterShaderNoMip = RE_RegisterShaderNoMip;
+#ifdef ELITEFORCE
+	re.RegisterShader3D = RE_RegisterShader3D;
+#endif
 	re.LoadWorld = RE_LoadWorldMap;
 	re.SetWorldVisData = RE_SetWorldVisData;
 	re.EndRegistration = RE_EndRegistration;
Index: code/renderer/tr_shade_calc.c
===================================================================
--- code/renderer/tr_shade_calc.c	(revision 965)
+++ code/renderer/tr_shade_calc.c	(working copy)
@@ -43,6 +43,8 @@
 		return tr.sawToothTable;
 	case GF_INVERSE_SAWTOOTH:
 		return tr.inverseSawToothTable;
+	case GF_NOISE:
+		return tr.noiseTable;
 	case GF_NONE:
 	default:
 		break;
@@ -577,7 +579,9 @@
 		case DEFORM_TEXT5:
 		case DEFORM_TEXT6:
 		case DEFORM_TEXT7:
+#ifndef ELITEFORCE
 			DeformText( backEnd.refdef.text[ds->deformation - DEFORM_TEXT0] );
+#endif
 			break;
 		}
 	}
@@ -688,6 +692,8 @@
 
   if ( wf->func == GF_NOISE ) {
 		glow = wf->base + R_NoiseGet4f( 0, 0, 0, ( tess.shaderTime + wf->phase ) * wf->frequency ) * wf->amplitude;
+	} else if( wf->func == GF_RANDOM ) {
+		glow = wf->base + R_RandomOn( (tess.shaderTime + wf->phase) * wf->frequency ) * wf->amplitude;		
 	} else {
 		glow = EvalWaveForm( wf ) * tr.identityLight;
 	}
Index: code/renderer/tr_shader.c
===================================================================
--- code/renderer/tr_shader.c	(revision 965)
+++ code/renderer/tr_shader.c	(working copy)
@@ -294,6 +294,10 @@
 	{
 		return GF_NOISE;
 	}
+	else if( !Q_stricmp( funcname, "random" ) )
+	{
+		return GF_RANDOM;
+	}
 
 	ri.Printf( PRINT_WARNING, "WARNING: invalid genfunc name '%s' in shader '%s'\n", funcname, shader.name );
 	return GF_SIN;
@@ -742,6 +746,12 @@
 			{
 				depthFuncBits = 0;
 			}
+#ifdef ELITEFORCE
+			if ( !Q_stricmp( token, "disable" ) )
+			{
+				depthFuncBits = 0;
+			}
+#endif
 			else if ( !Q_stricmp( token, "equal" ) )
 			{
 				depthFuncBits = GLS_DEPTHFUNC_EQUAL;
@@ -2763,7 +2773,38 @@
 
 	return sh->index;
 }
+#ifdef ELITEFORCE
+/*
+====================
+RE_RegisterShader3D
 
+For explicitly defined shaders that need LIGHTMAP_NONE
+as lightmapIndex.
+====================
+*/
+qhandle_t RE_RegisterShader3D( const char *name ) {
+	shader_t	*sh;
+
+	if ( strlen( name ) >= MAX_QPATH ) {
+		Com_Printf( "Shader name exceeds MAX_QPATH\n" );
+		return 0;
+	}
+
+	sh = R_FindShader( name, LIGHTMAP_NONE, qfalse );
+
+	// we want to return 0 if the shader failed to
+	// load for some reason, but R_FindShader should
+	// still keep a name allocated for it, so if
+	// something calls RE_RegisterShader again with
+	// the same name, we don't try looking for it again
+	if ( sh->defaultShader ) {
+		return 0;
+	}
+
+	return sh->index;
+}
+#endif
+
 /*
 ====================
 R_GetShaderByHandle
Index: code/renderer/tr_light.c
===================================================================
--- code/renderer/tr_light.c	(revision 965)
+++ code/renderer/tr_light.c	(working copy)
@@ -294,6 +294,20 @@
 	}
 	ent->lightingCalculated = qtrue;
 
+#ifdef ELITEFORCE
+	if(ent->e.renderfx & RF_FULLBRIGHT)
+	{
+//		ent->ambientLight[0] = ent->ambientLight[1] = ent->ambientLight[1] = 0xFF;
+		((byte *)&ent->ambientLightInt)[0] = 0x7F;
+		((byte *)&ent->ambientLightInt)[1] = 0x7F;
+		((byte *)&ent->ambientLightInt)[2] = 0x7F;
+		((byte *)&ent->ambientLightInt)[3] = 0xFF;
+
+		ent->lightDir[0] = ent->lightDir[1] = ent->lightDir[2] = 0;
+		return;
+	}
+#endif
+
 	//
 	// trace a sample point down to find ambient light
 	//
Index: code/renderer/tr_types.h
===================================================================
--- code/renderer/tr_types.h	(revision 965)
+++ code/renderer/tr_types.h	(working copy)
@@ -32,6 +32,9 @@
 #define	RF_THIRD_PERSON		2		// don't draw through eyes, only mirrors (player bodies, chat sprites)
 #define	RF_FIRST_PERSON		4		// only draw through eyes (view weapon, damage blood blob)
 #define	RF_DEPTHHACK		8		// for view weapon Z crunching
+#ifdef ELITEFORCE
+#define RF_FULLBRIGHT	0x0010
+#endif
 #define	RF_NOSHADOW			64		// don't add stencil shadows
 
 #define RF_LIGHTING_ORIGIN	128		// use refEntity->lightingOrigin instead of refEntity->origin
@@ -42,6 +45,10 @@
 #define	RF_WRAP_FRAMES		512		// mod the model frames by the maxframes to allow continuous
 									// animation without needing to know the frame count
 
+#ifdef ELITEFORCE
+#define RF_FORCE_ENT_ALPHA 0x0800		// override shader alpha value and take the one from the entity.
+#endif
+
 // refdef flags
 #define RDF_NOWORLDMODEL	1		// used for player configuration screen
 #define RDF_HYPERSPACE		4		// teleportation effect
@@ -58,7 +65,28 @@
 	polyVert_t			*verts;
 } poly_t;
 
+#ifdef ELITEFORCE
 typedef enum {
+        RT_MODEL,
+        RT_SPRITE,
+        RT_ORIENTEDSPRITE,              // Replaces RT_POLY, which wasn't used. --Pat
+        RT_ALPHAVERTPOLY,               // Individual alpha levels on each vertex
+        RT_BEAM,
+        RT_RAIL_CORE,
+        RT_RAIL_RINGS,
+        RT_LIGHTNING,
+        RT_PORTALSURFACE,               // doesn't draw anything, just info for portals
+        RT_LINE,                                // New type for Trek MP --Pat
+        RT_ORIENTEDLINE,
+        RT_LINE2,                               // New line type for Trek MP, with taper support --Pat
+        RT_BEZIER,                              // what he said --keith
+        RT_CYLINDER,                    // Yet another Trek primitive!
+        RT_ELECTRICITY,                 // Yet another Trek primitive!
+
+        RT_MAX_REF_ENTITY_TYPE
+} refEntityType_t;
+#else
+typedef enum {
 	RT_MODEL,
 	RT_POLY,
 	RT_SPRITE,
@@ -70,6 +98,7 @@
 
 	RT_MAX_REF_ENTITY_TYPE
 } refEntityType_t;
+#endif
 
 typedef struct {
 	refEntityType_t	reType;
@@ -102,8 +131,49 @@
 	float		shaderTime;			// subtracted from refdef time to control effect start times
 
 	// extra sprite information
+#ifdef ELITEFORCE
+        union
+        {
+                struct
+                {
+                        float rotation;
+                        float radius;
+                        byte  vertRGBA[4][4];
+                } sprite;
+                struct
+                {
+                        float width;
+                        float width2;
+                        float stscale;
+                } line;
+                struct  // that whole put-the-opening-brace-on-the-same-line-as-the-beginning-of-the-definition coding style is fecal // I agree.
+                {
+                        float   width;
+                        vec3_t  control1;
+                        vec3_t  control2;
+                } bezier;
+                struct
+                {
+                        float width;
+                        float width2;
+                        float stscale;
+                        float height;
+                        float bias;
+                        qboolean wrap;
+                } cylinder;
+                struct
+                {
+                        float width;
+                        float deviation;
+                        float stscale;
+                        qboolean wrap;
+                        qboolean taper;
+                } electricity;
+        } data;
+#else
 	float		radius;
 	float		rotation;
+#endif
 } refEntity_t;
 
 
@@ -124,8 +194,10 @@
 	// 1 bits will prevent the associated area from rendering at all
 	byte		areamask[MAX_MAP_AREA_BYTES];
 
+#ifndef ELITEFORCE
 	// text messages for deform text shaders
 	char		text[MAX_RENDER_STRINGS][MAX_RENDER_STRING_LENGTH];
+#endif
 } refdef_t;
 
 
@@ -145,7 +217,10 @@
 */
 typedef enum {
 	TC_NONE,
-	TC_S3TC
+	TC_S3TC,
+#ifdef ELITEFORCE
+	TC_S3TC_DXT
+#endif
 } textureCompression_t;
 
 typedef enum {
@@ -172,7 +247,11 @@
 	char					renderer_string[MAX_STRING_CHARS];
 	char					vendor_string[MAX_STRING_CHARS];
 	char					version_string[MAX_STRING_CHARS];
+#ifdef ELITEFORCE
+	char					extensions_string[2*MAX_STRING_CHARS];
+#else
 	char					extensions_string[BIG_INFO_STRING];
+#endif
 
 	int						maxTextureSize;			// queried from GL
 	int						maxActiveTextures;		// multitexture ability
@@ -185,6 +264,9 @@
 	qboolean				deviceSupportsGamma;
 	textureCompression_t	textureCompression;
 	qboolean				textureEnvAddAvailable;
+#ifdef ELITEFORCE
+	qboolean				textureFilterAnisotropicAvailable;
+#endif
 
 	int						vidWidth, vidHeight;
 	// aspect is the screen's physical width / height, which may be different
Index: code/renderer/tr_noise.c
===================================================================
--- code/renderer/tr_noise.c	(revision 965)
+++ code/renderer/tr_noise.c	(working copy)
@@ -22,15 +22,18 @@
 // tr_noise.c
 #include "tr_local.h"
 
-#define NOISE_SIZE 256
+#define NOISE_SIZE FUNCTABLE_SIZE
 #define NOISE_MASK ( NOISE_SIZE - 1 )
 
 #define VAL( a ) s_noise_perm[ ( a ) & ( NOISE_MASK )]
+#define VALR( a ) s_random[ ( a ) & ( NOISE_MASK )]
 #define INDEX( x, y, z, t ) VAL( x + VAL( y + VAL( z + VAL( t ) ) ) )
 
 static float s_noise_table[NOISE_SIZE];
 static int s_noise_perm[NOISE_SIZE];
 
+static int s_random[NOISE_SIZE];
+
 #define LERP( a, b, w ) ( a * ( 1.0f - w ) + b * w )
 
 static float GetNoiseValue( int x, int y, int z, int t )
@@ -50,6 +53,8 @@
 	{
 		s_noise_table[i] = ( float ) ( ( ( rand() / ( float ) RAND_MAX ) * 2.0 - 1.0 ) );
 		s_noise_perm[i] = ( unsigned char ) ( rand() / ( float ) RAND_MAX * 255 );
+
+		s_random[i] = rand() & 0x01;
 	}
 }
 
@@ -93,3 +98,9 @@
 
 	return finalvalue;
 }
+
+// used in the shader functions (GF_RANDOM) to implement a quasi random flickering.
+int R_RandomOn(float t)
+{
+	return VALR((unsigned int) floor(t));
+}
Index: code/renderer/tr_public.h
===================================================================
--- code/renderer/tr_public.h	(revision 965)
+++ code/renderer/tr_public.h	(working copy)
@@ -49,6 +49,9 @@
 	qhandle_t (*RegisterSkin)( const char *name );
 	qhandle_t (*RegisterShader)( const char *name );
 	qhandle_t (*RegisterShaderNoMip)( const char *name );
+#ifdef ELITEFORCE
+	qhandle_t (*RegisterShader3D)( const char *name );
+#endif
 	void	(*LoadWorld)( const char *name );
 
 	// the vis data is a large enough block of data that we go to the trouble
Index: code/renderer/tr_main.c
===================================================================
--- code/renderer/tr_main.c	(revision 965)
+++ code/renderer/tr_main.c	(working copy)
@@ -968,18 +968,25 @@
 int R_SpriteFogNum( trRefEntity_t *ent ) {
 	int				i, j;
 	fog_t			*fog;
+	float radius;
 
 	if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
 		return 0;
 	}
 
+	#ifdef ELITEFORCE
+	radius = ent->e.data.sprite.radius;
+	#else
+	radius = ent->e.radius;
+	#endif
+
 	for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
 		fog = &tr.world->fogs[i];
 		for ( j = 0 ; j < 3 ; j++ ) {
-			if ( ent->e.origin[j] - ent->e.radius >= fog->bounds[1][j] ) {
+			if ( ent->e.origin[j] - radius >= fog->bounds[1][j] ) {
 				break;
 			}
-			if ( ent->e.origin[j] + ent->e.radius <= fog->bounds[0][j] ) {
+			if ( ent->e.origin[j] + radius <= fog->bounds[0][j] ) {
 				break;
 			}
 		}
@@ -1177,6 +1184,18 @@
 		switch ( ent->e.reType ) {
 		case RT_PORTALSURFACE:
 			break;		// don't draw anything
+
+#ifdef ELITEFORCE
+		case RT_ORIENTEDSPRITE:
+		case RT_ALPHAVERTPOLY:
+		case RT_LINE:
+		case RT_ORIENTEDLINE:
+		case RT_LINE2:
+		case RT_BEZIER:
+		case RT_CYLINDER:
+		case RT_ELECTRICITY:
+#endif
+
 		case RT_SPRITE:
 		case RT_BEAM:
 		case RT_LIGHTNING:
Index: code/renderer/tr_shade.c
===================================================================
--- code/renderer/tr_shade.c	(revision 965)
+++ code/renderer/tr_shade.c	(working copy)
@@ -1047,6 +1047,10 @@
 static void RB_IterateStagesGeneric( shaderCommands_t *input )
 {
 	int stage;
+#ifdef ELITEFORCE
+	qboolean overridealpha;
+	int oldalphaGen = 0;
+#endif
 
 	for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ )
 	{
@@ -1057,7 +1061,25 @@
 			break;
 		}
 
+		#ifdef ELITEFORCE
+		// Override the shader alpha channel if requested.
+		if(backEnd.currentEntity->e.renderfx & RF_FORCE_ENT_ALPHA)
+		{
+			overridealpha = qtrue;
+			oldalphaGen = pStage->alphaGen;
+			pStage->alphaGen = AGEN_ENTITY;
+		}
+		else
+			overridealpha = qfalse;
+		#endif
+
 		ComputeColors( pStage );
+		
+		#ifdef ELITEFORCE
+		if(overridealpha)
+			pStage->alphaGen = oldalphaGen;
+		#endif
+		
 		ComputeTexCoords( pStage );
 
 		if ( !setArraysOnce )
@@ -1090,7 +1112,15 @@
 			else 
 				R_BindAnimatedImage( &pStage->bundle[0] );
 
-			GL_State( pStage->stateBits );
+			#ifdef ELITEFORCE
+			if(overridealpha && backEnd.currentEntity->e.shaderRGBA[3] < 0xFF && !(pStage->stateBits & GLS_ATEST_BITS))
+			{
+				GL_State((pStage->stateBits & ~(GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS | GLS_ATEST_BITS))  // remove the shader set values.
+					 | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_ATEST_GT_0); // Now add the default values.
+			}
+			else
+			#endif
+				GL_State( pStage->stateBits );
 
 			//
 			// draw
Index: code/renderer/tr_backend.c
===================================================================
--- code/renderer/tr_backend.c	(revision 965)
+++ code/renderer/tr_backend.c	(working copy)
@@ -462,11 +462,18 @@
 	if ( r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) )
 	{
 		clearBits |= GL_COLOR_BUFFER_BIT;	// FIXME: only if sky shaders have been used
+#ifdef ELITEFORCE
+		if(r_origfastsky->integer)
+			qglClearColor(0.8f, 0.7f, 0.4f, 1.0f);
+		else
+			qglClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+#else
 #ifdef _DEBUG
 		qglClearColor( 0.8f, 0.7f, 0.4f, 1.0f );	// FIXME: get color of sky
 #else
 		qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f );	// FIXME: get color of sky
 #endif
+#endif
 	}
 	qglClear( clearBits );
 
Index: code/renderer/tr_surface.c
===================================================================
--- code/renderer/tr_surface.c	(revision 965)
+++ code/renderer/tr_surface.c	(working copy)
@@ -156,17 +156,25 @@
 static void RB_SurfaceSprite( void ) {
 	vec3_t		left, up;
 	float		radius;
+	float		rotation;
 
 	// calculate the xyz locations for the four corners
+	#ifdef ELITEFORCE
+	radius = backEnd.currentEntity->e.data.sprite.radius;
+	rotation = backEnd.currentEntity->e.data.sprite.rotation;
+	#else
 	radius = backEnd.currentEntity->e.radius;
-	if ( backEnd.currentEntity->e.rotation == 0 ) {
+	rotation = backEnd.currentEntity->e.rotation;
+	#endif
+
+	if ( rotation == 0 ) {
 		VectorScale( backEnd.viewParms.or.axis[1], radius, left );
 		VectorScale( backEnd.viewParms.or.axis[2], radius, up );
 	} else {
 		float	s, c;
 		float	ang;
 		
-		ang = M_PI * backEnd.currentEntity->e.rotation / 180;
+		ang = M_PI * rotation / 180;
 		s = sin( ang );
 		c = cos( ang );
 
@@ -549,7 +557,577 @@
 	}
 }
 
+#ifdef ELITEFORCE
+
 /*
+==============
+RB_SurfaceOrientedSprite
+==============
+*/
+static void RB_SurfaceOrientedSprite( void )
+{
+	vec3_t		left, up;
+	float		radius;
+	float		rotation;
+
+	// calculate the xyz locations for the four corners
+	radius = backEnd.currentEntity->e.data.sprite.radius;
+	rotation = backEnd.currentEntity->e.data.sprite.rotation;
+
+	if (rotation == 0)
+	{
+		VectorScale( backEnd.currentEntity->e.axis[1], radius, left );
+		VectorScale( backEnd.currentEntity->e.axis[2], radius, up );
+	}
+	else
+	{
+		float	s, c;
+		float	ang;
+		
+		ang = M_PI * rotation / 180;
+		s = sin( ang );
+		c = cos( ang );
+
+		VectorScale( backEnd.currentEntity->e.axis[1], c * radius, left );
+		VectorMA( left, -s * radius, backEnd.currentEntity->e.axis[2], left );
+
+		VectorScale( backEnd.currentEntity->e.axis[2], c * radius, up );
+		VectorMA( up, s * radius, backEnd.currentEntity->e.axis[1], up );
+	}
+	if ( backEnd.viewParms.isMirror )
+		VectorSubtract( vec3_origin, left, left );
+
+	RB_AddQuadStamp( backEnd.currentEntity->e.origin, left, up, backEnd.currentEntity->e.shaderRGBA );
+}
+
+void RB_Line(vec3_t start, vec3_t end, vec3_t linedirection, vec3_t left,
+	     vec3_t *corners, float starttex, float endtex, refEntity_t *e)
+{
+	int ndx, numind;
+	color4ub_t *vertcols;
+
+	RB_CHECKOVERFLOW( 4, 6 );
+
+	// Set up the triangles ..
+	ndx = tess.numVertexes;
+	numind = tess.numIndexes;
+
+	tess.indexes[ numind ] = ndx;
+	tess.indexes[ numind + 1 ] = ndx + 1;
+	tess.indexes[ numind + 2 ] = ndx + 3;
+
+	tess.indexes[ numind + 3 ] = ndx + 3;
+	tess.indexes[ numind + 4 ] = ndx + 1;
+	tess.indexes[ numind + 5 ] = ndx + 2;
+
+	// now create the corner vertices
+
+	if(corners)
+	{
+		// we have the corner points for the start already given.
+		VectorCopy(corners[0], tess.xyz[ndx]);
+		VectorCopy(corners[1], tess.xyz[ndx+1]);
+	}
+	else
+	{
+		// start left corner
+		VectorAdd(start, left, tess.xyz[ndx]);
+		// start right corner
+		VectorSubtract(start, left, tess.xyz[ndx+1]);
+	}
+	// end right corner
+	VectorSubtract(end, left, tess.xyz[ndx+2]);
+	// end left corner
+	VectorAdd(end, left, tess.xyz[ndx+3]);
+	
+	if(corners)
+	{
+		// save the end corner points here.
+		VectorCopy(tess.xyz[ndx+3], corners[0]);
+		VectorCopy(tess.xyz[ndx+2], corners[1]);
+	}
+
+	// Texture stuff....
+	tess.texCoords[ndx][0][0] = 0;
+	tess.texCoords[ndx][0][1] = starttex;
+
+	tess.texCoords[ndx+1][0][0] = 1;
+	tess.texCoords[ndx+1][0][1] = starttex;
+	
+	tess.texCoords[ndx+2][0][0] = 1;
+	tess.texCoords[ndx+2][0][1] = endtex;
+
+	tess.texCoords[ndx+3][0][0] = 0;
+	tess.texCoords[ndx+3][0][1] = endtex;
+
+	vertcols = tess.vertexColors;
+
+	vertcols[ndx][0] = vertcols[ndx+1][0] = vertcols[ndx+2][0] = vertcols[ndx+3][0] = e->shaderRGBA[0];
+	vertcols[ndx][1] = vertcols[ndx+1][1] = vertcols[ndx+2][1] = vertcols[ndx+3][1] = e->shaderRGBA[1];
+	vertcols[ndx][2] = vertcols[ndx+1][2] = vertcols[ndx+2][2] = vertcols[ndx+3][2] = e->shaderRGBA[2];
+	vertcols[ndx][3] = vertcols[ndx+1][3] = vertcols[ndx+2][3] = vertcols[ndx+3][3] = e->shaderRGBA[3];
+
+	tess.numVertexes += 4;
+	tess.numIndexes += 6;
+
+
+}
+
+// Create a normal vector and scale it to the right length
+void RB_LineNormal(vec3_t vec1, vec3_t vec2, float scale, vec3_t result)
+{
+	// Create the offset vector for the width of the line
+	CrossProduct(vec1, vec2, result);
+	// Normalize the offset vector first.
+	VectorNormalize(result);
+	// Scale the offset vector to the intended width.
+	VectorScale(result, scale / 2, result);
+}
+
+// Let's draw a thick line from A to B and dance happily around a christmas tree!
+void RB_SurfaceLine( void )
+{
+	refEntity_t *e;
+	vec3_t left;		// I vote the green party...
+	vec3_t start, end, linedirection, start2origin;
+	shader_t *surfshader;
+	
+	e = &backEnd.currentEntity->e;
+
+	// Getting up before 1:00 pm to attend HM I lectures finally paid off..
+
+	// Get the start and end point of the line
+	VectorCopy(e->origin, start);
+	VectorCopy(e->oldorigin, end);
+
+	// Direction vector for the line:
+	VectorSubtract(end, start, linedirection);
+	// Direction vector for the start to current point of view
+	VectorSubtract(backEnd.viewParms.or.origin, start, start2origin);
+
+	RB_LineNormal(start2origin, linedirection, e->data.line.width, left);
+	RB_Line(start, end, linedirection, left, NULL, 0, e->data.line.stscale, e); 
+
+	// Hack to make the dreadnought lightning bolt work: set the correct cull type...
+	if((surfshader = R_GetShaderByHandle(e->customShader)))
+		surfshader->cullType = CT_TWO_SIDED;
+}
+
+void RB_SurfaceOrientedLine(void)
+{
+	refEntity_t *e;
+	vec3_t left;
+	vec3_t linedirection;
+	shader_t *surfshader;
+
+	e = &backEnd.currentEntity->e;
+
+	VectorSubtract(e->oldorigin, e->origin, linedirection);
+
+	VectorCopy(e->axis[1], left);
+	VectorNormalize(left);
+	VectorScale(left, e->data.line.width / 2, left);
+	
+	RB_Line(e->origin, e->oldorigin, linedirection, left, NULL, 0, 1, e);
+
+	surfshader = R_GetShaderByHandle(e->customShader);
+	surfshader->cullType = CT_TWO_SIDED;
+
+}
+
+// This time it's not a rectangle but a trapezoid I guess ...
+void RB_SurfaceLine2( void )
+{
+	refEntity_t *e;
+	vec3_t startleft, endleft;		// I still vote the green party...
+	vec3_t start, end, linedirection, start2origin;
+	color4ub_t *vertcols;
+	int ndx, numind;
+	
+	RB_CHECKOVERFLOW( 6, 12 );
+	
+	e = &backEnd.currentEntity->e;
+
+	// Set up the triangle ..
+	ndx = tess.numVertexes;
+	numind = tess.numIndexes;
+
+	tess.indexes[ numind ] = ndx;
+	tess.indexes[ numind + 1 ] = ndx + 1;
+	tess.indexes[ numind + 2 ] = ndx + 5;
+	tess.indexes[ numind + 3 ] = ndx + 5;
+	tess.indexes[ numind + 4 ] = ndx + 4;
+	tess.indexes[ numind + 5 ] = ndx + 1;
+	tess.indexes[ numind + 6 ] = ndx + 1;
+	tess.indexes[ numind + 7 ] = ndx + 4;
+	tess.indexes[ numind + 8 ] = ndx + 3;
+	tess.indexes[ numind + 9 ] = ndx + 3;
+	tess.indexes[ numind + 10 ] = ndx + 2;
+	tess.indexes[ numind + 11 ] = ndx + 1;
+
+
+	// Get the start and end point of the line
+	VectorCopy(e->origin, start);
+	VectorCopy(e->oldorigin, end);
+
+	// Direction vector for the line:
+	VectorSubtract(end, start, linedirection);
+	// Direction vector for the start to current point of view
+	VectorSubtract(backEnd.viewParms.or.origin, start, start2origin);
+
+	// Create the offset vector for the width of the line
+	CrossProduct(start2origin, linedirection, startleft);
+	// Normalize the offset vector first.
+	VectorNormalize(startleft);
+	// The normal of the triangle we just thought up:
+
+
+	// Scale the offset vector to the intended width.
+	VectorScale(startleft, e->data.line.width2 / 2, endleft);
+	VectorScale(startleft, e->data.line.width / 2, startleft);
+
+	// now create the corner vertices
+
+	// start left corner
+	VectorAdd(start, startleft, tess.xyz[ndx]);
+	// start point
+	VectorCopy(start, tess.xyz[ndx+1]);
+	// start right corner
+	VectorSubtract(start, startleft, tess.xyz[ndx+2]);
+	// end right corner
+	VectorSubtract(end, endleft, tess.xyz[ndx+3]);
+	// end point
+	VectorCopy(end, tess.xyz[ndx+4]);
+	// end left corner	
+	VectorAdd(end, endleft, tess.xyz[ndx+5]);
+
+	// Texture stuff....
+	tess.texCoords[ndx][0][0] = 0;
+	tess.texCoords[ndx][0][1] = 0;
+
+	tess.texCoords[ndx+1][0][0] = 0.5;
+	tess.texCoords[ndx+1][0][1] = 0;
+	
+	tess.texCoords[ndx+2][0][0] = 1;
+	tess.texCoords[ndx+2][0][1] = 0;
+
+	tess.texCoords[ndx+3][0][0] = 1;
+	tess.texCoords[ndx+3][0][1] = 1;
+
+	tess.texCoords[ndx+4][0][0] = 0.5;
+	tess.texCoords[ndx+4][0][1] = 1;
+
+	tess.texCoords[ndx+5][0][0] = 0;
+	tess.texCoords[ndx+5][0][1] = 1;
+
+	vertcols = tess.vertexColors;
+
+	vertcols[ndx][0] = vertcols[ndx+1][0] = vertcols[ndx+2][0] =
+		vertcols[ndx+3][0] = vertcols[ndx+4][0] = vertcols[ndx+5][0] = e->shaderRGBA[0];
+	vertcols[ndx][1] = vertcols[ndx+1][1] = vertcols[ndx+2][1] =
+		vertcols[ndx+3][1] = vertcols[ndx+4][1] = vertcols[ndx+5][1] = e->shaderRGBA[1];
+	vertcols[ndx][2] = vertcols[ndx+1][2] = vertcols[ndx+2][2] =
+		vertcols[ndx+3][2] = vertcols[ndx+4][2] = vertcols[ndx+5][2] = e->shaderRGBA[2];
+	vertcols[ndx][3] = vertcols[ndx+1][3] = vertcols[ndx+2][3] =
+		vertcols[ndx+3][3] = vertcols[ndx+4][3] = vertcols[ndx+5][3] = e->shaderRGBA[3];
+
+	tess.numVertexes += 6;
+	tess.numIndexes += 12;
+}
+
+// Draw a cubic bezier curve for the imod weapon.
+#define BEZIER_SEGMENTS 32
+#define BEZIER_STEPSIZE 1.0 / BEZIER_SEGMENTS
+
+void RB_SurfaceBezier(void)
+{
+	refEntity_t *e = &backEnd.currentEntity->e;
+	double tvar = 0, one_tvar; // use double to not lose as much precision on cubing and squaring.
+	float starttc, endtc;
+	vec3_t segstartpos, segendpos, prevend[2];
+	vec3_t linedirection, start2origin, left;
+	int index;
+
+	VectorCopy(e->origin, segstartpos);
+
+	// start of the bezier curve is pointy
+	VectorCopy(segstartpos, prevend[0]);
+	VectorCopy(segstartpos, prevend[1]);
+	
+	// iterate through all segments we have to create.
+	while(tvar <= 1.0)
+	{
+		// get the texture position for the rectangular approximating the bezier curve.
+		starttc = tvar / 2.0;
+		tvar += BEZIER_STEPSIZE;
+		endtc = tvar / 2.0;
+
+		one_tvar = 1.0 - tvar;
+
+		// get the endpoint for this segment.
+
+		for(index = 0; index < 3; index++)
+		{
+			// C(t) = P0 (t-1)^3 + 3 P1 t (t-1)^2 + 3 P2 t^2 (t-1) + P3 t^3
+			segendpos[index] =
+					e->origin[index] * one_tvar * one_tvar * one_tvar +
+					3 * e->data.bezier.control1[index] * tvar * one_tvar * one_tvar +
+					3 * e->data.bezier.control2[index] * tvar * tvar * one_tvar +
+					e->oldorigin[index] * tvar * tvar * tvar;
+		}
+		
+		// Direction vector for the line:
+		VectorSubtract(segendpos, segstartpos, linedirection);
+		// Direction vector for the start to current point of view
+		VectorSubtract(backEnd.viewParms.or.origin, segstartpos, start2origin);
+
+		RB_LineNormal(start2origin, linedirection, e->data.bezier.width, left);
+		RB_Line(segstartpos, segendpos, linedirection, left, prevend, starttc, endtc, e);
+		
+		// Our next segment starts where the old one ends.
+		VectorCopy(segendpos, segstartpos);
+	}
+}
+
+// this actually isn't a cylinder but a frustum, but for the sake of naming
+// conventions we'll keep calling it a cylinder.
+
+// number of rectangles we'll use to approximate a frustum of a cone.
+#define CYLINDER_MAXPLANES 64
+#define LOD_CONSTANT	4.0f
+
+void RB_SurfaceCylinder(void)
+{
+	int planes, index = 0;	// calculate the number of planes based on the level of detail.
+	vec3_t bottom, top, bottom2top, zerodeg_bottom, zerodeg_top, faxis;
+	vec3_t bottomcorner, topcorner, vieworigin;
+	float anglestep, tcstep = 0, width, width2, height;
+	int ndx, numind;
+	color4ub_t *vertcols;
+	refEntity_t *e = &backEnd.currentEntity->e;
+	// for LOD calculation:
+	vec3_t bottom2origin, top2origin, lodcalc, projection;
+	float maxradius, startdistance, enddistance, distance;
+
+	height = e->data.cylinder.height;
+	width = e->data.cylinder.width;
+	width2 = e->data.cylinder.width2;
+	maxradius = (width > width2) ? width : width2;
+
+	// get the start and end point of the frustum:
+	
+	VectorCopy(backEnd.viewParms.or.origin, vieworigin);
+	VectorCopy(e->axis[0], faxis);
+	VectorCopy(e->origin, bottom);
+	VectorScale(faxis, height, bottom2top);
+	VectorAdd(bottom, bottom2top, top);
+
+	// Get distance from frustum:
+	// first distance from endpoints
+	VectorSubtract(vieworigin, bottom, bottom2origin);
+	VectorSubtract(vieworigin, top, top2origin);
+	
+	// get projection of view origin on the middle line:
+	distance = DotProduct(bottom2origin, faxis);
+	
+	startdistance = VectorLength(bottom2origin);
+	enddistance = VectorLength(top2origin);
+
+	if(distance < 0 || distance > height)
+	{
+		// projected point is not between bottom and top.
+		distance = (startdistance < enddistance) ? startdistance : enddistance;
+	}
+	else
+	{
+		VectorMA(bottom, distance, faxis, projection);
+		VectorSubtract(vieworigin, projection, lodcalc);
+		distance = VectorLength(lodcalc);
+	
+		if(startdistance < distance)
+			distance = startdistance;
+		if(enddistance < distance)
+			distance = enddistance;
+	}			
+	
+	planes = LOD_CONSTANT * maxradius/distance * CYLINDER_MAXPLANES;
+	
+	if(planes < 8)
+		planes = 8;
+	else if(planes > CYLINDER_MAXPLANES)
+		planes = CYLINDER_MAXPLANES;
+
+	RB_CHECKOVERFLOW(4 * planes, 6 * planes);
+
+	// create a normalized perpendicular vector to the frustum height.
+	PerpendicularVector(zerodeg_bottom, faxis);
+
+	// This vector gets rotated to create the top ring
+	VectorScale(zerodeg_bottom, width2 / 2.0f, zerodeg_top);
+	// Likewise the vector for the lower ring:
+	VectorScale(zerodeg_bottom, width / 2.0f, zerodeg_bottom);
+
+	anglestep = 360.0f / planes;
+	if(e->data.cylinder.wrap)
+		tcstep = e->data.cylinder.stscale / planes;
+	
+	ndx = tess.numVertexes;
+	numind = tess.numIndexes;
+	vertcols = tess.vertexColors;
+
+	// this loop is creating all surface planes.
+	while(index < planes)
+	{
+		index++;
+	
+		// Set up the indexes for the new plane:
+		tess.indexes[numind++] = ndx;
+		tess.indexes[numind++] = ndx + 2;
+		tess.indexes[numind++] = ndx + 3;
+		
+		tess.indexes[numind++] = ndx;
+		tess.indexes[numind++] = ndx + 3;
+		tess.indexes[numind++] = ndx + 1;
+		
+		if(index <= 1)
+		{
+			VectorAdd(bottom, zerodeg_bottom, tess.xyz[ndx]);
+			VectorAdd(top, zerodeg_top, tess.xyz[ndx + 1]);
+		}
+		else
+		{
+			VectorCopy(bottomcorner, tess.xyz[ndx]);
+			VectorCopy(topcorner, tess.xyz[ndx + 1]);
+		}
+
+		// Create on the right side two new vertices, first the bottom, then the top one.
+		if(index >= planes)
+		{
+			VectorAdd(bottom, zerodeg_bottom, bottomcorner);
+			VectorAdd(top, zerodeg_top, topcorner);
+		}
+		else
+		{
+			RotatePointAroundVector(bottomcorner, faxis, zerodeg_bottom, anglestep * index);
+			VectorAdd(bottom, bottomcorner, bottomcorner);
+			RotatePointAroundVector(topcorner, faxis, zerodeg_top, index * anglestep);
+			VectorAdd(top, topcorner, topcorner);
+		}
+		
+		VectorCopy(bottomcorner, tess.xyz[ndx + 2]);
+		VectorCopy(topcorner, tess.xyz[ndx + 3]);
+		
+		// Take care about the texture stuff
+		if(e->data.cylinder.wrap)
+		{
+			tess.texCoords[ndx][0][0] = tcstep * (index - 1);
+			tess.texCoords[ndx][0][1] = 0;
+			
+			tess.texCoords[ndx+1][0][0] = tcstep * (index - 1);
+			tess.texCoords[ndx+1][0][1] = 1;
+
+			tess.texCoords[ndx+2][0][0] = tcstep * index;
+			tess.texCoords[ndx+2][0][1] = 0;
+			
+			tess.texCoords[ndx+3][0][0] = tcstep * index;
+			tess.texCoords[ndx+3][0][1] = 1;
+		}
+		else
+		{
+			tess.texCoords[ndx][0][0] = 0;
+			tess.texCoords[ndx][0][1] = 0;
+			
+			tess.texCoords[ndx+1][0][0] = 0;
+			tess.texCoords[ndx+1][0][1] = 1;
+
+			tess.texCoords[ndx+2][0][0] = e->data.cylinder.stscale;
+			tess.texCoords[ndx+2][0][1] = 0;
+			
+			tess.texCoords[ndx+3][0][0] = e->data.cylinder.stscale;
+			tess.texCoords[ndx+3][0][1] = 1;
+		}
+
+		vertcols[ndx][0] = vertcols[ndx+1][0] = vertcols[ndx+2][0] = vertcols[ndx+3][0] = e->shaderRGBA[0];
+		vertcols[ndx][1] = vertcols[ndx+1][1] = vertcols[ndx+2][1] = vertcols[ndx+3][1] = e->shaderRGBA[1];
+		vertcols[ndx][2] = vertcols[ndx+1][2] = vertcols[ndx+2][2] = vertcols[ndx+3][2] = e->shaderRGBA[2];
+		vertcols[ndx][3] = vertcols[ndx+1][3] = vertcols[ndx+2][3] = vertcols[ndx+3][3] = 0xff;
+                               
+		ndx += 4;
+	}
+	
+	tess.numVertexes = ndx;
+	tess.numIndexes = numind;	
+}
+
+// Draws lightning using a multisegment line with jumpy connecting points.
+#define ELECTRICITY_SEGMENTS 16
+#define ELECTRICITY_STEPSIZE 1.0 / ELECTRICITY_SEGMENTS
+
+void RB_SurfaceElectricity(void)
+{
+	vec3_t start, end, linedirection, segstartpos, segendpos;
+	vec3_t prevend[2], left, start2origin, start2end;
+	refEntity_t *e = &backEnd.currentEntity->e;
+	float width, deviation, veclen;
+	int index;
+	
+	VectorCopy(e->origin, start);
+	VectorCopy(e->oldorigin, end);
+	VectorSubtract(end, start, start2end);
+	veclen = VectorLength(start2end);
+	
+	width = e->data.electricity.width;
+	deviation = e->data.electricity.deviation;
+
+	VectorCopy(start, segendpos);
+	
+	for(index = 0; index < ELECTRICITY_SEGMENTS; index++)
+	{
+		VectorCopy(segendpos, segstartpos);
+		
+		if(index > ELECTRICITY_SEGMENTS - 2)
+		{
+			// This is the last segment.
+			VectorCopy(end, segendpos);
+		}
+		else
+		{
+			if(index > ELECTRICITY_SEGMENTS - 3)
+			{
+				// The line should have somewhat deviated by now.
+				// Make the last two segments go to the endpoint
+
+				// get the middle point between startpos and endpos
+				VectorAdd(segstartpos, end, segendpos);
+				VectorScale(segendpos, 0.5f, segendpos);
+			}
+
+			// Slightly misplace the next point on the line.
+			segendpos[PITCH] += (start2end[PITCH] + crandom() * deviation * veclen) * ELECTRICITY_STEPSIZE;
+			segendpos[YAW] += (start2end[YAW] + crandom() * deviation * veclen) * ELECTRICITY_STEPSIZE;
+			segendpos[ROLL] += (start2end[ROLL] + crandom() * deviation * veclen / 2.0) * ELECTRICITY_STEPSIZE;
+		}
+
+		// Direction vector for the line:
+		VectorSubtract(segendpos, segstartpos, linedirection);
+		// Direction vector for the start to current point of view
+		VectorSubtract(backEnd.viewParms.or.origin, segstartpos, start2origin);
+		
+		RB_LineNormal(start2origin, linedirection, width, left);
+
+		if(!index)
+		{
+			// this is our first segment, create the starting points
+			VectorAdd(segstartpos, left, prevend[0]);
+			VectorSubtract(segstartpos, left, prevend[1]);
+		}
+		
+		RB_Line(segstartpos, segendpos, linedirection, left, prevend, 0, e->data.electricity.stscale, e);
+	}
+}
+#endif
+
+/*
 ** VectorArrayNormalize
 *
 * The inputs to this routing seem to always be close to length = 1.0 (about 0.6 to 2.0)
@@ -1144,7 +1722,6 @@
 	}
 }
 
-
 /*
 ===========================================================================
 
@@ -1188,6 +1765,9 @@
 */
 void RB_SurfaceEntity( surfaceType_t *surfType ) {
 	switch( backEnd.currentEntity->e.reType ) {
+#ifdef ELITEFORCE
+	case RT_ALPHAVERTPOLY:
+#endif
 	case RT_SPRITE:
 		RB_SurfaceSprite();
 		break;
@@ -1203,6 +1783,29 @@
 	case RT_LIGHTNING:
 		RB_SurfaceLightningBolt();
 		break;
+#ifdef ELITEFORCE
+	case RT_ORIENTEDSPRITE:
+		RB_SurfaceOrientedSprite();
+		break;
+	case RT_LINE:
+		RB_SurfaceLine();
+		break;
+	case RT_ORIENTEDLINE:
+		RB_SurfaceOrientedLine();
+		break;
+	case RT_LINE2:
+		RB_SurfaceLine2();
+		break;
+	case RT_BEZIER:
+		RB_SurfaceBezier();
+		break;
+	case RT_CYLINDER:
+		RB_SurfaceCylinder();
+		break;
+	case RT_ELECTRICITY:
+		RB_SurfaceElectricity();
+		break;
+#endif
 	default:
 		RB_SurfaceAxis();
 		break;
Index: code/qcommon/q_math.c
===================================================================
--- code/qcommon/q_math.c	(revision 965)
+++ code/qcommon/q_math.c	(working copy)
@@ -1230,7 +1230,11 @@
 	/*
 	** find the smallest magnitude axially aligned vector
 	*/
+#ifdef ELITEFORCE
+	for ( pos = 0, i = 2; i >= 0; i-- )
+#else
 	for ( pos = 0, i = 0; i < 3; i++ )
+#endif
 	{
 		if ( fabs( src[i] ) < minelem )
 		{
Index: code/qcommon/surfaceflags.h
===================================================================
--- code/qcommon/surfaceflags.h	(revision 965)
+++ code/qcommon/surfaceflags.h	(working copy)
@@ -41,6 +41,10 @@
 
 #define	CONTENTS_PLAYERCLIP		0x10000
 #define	CONTENTS_MONSTERCLIP	0x20000
+#ifdef ELITEFORCE
+#define CONTENTS_SHOTCLIP		0x40000
+#endif
+
 //bot specific contents types
 #define	CONTENTS_TELEPORTER		0x40000
 #define	CONTENTS_JUMPPAD		0x80000
Index: code/qcommon/cm_local.h
===================================================================
--- code/qcommon/cm_local.h	(revision 965)
+++ code/qcommon/cm_local.h	(working copy)
@@ -24,11 +24,16 @@
 #include "qcommon.h"
 #include "cm_polylib.h"
 
-#define	MAX_SUBMODELS			256
-#define	BOX_MODEL_HANDLE		255
-#define CAPSULE_MODEL_HANDLE	254
+#ifdef ELITEFORCE
+	#define	MAX_SUBMODELS			8192
+	#define	BOX_MODEL_HANDLE		MAX_SUBMODELS-1
+	#define CAPSULE_MODEL_HANDLE		BOX_MODEL_HANDLE-2
+#else
+	#define	MAX_SUBMODELS			256
+	#define	BOX_MODEL_HANDLE		255
+	#define CAPSULE_MODEL_HANDLE	254
+#endif
 
-
 typedef struct {
 	cplane_t	*plane;
 	int			children[2];		// negative numbers are leafs
Index: code/qcommon/net_chan.c
===================================================================
--- code/qcommon/net_chan.c	(revision 965)
+++ code/qcommon/net_chan.c	(working copy)
@@ -94,7 +94,7 @@
 }
 
 // TTimo: unused, commenting out to make gcc happy
-#if 0
+#ifdef ELITEFORCE
 /*
 ==============
 Netchan_ScramblePacket
@@ -109,7 +109,7 @@
 	int			i, j, c, mask, temp;
 	int			seq[MAX_PACKETLEN];
 
-	seed = ( LittleLong( *(unsigned *)buf->data ) * 3 ) ^ ( buf->cursize * 123 );
+	seed = ( LittleLong( *(unsigned *)buf->data ) * 3 ) ^ ( buf->cursize * 123 ) ^ 0x87243987;
 	c = buf->cursize;
 	if ( c <= SCRAMBLE_START ) {
 		return;
@@ -120,10 +120,15 @@
 
 	// generate a sequence of "random" numbers
 	for (i = 0 ; i < c ; i++) {
-		seed = (119 * seed + 1);
+		seed = (69069 * seed + 1);
 		seq[i] = seed;
 	}
 
+	// byte xor the data after the header
+	for (i = SCRAMBLE_START ; i < c ; i++) {
+		buf->data[i] ^= seq[i];
+	}
+
 	// transpose each character
 	for ( mask = 1 ; mask < c-SCRAMBLE_START ; mask = ( mask << 1 ) + 1 ) {
 	}
@@ -136,9 +141,9 @@
 	}
 
 	// byte xor the data after the header
-	for (i = SCRAMBLE_START ; i < c ; i++) {
-		buf->data[i] ^= seq[i];
-	}
+//	for (i = SCRAMBLE_START ; i < c ; i++) {
+//		buf->data[i] ^= seq[i];
+//	}
 }
 
 static void Netchan_UnScramblePacket( msg_t *buf ) {
@@ -146,7 +151,7 @@
 	int			i, j, c, mask, temp;
 	int			seq[MAX_PACKETLEN];
 
-	seed = ( LittleLong( *(unsigned *)buf->data ) * 3 ) ^ ( buf->cursize * 123 );
+	seed = ( LittleLong( *(unsigned *)buf->data ) * 3 ) ^ ( buf->cursize * 123 ) ^ 0x87243987;
 	c = buf->cursize;
 	if ( c <= SCRAMBLE_START ) {
 		return;
@@ -157,14 +162,14 @@
 
 	// generate a sequence of "random" numbers
 	for (i = 0 ; i < c ; i++) {
-		seed = (119 * seed + 1);
+		seed = (69069 * seed + 1);
 		seq[i] = seed;
 	}
 
 	// byte xor the data after the header
-	for (i = SCRAMBLE_START ; i < c ; i++) {
-		buf->data[i] ^= seq[i];
-	}
+//	for (i = SCRAMBLE_START ; i < c ; i++) {
+//		buf->data[i] ^= seq[i];
+//	}
 
 	// transpose each character in reverse order
 	for ( mask = 1 ; mask < c-SCRAMBLE_START ; mask = ( mask << 1 ) + 1 ) {
@@ -176,6 +181,12 @@
 		buf->data[j] = buf->data[i];
 		buf->data[i] = temp;
 	}
+
+
+	// byte xor the data after the header
+	for (i = SCRAMBLE_START ; i < c ; i++) {
+		buf->data[i] ^= seq[i];
+	}
 }
 #endif
 
@@ -211,6 +222,14 @@
 	MSG_WriteShort( &send, fragmentLength );
 	MSG_WriteData( &send, chan->unsentBuffer + chan->unsentFragmentStart, fragmentLength );
 
+	#ifdef ELITEFORCE
+	if(chan->compat)
+	{
+		// the original eliteforce uses the old scrambling routines only slightly modified.	
+		Netchan_ScramblePacket( &send );
+	}
+	#endif
+
 	// send the datagram
 	NET_SendPacket( chan->sock, send.cursize, send.data, chan->remoteAddress );
 
@@ -277,6 +296,14 @@
 
 	MSG_WriteData( &send, data, length );
 
+	#ifdef ELITEFORCE
+	if(chan->compat)
+	{
+		// the original eliteforce uses the old scrambling routines only slightly modified.	
+		Netchan_ScramblePacket( &send );
+	}
+	#endif
+
 	// send the datagram
 	NET_SendPacket( chan->sock, send.cursize, send.data, chan->remoteAddress );
 
@@ -308,7 +335,10 @@
 	qboolean	fragmented;
 
 	// XOR unscramble all data in the packet after the header
-//	Netchan_UnScramblePacket( msg );
+#ifdef ELITEFORCE
+	if(chan->compat)
+		Netchan_UnScramblePacket( msg );
+#endif
 
 	// get sequence numbers		
 	MSG_BeginReadingOOB( msg );
@@ -445,7 +475,10 @@
 
 		// TTimo
 		// clients were not acking fragmented messages
-		chan->incomingSequence = sequence;
+		#ifdef ELITEFORCE
+		if(!chan->compat)
+		#endif
+			chan->incomingSequence = sequence;
 		
 		return qtrue;
 	}
Index: code/qcommon/cm_patch.h
===================================================================
--- code/qcommon/cm_patch.h	(revision 965)
+++ code/qcommon/cm_patch.h	(working copy)
@@ -60,8 +60,8 @@
 */
 
 
-#define	MAX_FACETS			1024
-#define	MAX_PATCH_PLANES	2048
+#define	MAX_FACETS			4096
+#define	MAX_PATCH_PLANES	8192
 
 typedef struct {
 	float	plane[4];
Index: code/qcommon/q_shared.h
===================================================================
--- code/qcommon/q_shared.h	(revision 965)
+++ code/qcommon/q_shared.h	(working copy)
@@ -26,17 +26,30 @@
 // q_shared.h -- included first by ALL program modules.
 // A user mod should never modify this file
 
+#ifdef ELITEFORCE
+#define Q3_VERSION            "ioST:V HM v1.37"
+#define CLIENT_WINDOW_TITLE   "icculus.org/stvoyhm"
+#define CONSOLE_WINDOW_TITLE  "icculus.org/stvoyhm console"
+#else
 #define Q3_VERSION            "ioQ3 1.33"
+#define CLIENT_WINDOW_TITLE   "icculus.org/quake3"
+#define CONSOLE_WINDOW_TITLE  "icculus.org/quake3 console"
+#endif
+
 #ifndef SVN_VERSION
   #define SVN_VERSION Q3_VERSION
 #endif
-#define CLIENT_WINDOW_TITLE   "icculus.org/quake3"
+
 #define CLIENT_WINDOW_ICON    "ioq3"
-#define CONSOLE_WINDOW_TITLE  "icculus.org/quake3 console"
 #define CONSOLE_WINDOW_ICON   "ioq3 console"
+
 // 1.32 released 7-10-2002
 
+#ifdef ELITEFORCE
+#define BASEGAME              "baseEF"
+#else
 #define BASEGAME              "baseq3"
+#endif
 
 #define MAX_TEAMNAME 32
 
@@ -943,7 +956,11 @@
 #define	MAX_POWERUPS			16
 #define	MAX_WEAPONS				16		
 
+#ifdef ELITEFORCE
+#define MAX_PS_EVENTS			4
+#else
 #define	MAX_PS_EVENTS			2
+#endif
 
 #define PS_PMOVEFRAMECOUNTBITS	6
 
@@ -967,6 +984,11 @@
 	vec3_t		origin;
 	vec3_t		velocity;
 	int			weaponTime;
+#ifdef ELITEFORCE
+        int                     rechargeTime;           // for the phaser
+        short           useTime;                        // use debounce
+        int                     introTime;                      // for the holodoor
+#endif
 	int			gravity;
 	int			speed;
 	int			delta_angles[3];	// add to command angles to get view direction
@@ -985,7 +1007,9 @@
 								// when at rest, the value will remain unchanged
 								// used to twist the legs during strafing
 
+#ifndef ELITEFORCE
 	vec3_t		grapplePoint;	// location of grapple to pull towards if PMF_GRAPPLE_PULL
+#endif
 
 	int			eFlags;			// copied to entityState_t->eFlags
 
@@ -1009,20 +1033,27 @@
 	int			damageYaw;
 	int			damagePitch;
 	int			damageCount;
+#ifdef ELITEFORCE
+	int			damageShieldCount;
+#endif
 
 	int			stats[MAX_STATS];
 	int			persistant[MAX_PERSISTANT];	// stats that aren't cleared on death
 	int			powerups[MAX_POWERUPS];	// level.time that the powerup runs out
 	int			ammo[MAX_WEAPONS];
 
+#ifndef ELITEFORCE
 	int			generic1;
 	int			loopSound;
 	int			jumppad_ent;	// jumppad entity hit this frame
+#endif
 
 	// not communicated over the net at all
 	int			ping;			// server to game info for scoreboard
+#ifndef ELITEFORCE
 	int			pmove_framecount;	// FIXME: don't transmit over the network
 	int			jumppad_frame;
+#endif
 	int			entityEventSequence;
 } playerState_t;
 
@@ -1057,14 +1088,23 @@
 										// then BUTTON_WALKING should be set
 
 // usercmd_t is sent to the server each client frame
+#ifdef ELITEFORCE
 typedef struct usercmd_s {
+        int             serverTime;
+        byte    buttons;
+        byte    weapon;
+        int             angles[3];
+        signed char     forwardmove, rightmove, upmove;
+} usercmd_t;
+#else
+typedef struct usercmd_s {
 	int				serverTime;
 	int				angles[3];
 	int 			buttons;
 	byte			weapon;           // weapon 
 	signed char	forwardmove, rightmove, upmove;
 } usercmd_t;
-
+#endif
 //===================================================================
 
 // if entityState->solid == SOLID_BMODEL, modelindex is an inline model number
@@ -1135,7 +1175,9 @@
 	int		legsAnim;		// mask off ANIM_TOGGLEBIT
 	int		torsoAnim;		// mask off ANIM_TOGGLEBIT
 
+#ifndef ELITEFORCE
 	int		generic1;
+#endif
 } entityState_t;
 
 typedef enum {
Index: code/qcommon/files.c
===================================================================
--- code/qcommon/files.c	(revision 965)
+++ code/qcommon/files.c	(working copy)
@@ -200,8 +200,12 @@
 
 // every time a new demo pk3 file is built, this checksum must be updated.
 // the easiest way to get it is to just run the game and see what it spits out
+#ifdef ELITEFORCE
+#define PAK0_CHECKSUM				3376297517u
+#else
 #define	DEMO_PAK0_CHECKSUM	2985612116u
 #define	PAK0_CHECKSUM				1566731103u
+#endif
 
 // if this is defined, the executable positively won't work with any paks other
 // than the demo pak, even if productid is present.  This is only used for our
@@ -2629,9 +2633,14 @@
 		havepak = qfalse;
 
 		// never autodownload any of the id paks
+#ifdef ELITEFORCE
+		if(FS_idPak(fs_serverReferencedPakNames[i], BASEGAME))
+			continue;
+#else
 		if ( FS_idPak(fs_serverReferencedPakNames[i], BASEGAME) || FS_idPak(fs_serverReferencedPakNames[i], "missionpack") ) {
 			continue;
 		}
+#endif
 
 		// Make sure the server cannot make us write to non-quake3 directories.
 		if(FS_CheckDirTraversal(fs_serverReferencedPakNames[i]))
@@ -2862,6 +2871,7 @@
 	}
 
 	Com_ReadCDKey(BASEGAME);
+
 	fs = Cvar_Get ("fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO );
 	if (fs && fs->string[0] != 0) {
 		Com_AppendCDKey( fs->string );
@@ -2913,6 +2923,18 @@
 				!Q_stricmpn( path->pack->pakGamename, "demoq3", MAX_OSPATH ))) {
 			foundPak0 = qtrue;
 
+#ifdef ELITEFORCE
+			if(path->pack->checksum != PAK0_CHECKSUM)
+			{
+				Com_Printf("\n\n"
+						"**************************************************\n"
+						"WARNING: pak0.pk3 is present but its checksum (%u)\n"
+						"is not correct. Please re-copy pak0.pk3 from your\n"
+						"legitimate EF CDROM.\n"
+						"**************************************************\n\n\n",
+						path->pack->checksum);
+			}
+#else
 			if( path->pack->checksum == DEMO_PAK0_CHECKSUM ) {
 				Com_Printf( "\n\n"
 						"**************************************************\n"
@@ -2929,6 +2951,7 @@
 						"**************************************************\n\n\n",
 						path->pack->checksum );
 			}
+#endif
 		}
 	}
 
@@ -3374,7 +3397,11 @@
 	if ( Q_stricmp(fs_gamedirvar->string, lastValidGame) ) {
 		// skip the q3config.cfg if "safe" is on the command line
 		if ( !Com_SafeMode() ) {
+#ifdef ELITEFORCE
+			Cbuf_AddText("exec hmconfig.cfg\n");
+#else
 			Cbuf_AddText ("exec q3config.cfg\n");
+#endif
 		}
 	}
 
Index: code/qcommon/cm_trace.c
===================================================================
--- code/qcommon/cm_trace.c	(revision 965)
+++ code/qcommon/cm_trace.c	(working copy)
@@ -1164,6 +1164,12 @@
 	// fill in a default trace
 	Com_Memset( &tw, 0, sizeof(tw) );
 	tw.trace.fraction = 1;	// assume it goes the entire distance until shown otherwise
+#ifdef ELITEFORCE
+	// obviously Raven fucked this up. They seem to expect a SURF_NOIMPACT flag if the trace
+	// went through to the end, or the game will crash when firing the dreadnought weapon and
+	// it doesn't hit anything.
+	tw.trace.surfaceFlags = SURF_NOIMPACT;
+#endif
 	VectorCopy(origin, tw.modelOrigin);
 
 	if (!cm.numNodes) {
Index: code/qcommon/qcommon.h
===================================================================
--- code/qcommon/qcommon.h	(revision 965)
+++ code/qcommon/qcommon.h	(working copy)
@@ -23,6 +23,10 @@
 #ifndef _QCOMMON_H_
 #define _QCOMMON_H_
 
+#if defined(ELITEFORCE) && defined(MISSIONPACK)
+	#undef MISSIONPACK
+#endif
+
 #include "../qcommon/cm_public.h"
 
 //Ignore __attribute__ on non-gcc platforms
@@ -43,6 +47,9 @@
 	qboolean	allowoverflow;	// if false, do a Com_Error
 	qboolean	overflowed;		// set to true if the buffer size failed (with allowoverflow set)
 	qboolean	oob;			// set to true if the buffer size failed (with allowoverflow set)
+#ifdef ELITEFORCE
+	qboolean	compat;		// Compatibility mode for old EliteForce servers.
+#endif
 	byte	*data;
 	int		maxsize;
 	int		cursize;
@@ -207,6 +214,10 @@
 	int			unsentFragmentStart;
 	int			unsentLength;
 	byte		unsentBuffer[MAX_MSGLEN];
+
+#ifdef ELITEFORCE
+	qboolean	compat;
+#endif
 } netchan_t;
 
 void Netchan_Init( int qport );
@@ -226,23 +237,45 @@
 ==============================================================
 */
 
+#ifdef ELITEFORCE
+#define EFPROTOCOL_VERSION	24
+#define PROTOCOL_VERSION	25
+#else
 #define	PROTOCOL_VERSION	68
+#endif
 // 1.31 - 67
 
 // maintain a list of compatible protocols for demo playing
 // NOTE: that stuff only works with two digits protocols
 extern int demo_protocols[];
 
-#define	UPDATE_SERVER_NAME	"update.quake3arena.com"
 // override on command line, config files etc.
-#ifndef MASTER_SERVER_NAME
-#define MASTER_SERVER_NAME	"master.quake3arena.com"
+#ifdef ELITEFORCE
+  
+  #define	UPDATE_SERVER_NAME	"motd.stef1.ravensoft.com"
+  #ifndef MASTER_SERVER_NAME
+  #define MASTER_SERVER_NAME	"master.stef1.ravensoft.com"
+  #endif
+  #ifndef AUTHORIZE_SERVER_NAME
+  #define	AUTHORIZE_SERVER_NAME	"authenticate.stef1.ravensoft.com"
+  #endif
+
+  #define PORT_MASTER 27953
+
+#else
+
+  #define	UPDATE_SERVER_NAME	"update.quake3arena.com"
+  #ifndef MASTER_SERVER_NAME
+  #define MASTER_SERVER_NAME	"master.quake3arena.com"
+  #endif
+  #ifndef AUTHORIZE_SERVER_NAME
+  #define	AUTHORIZE_SERVER_NAME	"authorize.quake3arena.com"
+  #endif
+
+  #define PORT_MASTER 27950
+
 #endif
-#ifndef AUTHORIZE_SERVER_NAME
-#define	AUTHORIZE_SERVER_NAME	"authorize.quake3arena.com"
-#endif
 
-#define	PORT_MASTER			27950
 #define	PORT_UPDATE			27951
 #ifndef PORT_AUTHORIZE
 #define	PORT_AUTHORIZE		27952
@@ -535,7 +568,11 @@
 #define FS_CGAME_REF	0x04
 #define FS_QAGAME_REF	0x08
 // number of id paks that will never be autodownloaded from baseq3
+#ifdef ELITEFORCE
+#define NUM_ID_PAKS		4
+#else
 #define NUM_ID_PAKS		9
+#endif
 
 #define	MAX_FILE_HANDLES	64
 
Index: code/qcommon/msg.c
===================================================================
--- code/qcommon/msg.c	(revision 965)
+++ code/qcommon/msg.c	(working copy)
@@ -103,6 +103,15 @@
 
 int	overflows;
 
+#ifdef ELITEFORCE
+// Apparently, eliteforce only sends stuff like strings on 1 byte boundaries.
+void MSG_RoundBits(msg_t *msg)
+{
+	if(msg->bit & 0x07)
+		msg->bit = ++msg->readcount << 3;
+}
+#endif
+
 // negative bit values include signs
 void MSG_WriteBits( msg_t *msg, int value, int bits ) {
 	int	i;
@@ -140,23 +149,58 @@
 		bits = -bits;
 	}
 	if (msg->oob) {
-		if (bits==8) {
-			msg->data[msg->cursize] = value;
-			msg->cursize += 1;
-			msg->bit += 8;
-		} else if (bits==16) {
-			unsigned short *sp = (unsigned short *)&msg->data[msg->cursize];
-			*sp = LittleShort(value);
-			msg->cursize += 2;
-			msg->bit += 16;
-		} else if (bits==32) {
-			unsigned int *ip = (unsigned int *)&msg->data[msg->cursize];
-			*ip = LittleLong(value);
-			msg->cursize += 4;
-			msg->bit += 32;
-		} else {
-			Com_Error(ERR_DROP, "can't read %d bits\n", bits);
+		#ifdef ELITEFORCE
+		if(msg->compat)
+		{
+			int write, leftover, nbits = bits, location;
+			
+			// make sure to set all non-used space in value to zero.
+			if(bits < 32)
+				value &= ((1 << bits) - 1);
+			
+			while(nbits)
+			{
+				leftover = msg->bit & 0x07;
+				write = 8 - leftover;
+				location = msg->bit >> 3;
+				
+				if(write > nbits)
+					write = nbits;
+			
+				msg->data[location] &= (1 << leftover) - 1;
+				msg->data[location] |= (value & ((1 << write) - 1)) << (leftover);
+				nbits -= write;
+				value >>= write;
+				msg->bit += write;
+			}
+
+			msg->cursize = (msg->bit >> 3) + ((msg->bit & 0x07) ? 1 : 0);
 		}
+		else
+		{
+		#endif		
+			if (bits==8) {
+				msg->data[msg->cursize] = value;
+				msg->cursize += 1;
+				msg->bit += 8;
+			} else if (bits==16) {
+				unsigned short *sp = (unsigned short *)&msg->data[msg->cursize];
+				*sp = LittleShort(value);
+				msg->cursize += 2;
+				msg->bit += 16;
+			} else if (bits==32) {
+				unsigned int *ip = (unsigned int *)&msg->data[msg->cursize];
+				*ip = LittleLong(value);
+				msg->cursize += 4;
+				msg->bit += 32;
+			}
+			else
+			{
+				Com_Error(ERR_DROP, "can't write %d bits\n", bits);
+			}
+		#ifdef ELITEFORCE
+		}
+		#endif
 	} else {
 //		fp = fopen("c:\\netchan.bin", "a");
 		value &= (0xffffffff>>(32-bits));
@@ -198,23 +242,51 @@
 	}
 
 	if (msg->oob) {
-		if (bits==8) {
-			value = msg->data[msg->readcount];
-			msg->readcount += 1;
-			msg->bit += 8;
-		} else if (bits==16) {
-			unsigned short *sp = (unsigned short *)&msg->data[msg->readcount];
-			value = LittleShort(*sp);
-			msg->readcount += 2;
-			msg->bit += 16;
-		} else if (bits==32) {
-			unsigned int *ip = (unsigned int *)&msg->data[msg->readcount];
-			value = LittleLong(*ip);
-			msg->readcount += 4;
-			msg->bit += 32;
-		} else {
-			Com_Error(ERR_DROP, "can't read %d bits\n", bits);
+		#ifdef ELITEFORCE
+		if(msg->compat)
+		{
+			nbits = 0;
+			
+			while(nbits < bits)
+			{
+				i = msg->bit & 0x07;
+				get = 8 - i;
+				
+				if(get > bits - nbits)
+					get = bits - nbits;
+					
+				value |= ((msg->data[msg->bit >> 3] >> i) & ((1 << get) - 1)) << nbits;
+				msg->bit += get;
+				nbits += get;
+			}
+
+			msg->readcount = (msg->bit >> 3) + ((msg->bit & 0x07) ? 1 : 0);
 		}
+		else
+		{
+		#endif
+			if (bits==8) {
+				value = msg->data[msg->readcount];
+				msg->readcount += 1;
+				msg->bit += 8;
+			} else if (bits==16) {
+				unsigned short *sp = (unsigned short *)&msg->data[msg->readcount];
+				value = LittleShort(*sp);
+				msg->readcount += 2;
+				msg->bit += 16;
+			} else if (bits==32) {
+				unsigned int *ip = (unsigned int *)&msg->data[msg->readcount];
+				value = LittleLong(*ip);
+				msg->readcount += 4;
+				msg->bit += 32;
+			}
+			else
+			{
+				Com_Error(ERR_DROP, "can't read %d bits\n", bits);
+			}
+		#ifdef ELITEFORCE
+		}
+		#endif
 	} else {
 		nbits = 0;
 		if (bits&7) {
@@ -245,7 +317,6 @@
 }
 
 
-
 //================================================================================
 
 //
@@ -272,6 +343,16 @@
 
 void MSG_WriteData( msg_t *buf, const void *data, int length ) {
 	int i;
+
+#ifdef ELITEFORCE
+	if(buf->compat)
+	{
+		// Start writing on a whole-byte boundary
+		if(buf->bit & 0x07)
+			buf->bit = ++buf->cursize << 3;
+	}
+#endif
+
 	for(i=0;i<length;i++) {
 		MSG_WriteByte(buf, ((byte *)data)[i]);
 	}
@@ -304,7 +385,11 @@
 	if ( !s ) {
 		MSG_WriteData (sb, "", 1);
 	} else {
+#ifdef ELITEFORCE
+		int l;
+#else
 		int		l,i;
+#endif
 		char	string[MAX_STRING_CHARS];
 
 		l = strlen( s );
@@ -315,12 +400,14 @@
 		}
 		Q_strncpyz( string, s, sizeof( string ) );
 
+#ifndef ELITEFORCE
 		// get rid of 0xff chars, because old clients don't like them
 		for ( i = 0 ; i < l ; i++ ) {
 			if ( ((byte *)string)[i] > 127 ) {
 				string[i] = '.';
 			}
 		}
+#endif
 
 		MSG_WriteData (sb, string, l+1);
 	}
@@ -330,7 +417,11 @@
 	if ( !s ) {
 		MSG_WriteData (sb, "", 1);
 	} else {
+#ifdef ELITEFORCE
+		int l;
+#else
 		int		l,i;
+#endif
 		char	string[BIG_INFO_STRING];
 
 		l = strlen( s );
@@ -341,12 +432,14 @@
 		}
 		Q_strncpyz( string, s, sizeof( string ) );
 
+#ifndef ELITEFORCE
 		// get rid of 0xff chars, because old clients don't like them
 		for ( i = 0 ; i < l ; i++ ) {
 			if ( ((byte *)string)[i] > 127 ) {
 				string[i] = '.';
 			}
 		}
+#endif
 
 		MSG_WriteData (sb, string, l+1);
 	}
@@ -430,6 +523,11 @@
 	static char	string[MAX_STRING_CHARS];
 	int		l,c;
 	
+#ifdef ELITEFORCE
+	if(msg->compat)
+		MSG_RoundBits(msg);
+#endif
+
 	l = 0;
 	do {
 		c = MSG_ReadByte(msg);		// use ReadByte so -1 is out of bounds
@@ -440,11 +538,12 @@
 		if ( c == '%' ) {
 			c = '.';
 		}
+#ifndef ELITEFORCE
 		// don't allow higher ascii values
 		if ( c > 127 ) {
 			c = '.';
 		}
-
+#endif
 		string[l] = c;
 		l++;
 	} while (l < sizeof(string)-1);
@@ -458,6 +557,12 @@
 	static char	string[BIG_INFO_STRING];
 	int		l,c;
 	
+#ifdef ELITEFORCE
+	if(msg->compat)
+		MSG_RoundBits(msg);
+#endif
+
+
 	l = 0;
 	do {
 		c = MSG_ReadByte(msg);		// use ReadByte so -1 is out of bounds
@@ -468,10 +573,12 @@
 		if ( c == '%' ) {
 			c = '.';
 		}
+#ifndef ELITEFORCE
 		// don't allow higher ascii values
 		if ( c > 127 ) {
 			c = '.';
 		}
+#endif
 
 		string[l] = c;
 		l++;
@@ -486,6 +593,11 @@
 	static char	string[MAX_STRING_CHARS];
 	int		l,c;
 
+#ifdef ELITEFORCE
+	if(msg->compat)
+		MSG_RoundBits(msg);
+#endif
+
 	l = 0;
 	do {
 		c = MSG_ReadByte(msg);		// use ReadByte so -1 is out of bounds
@@ -496,11 +608,12 @@
 		if ( c == '%' ) {
 			c = '.';
 		}
+#ifndef ELITEFORCE
 		// don't allow higher ascii values
 		if ( c > 127 ) {
 			c = '.';
 		}
-
+#endif
 		string[l] = c;
 		l++;
 	} while (l < sizeof(string)-1);
@@ -517,6 +630,11 @@
 void MSG_ReadData( msg_t *msg, void *data, int len ) {
 	int		i;
 
+#ifdef ELITEFORCE
+	if(msg->compat)
+		MSG_RoundBits(msg);
+#endif
+
 	for (i=0 ; i<len ; i++) {
 		((byte *)data)[i] = MSG_ReadByte (msg);
 	}
@@ -662,7 +780,11 @@
 	MSG_WriteDelta( msg, from->forwardmove, to->forwardmove, 8 );
 	MSG_WriteDelta( msg, from->rightmove, to->rightmove, 8 );
 	MSG_WriteDelta( msg, from->upmove, to->upmove, 8 );
+#ifdef ELITEFORCE
+	MSG_WriteDelta( msg, from->buttons, to->buttons, 8 );
+#else
 	MSG_WriteDelta( msg, from->buttons, to->buttons, 16 );
+#endif
 	MSG_WriteDelta( msg, from->weapon, to->weapon, 8 );
 }
 
@@ -684,7 +806,11 @@
 	to->forwardmove = MSG_ReadDelta( msg, from->forwardmove, 8);
 	to->rightmove = MSG_ReadDelta( msg, from->rightmove, 8);
 	to->upmove = MSG_ReadDelta( msg, from->upmove, 8);
+#ifdef ELITEFORCE
+	to->buttons = MSG_ReadDelta( msg, from->buttons, 8);
+#else
 	to->buttons = MSG_ReadDelta( msg, from->buttons, 16);
+#endif
 	to->weapon = MSG_ReadDelta( msg, from->weapon, 8);
 }
 
@@ -721,7 +847,11 @@
 	MSG_WriteDeltaKey( msg, key, from->forwardmove, to->forwardmove, 8 );
 	MSG_WriteDeltaKey( msg, key, from->rightmove, to->rightmove, 8 );
 	MSG_WriteDeltaKey( msg, key, from->upmove, to->upmove, 8 );
+#ifdef ELITEFORCE
+	MSG_WriteDeltaKey( msg, key, from->buttons, to->buttons, 8 );
+#else
 	MSG_WriteDeltaKey( msg, key, from->buttons, to->buttons, 16 );
+#endif
 	MSG_WriteDeltaKey( msg, key, from->weapon, to->weapon, 8 );
 }
 
@@ -745,7 +875,11 @@
 		to->forwardmove = MSG_ReadDeltaKey( msg, key, from->forwardmove, 8);
 		to->rightmove = MSG_ReadDeltaKey( msg, key, from->rightmove, 8);
 		to->upmove = MSG_ReadDeltaKey( msg, key, from->upmove, 8);
+#ifdef ELITEFORCE
+		to->buttons = MSG_ReadDeltaKey( msg, key, from->buttons, 8);
+#else
 		to->buttons = MSG_ReadDeltaKey( msg, key, from->buttons, 16);
+#endif
 		to->weapon = MSG_ReadDeltaKey( msg, key, from->weapon, 8);
 	} else {
 		to->angles[0] = from->angles[0];
@@ -767,6 +901,48 @@
 =============================================================================
 */
 
+#ifdef ELITEFORCE
+#define PVECTOR_BITS 5	// amount of bits we need to reference all predefined vectors.
+#define PVECTOR_BYTES 8	// length of predefined vector.
+#define PVECTOR_NUM (1 << PVECTOR_BITS) - 1 // number of existing predefined vectors.
+
+byte pVectors[PVECTOR_NUM][PVECTOR_BYTES] =
+{
+	{0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x80, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00},
+	{0x60, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00},
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00},
+	{0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0xe0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00},
+	{0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0xc0, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00},
+	{0x60, 0xc0, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00},
+	{0x60, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00},
+	{0x60, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00},
+	{0xe1, 0x00, 0xc0, 0x01, 0x90, 0x00, 0x00, 0x00},
+	{0xed, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00},
+	{0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00},
+	{0x62, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00},
+	{0x02, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00},
+	{0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00},
+};
+
+#endif
+
 /*
 =================
 MSG_ReportChangeVectors_f
@@ -792,6 +968,61 @@
 // using the stringizing operator to save typing...
 #define	NETF(x) #x,(int)&((entityState_t*)0)->x
 
+#ifdef ELITEFORCE
+netField_t      entityStateFields[] =
+{
+{ NETF(eType), 8 },
+{ NETF(eFlags), 24 },
+{ NETF(pos.trType), 8 },
+{ NETF(pos.trTime), 32 },
+{ NETF(pos.trDuration), 32 },
+{ NETF(pos.trBase[0]), 0 },
+{ NETF(pos.trBase[1]), 0 },
+{ NETF(pos.trBase[2]), 0 },
+{ NETF(pos.trDelta[0]), 0 },
+{ NETF(pos.trDelta[1]), 0 },
+{ NETF(pos.trDelta[2]), 0 },
+{ NETF(apos.trType), 8 },
+{ NETF(apos.trTime), 32 },
+{ NETF(apos.trDuration), 32 },
+{ NETF(apos.trBase[0]), 0 },
+{ NETF(apos.trBase[1]), 0 },
+{ NETF(apos.trBase[2]), 0 },
+{ NETF(apos.trDelta[0]), 0 },
+{ NETF(apos.trDelta[1]), 0 },
+{ NETF(apos.trDelta[2]), 0 },
+{ NETF(time), 32 },
+{ NETF(time2), 32 },
+{ NETF(origin[0]), 0 },
+{ NETF(origin[1]), 0 },
+{ NETF(origin[2]), 0 },
+{ NETF(origin2[0]), 0 },
+{ NETF(origin2[1]), 0 },
+{ NETF(origin2[2]), 0 },
+{ NETF(angles[0]), 0 },
+{ NETF(angles[1]), 0 },
+{ NETF(angles[2]), 0 },
+{ NETF(angles2[0]), 0 },
+{ NETF(angles2[1]), 0 },
+{ NETF(angles2[2]), 0 },
+{ NETF(otherEntityNum), GENTITYNUM_BITS },
+{ NETF(otherEntityNum2), GENTITYNUM_BITS },
+{ NETF(groundEntityNum), GENTITYNUM_BITS },
+{ NETF(loopSound), 16 },
+{ NETF(constantLight), 32 },
+{ NETF(modelindex), 8 },
+{ NETF(modelindex2), 8 },
+{ NETF(frame), 16 },
+{ NETF(clientNum), 8 },
+{ NETF(solid), 24 },
+{ NETF(event), 10 },
+{ NETF(eventParm), 8 },
+{ NETF(powerups), 16 },
+{ NETF(weapon), 8 },
+{ NETF(legsAnim), 8 },
+{ NETF(torsoAnim), 8 },
+};
+#else
 netField_t	entityStateFields[] = 
 {
 { NETF(pos.trTime), 32 },
@@ -811,7 +1042,7 @@
 { NETF(legsAnim), 8 },
 { NETF(groundEntityNum), GENTITYNUM_BITS },
 { NETF(pos.trType), 8 },
-{ NETF(eFlags), 19 },
+{ NETF(eFlags), 27 },
 { NETF(otherEntityNum), GENTITYNUM_BITS },
 { NETF(weapon), 8 },
 { NETF(clientNum), 8 },
@@ -846,8 +1077,8 @@
 { NETF(constantLight), 32 },
 { NETF(frame), 16 }
 };
+#endif
 
-
 // if (int)f == f and (int)f + ( 1<<(FLOAT_INT_BITS-1) ) < ( 1 << FLOAT_INT_BITS )
 // the float will be sent with FLOAT_INT_BITS, otherwise all 32 bits will be sent
 #define	FLOAT_INT_BITS	13
@@ -872,6 +1103,10 @@
 	int			trunc;
 	float		fullFloat;
 	int			*fromF, *toF;
+#ifdef ELITEFORCE
+        byte            vector[PVECTOR_BYTES];
+	int                     vectorIndex = -1;
+#endif
 
 	numFields = sizeof(entityStateFields)/sizeof(entityStateFields[0]);
 
@@ -895,17 +1130,33 @@
 		Com_Error (ERR_FATAL, "MSG_WriteDeltaEntity: Bad entity number: %i", to->number );
 	}
 
+        #ifdef ELITEFORCE
+	if(msg->compat)
+		Com_Memset(vector, 0, sizeof(vector));
+	#endif
+
 	lc = 0;
 	// build the change vector as bytes so it is endien independent
 	for ( i = 0, field = entityStateFields ; i < numFields ; i++, field++ ) {
 		fromF = (int *)( (byte *)from + field->offset );
 		toF = (int *)( (byte *)to + field->offset );
 		if ( *fromF != *toF ) {
-			lc = i+1;
+			#ifdef ELITEFORCE
+			if(msg->compat)
+				 vector[i >> 3] |= 1 << (i & 0x07);
+			else
+			#endif
+				lc = i+1;
 		}
 	}
 
-	if ( lc == 0 ) {
+	#ifdef ELITEFORCE
+	if((msg->compat && !((int *) vector)[0] && !((int *) vector)[1]) || (!msg->compat && !lc))
+	{
+	#else
+	if ( lc == 0 )
+	{
+	#endif
 		// nothing at all changed
 		if ( !force ) {
 			return;		// nothing at all
@@ -917,35 +1168,87 @@
 		return;
 	}
 
+	#ifdef ELITEFORCE
+	if(msg->compat)
+	{
+		for (i = 0; i < PVECTOR_NUM; i++)
+		{
+			if( ((int *) vector)[0] == ((int *)pVectors[i])[0] &&
+			    ((int *) vector)[1] == ((int *)pVectors[i])[1]
+			  )
+			{
+				vectorIndex = i;
+				break;
+			}
+		}
+	}
+	#endif
+
 	MSG_WriteBits( msg, to->number, GENTITYNUM_BITS );
 	MSG_WriteBits( msg, 0, 1 );			// not removed
 	MSG_WriteBits( msg, 1, 1 );			// we have a delta
 
-	MSG_WriteByte( msg, lc );	// # of changes
+#ifdef ELITEFORCE
+	if(msg->compat)
+	{
+		MSG_WriteBits(msg, vectorIndex, PVECTOR_BITS);
 
+		if (vectorIndex < 0)
+		{
+			for ( i = 0 ; i + 8 <= numFields ; i += 8 )
+				MSG_WriteByte( msg, vector[i >> 3] );
+			if ( numFields & 7 )
+				MSG_WriteBits( msg, vector[i >> 3], numFields & 7 );
+	        }
+
+	}
+	else
+#endif
+		MSG_WriteByte( msg, lc );	// # of changes
+
 	oldsize += numFields;
 
+#ifdef ELITEFORCE
+	for ( i = 0, field = entityStateFields ; msg->compat ? (i < numFields) : (i < lc) ; i++, field++ ) {
+#else
 	for ( i = 0, field = entityStateFields ; i < lc ; i++, field++ ) {
+#endif
 		fromF = (int *)( (byte *)from + field->offset );
 		toF = (int *)( (byte *)to + field->offset );
 
 		if ( *fromF == *toF ) {
-			MSG_WriteBits( msg, 0, 1 );	// no change
+
+			#ifdef ELITEFORCE
+			if(!msg->compat)
+			#endif
+				MSG_WriteBits( msg, 0, 1 );	// no change
 			continue;
 		}
 
-		MSG_WriteBits( msg, 1, 1 );	// changed
+		#ifdef ELITEFORCE
+		if(!msg->compat)
+		#endif
+			MSG_WriteBits( msg, 1, 1 );	// changed
 
 		if ( field->bits == 0 ) {
 			// float
 			fullFloat = *(float *)toF;
 			trunc = (int)fullFloat;
 
-			if (fullFloat == 0.0f) {
-					MSG_WriteBits( msg, 0, 1 );
-					oldsize += FLOAT_INT_BITS;
+#ifdef ELITEFORCE
+			if(!msg->compat && fullFloat == 0.0f)
+#else
+			if (fullFloat == 0.0f)
+#endif
+			{
+				MSG_WriteBits( msg, 0, 1 );
+				oldsize += FLOAT_INT_BITS;
 			} else {
-				MSG_WriteBits( msg, 1, 1 );
+				#ifdef ELITEFORCE
+				if(!msg->compat)
+				#endif
+					MSG_WriteBits( msg, 1, 1 );
+	
 				if ( trunc == fullFloat && trunc + FLOAT_INT_BIAS >= 0 && 
 					trunc + FLOAT_INT_BIAS < ( 1 << FLOAT_INT_BITS ) ) {
 					// send as small integer
@@ -958,13 +1261,23 @@
 				}
 			}
 		} else {
-			if (*toF == 0) {
-				MSG_WriteBits( msg, 0, 1 );
-			} else {
-				MSG_WriteBits( msg, 1, 1 );
-				// integer
-				MSG_WriteBits( msg, *toF, field->bits );
+			#ifdef ELITEFORCE
+			if(msg->compat)
+				MSG_WriteBits(msg, *toF, field->bits);
+			else
+			{
+			#endif
+				if (*toF == 0)
+					MSG_WriteBits( msg, 0, 1 );
+				else
+				{
+					MSG_WriteBits( msg, 1, 1 );
+					// integer
+					MSG_WriteBits( msg, *toF, field->bits );
+				}
+			#ifdef ELITEFORCE
 			}
+			#endif
 		}
 	}
 }
@@ -985,13 +1298,18 @@
 
 void MSG_ReadDeltaEntity( msg_t *msg, entityState_t *from, entityState_t *to, 
 						 int number) {
-	int			i, lc;
+	int			i, lc = 0;
 	int			numFields;
 	netField_t	*field;
 	int			*fromF, *toF;
 	int			print;
 	int			trunc;
 	int			startBit, endBit;
+#ifdef ELITEFORCE
+        int                     vectorIndex;
+        byte            vector_space[PVECTOR_BYTES];
+	byte            *vector = vector_space;
+#endif
 
 	if ( number < 0 || number >= MAX_GENTITIES) {
 		Com_Error( ERR_DROP, "Bad delta entity number: %i", number );
@@ -1021,7 +1339,10 @@
 	}
 
 	numFields = sizeof(entityStateFields)/sizeof(entityStateFields[0]);
-	lc = MSG_ReadByte(msg);
+	#ifdef ELITEFORCE
+	if(!msg->compat)
+	#endif
+		lc = MSG_ReadByte(msg);
 
 	// shownet 2/3 will interleave with other printed info, -1 will
 	// just print the delta records`
@@ -1034,19 +1355,48 @@
 
 	to->number = number;
 
+#ifdef ELITEFORCE
+	if(msg->compat)
+	{
+		// Read in the vector index and check whether there is a predefined one or not.
+		vectorIndex = MSG_ReadBits( msg, PVECTOR_BITS );
+
+		if (vectorIndex == PVECTOR_NUM)
+		{
+			for (i = 0; i + 8 < numFields; i += 8)
+				vector[i >> 3] = MSG_ReadByte(msg);
+			if (numFields & 7)
+				vector[i>>3] = MSG_ReadBits( msg, numFields & 7 );
+		}
+		else
+			vector = pVectors[vectorIndex];
+	}
+
+	for ( i = 0, field = entityStateFields ; msg->compat ? (i < numFields) : (i < lc) ; i++, field++ ) {
+#else
 	for ( i = 0, field = entityStateFields ; i < lc ; i++, field++ ) {
+#endif
 		fromF = (int *)( (byte *)from + field->offset );
 		toF = (int *)( (byte *)to + field->offset );
 
-		if ( ! MSG_ReadBits( msg, 1 ) ) {
+		#ifdef ELITEFORCE
+		if((msg->compat && ! (vector[i >> 3] & (1 << (i & 7)) )) || (!msg->compat && !MSG_ReadBits(msg, 1)))
+		#else
+		if ( ! MSG_ReadBits( msg, 1 ) )
+		#endif
+		{
 			// no change
 			*toF = *fromF;
 		} else {
 			if ( field->bits == 0 ) {
 				// float
-				if ( MSG_ReadBits( msg, 1 ) == 0 ) {
+#ifdef ELITEFORCE
+				if(!msg->compat && !MSG_ReadBits( msg, 1 ))
+#else
+				if ( MSG_ReadBits( msg, 1 ) == 0 )
+#endif
 						*(float *)toF = 0.0f; 
-				} else {
+				else {
 					if ( MSG_ReadBits( msg, 1 ) == 0 ) {
 						// integral float
 						trunc = MSG_ReadBits( msg, FLOAT_INT_BITS );
@@ -1065,9 +1415,13 @@
 					}
 				}
 			} else {
-				if ( MSG_ReadBits( msg, 1 ) == 0 ) {
+				#ifdef ELITEFORCE
+				if(!msg->compat && !MSG_ReadBits(msg, 1))
+				#else
+				if ( MSG_ReadBits( msg, 1 ) == 0 )
+				#endif
 					*toF = 0;
-				} else {
+				else {
 					// integer
 					*toF = MSG_ReadBits( msg, field->bits );
 					if ( print ) {
@@ -1078,12 +1432,19 @@
 //			pcount[i]++;
 		}
 	}
-	for ( i = lc, field = &entityStateFields[lc] ; i < numFields ; i++, field++ ) {
-		fromF = (int *)( (byte *)from + field->offset );
-		toF = (int *)( (byte *)to + field->offset );
-		// no change
-		*toF = *fromF;
+	#ifdef ELITEFORCE
+	if(!msg->compat)
+	{
+	#endif
+		for ( i = lc, field = &entityStateFields[lc] ; i < numFields ; i++, field++ ) {
+			fromF = (int *)( (byte *)from + field->offset );
+			toF = (int *)( (byte *)to + field->offset );
+			// no change
+			*toF = *fromF;
+		}
+	#ifdef ELITEFORCE
 	}
+	#endif
 
 	if ( print ) {
 		if ( msg->bit == 0 ) {
@@ -1107,6 +1468,59 @@
 // using the stringizing operator to save typing...
 #define	PSF(x) #x,(int)&((playerState_t*)0)->x
 
+#ifdef ELITEFORCE
+netField_t      playerStateFields[] =
+{
+{ PSF(commandTime), 32 },
+{ PSF(pm_type), 8 },
+{ PSF(bobCycle), 8 },
+{ PSF(pm_flags), 16 },
+{ PSF(pm_time), -16 },
+{ PSF(origin[0]), 0 },
+{ PSF(origin[1]), 0 },
+{ PSF(origin[2]), 0 },
+{ PSF(velocity[0]), 0 },
+{ PSF(velocity[1]), 0 },
+{ PSF(velocity[2]), 0 },
+{ PSF(weaponTime), -16 },
+{ PSF(gravity), 16 },
+{ PSF(speed), 16 },
+{ PSF(delta_angles[0]), 16 },
+{ PSF(delta_angles[1]), 16 },
+{ PSF(delta_angles[2]), 16 },
+{ PSF(groundEntityNum), GENTITYNUM_BITS },
+{ PSF(legsTimer), 8 },
+{ PSF(torsoTimer), 12 },
+{ PSF(legsAnim), 8 },
+{ PSF(torsoAnim), 8 },
+{ PSF(movementDir), 4 },
+{ PSF(eFlags), 16 },
+{ PSF(eventSequence), 16 },
+{ PSF(events[0]), 8 },
+{ PSF(events[1]), 8 },
+{ PSF(events[2]), 8 },
+{ PSF(events[3]), 8 },
+{ PSF(eventParms[0]), 8 },
+{ PSF(eventParms[1]), 8 },
+{ PSF(eventParms[2]), 8 },
+{ PSF(eventParms[3]), 8 },
+{ PSF(externalEvent), 10 },
+{ PSF(externalEventParm), 8 },
+{ PSF(clientNum), 8 },
+{ PSF(weapon), 5 },
+{ PSF(weaponstate), 4 },
+{ PSF(viewangles[0]), 0 },
+{ PSF(viewangles[1]), 0 },
+{ PSF(viewangles[2]), 0 },
+{ PSF(viewheight), -8 },
+{ PSF(damageEvent), 8 },
+{ PSF(damageYaw), 8 },
+{ PSF(damagePitch), 8 },
+{ PSF(damageCount), 8 },
+{ PSF(damageShieldCount), 8 },
+{ PSF(introTime), 32},
+};
+#else
 netField_t	playerStateFields[] = 
 {
 { PSF(commandTime), 32 },				
@@ -1158,7 +1572,7 @@
 { PSF(jumppad_ent), 10 },
 { PSF(loopSound), 16 }
 };
-
+#endif
 /*
 =============
 MSG_WriteDeltaPlayerstate
@@ -1177,7 +1591,7 @@
 	netField_t		*field;
 	int				*fromF, *toF;
 	float			fullFloat;
-	int				trunc, lc;
+	int				trunc, lc = 0;
 
 	if (!from) {
 		from = &dummy;
@@ -1188,20 +1602,33 @@
 
 	numFields = sizeof( playerStateFields ) / sizeof( playerStateFields[0] );
 
-	lc = 0;
-	for ( i = 0, field = playerStateFields ; i < numFields ; i++, field++ ) {
-		fromF = (int *)( (byte *)from + field->offset );
-		toF = (int *)( (byte *)to + field->offset );
-		if ( *fromF != *toF ) {
-			lc = i+1;
+	#ifdef ELITEFORCE
+	if(!msg->compat)
+	{
+	#endif
+		lc = 0;
+		for ( i = 0, field = playerStateFields ; i < numFields ; i++, field++ ) {
+			fromF = (int *)( (byte *)from + field->offset );
+			toF = (int *)( (byte *)to + field->offset );
+			if ( *fromF != *toF ) {
+				lc = i+1;
+			}
 		}
+
+		MSG_WriteByte( msg, lc );	// # of changes
+	
+	#ifdef ELITEFORCE
 	}
-
-	MSG_WriteByte( msg, lc );	// # of changes
-
+	#endif
+	
 	oldsize += numFields - lc;
 
-	for ( i = 0, field = playerStateFields ; i < lc ; i++, field++ ) {
+	#ifdef ELITEFORCE
+	for ( i = 0, field = playerStateFields ; msg->compat ? (i < numFields) : (i < lc) ; i++, field++ )
+	#else
+	for ( i = 0, field = playerStateFields ; i < lc ; i++, field++ )
+	#endif
+	{
 		fromF = (int *)( (byte *)from + field->offset );
 		toF = (int *)( (byte *)to + field->offset );
 
@@ -1264,13 +1691,22 @@
 		}
 	}
 
-	if (!statsbits && !persistantbits && !ammobits && !powerupbits) {
+	#ifdef ELITEFORCE
+	if (!msg->compat && !statsbits && !persistantbits && !ammobits && !powerupbits)
+	#else
+	if (!statsbits && !persistantbits && !ammobits && !powerupbits)
+	#endif
+	{
 		MSG_WriteBits( msg, 0, 1 );	// no change
 		oldsize += 4;
 		return;
 	}
-	MSG_WriteBits( msg, 1, 1 );	// changed
 
+	#ifdef ELITEFORCE
+	if(!msg->compat)
+	#endif
+		MSG_WriteBits( msg, 1, 1 );	// changed
+
 	if ( statsbits ) {
 		MSG_WriteBits( msg, 1, 1 );	// changed
 		MSG_WriteBits( msg, statsbits, MAX_STATS );
@@ -1322,7 +1758,7 @@
 ===================
 */
 void MSG_ReadDeltaPlayerstate (msg_t *msg, playerState_t *from, playerState_t *to ) {
-	int			i, lc;
+	int			i, lc = 0;
 	int			bits;
 	netField_t	*field;
 	int			numFields;
@@ -1354,9 +1790,18 @@
 	}
 
 	numFields = sizeof( playerStateFields ) / sizeof( playerStateFields[0] );
-	lc = MSG_ReadByte(msg);
 
-	for ( i = 0, field = playerStateFields ; i < lc ; i++, field++ ) {
+	#ifdef ELITEFORCE
+	if(!msg->compat)
+	#endif	
+		lc = MSG_ReadByte(msg);
+
+#ifdef ELITEFORCE
+	for ( i = 0, field = playerStateFields ; msg->compat ? (i < numFields) : (i < lc) ; i++, field++ )
+#else
+	for ( i = 0, field = playerStateFields ; i < lc ; i++, field++ )
+#endif
+	{
 		fromF = (int *)( (byte *)from + field->offset );
 		toF = (int *)( (byte *)to + field->offset );
 
@@ -1391,16 +1836,27 @@
 			}
 		}
 	}
-	for ( i=lc,field = &playerStateFields[lc];i<numFields; i++, field++) {
-		fromF = (int *)( (byte *)from + field->offset );
-		toF = (int *)( (byte *)to + field->offset );
-		// no change
-		*toF = *fromF;
+	#ifdef ELITEFORCE
+	if(!msg->compat)
+	{
+	#endif
+		for ( i=lc,field = &playerStateFields[lc];i<numFields; i++, field++) {
+			fromF = (int *)( (byte *)from + field->offset );
+			toF = (int *)( (byte *)to + field->offset );
+			// no change
+			*toF = *fromF;
+		}
+	#ifdef ELITEFORCE
 	}
-
-
+	#endif
+	
 	// read the arrays
-	if (MSG_ReadBits( msg, 1 ) ) {
+#ifdef ELITEFORCE
+	if(msg->compat || MSG_ReadBits( msg, 1 ))
+#else
+	if (MSG_ReadBits( msg, 1 ) )
+#endif
+	{
 		// parse stats
 		if ( MSG_ReadBits( msg, 1 ) ) {
 			LOG("PS_STATS");
Index: code/qcommon/qfiles.h
===================================================================
--- code/qcommon/qfiles.h	(revision 965)
+++ code/qcommon/qfiles.h	(working copy)
@@ -327,7 +327,7 @@
 
 // If you want to enable support for Raven's .mdr / md4 format, uncomment the next
 // line.
-//#define RAVENMD4
+#define RAVENMD4
 
 #ifdef RAVENMD4
 
Index: code/qcommon/common.c
===================================================================
--- code/qcommon/common.c	(revision 965)
+++ code/qcommon/common.c	(working copy)
@@ -31,8 +31,13 @@
 #include <winsock.h>
 #endif
 
+#ifdef ELITEFORCE
 int demo_protocols[] =
+{ 25, 0 };
+#else
+int demo_protocols[] =
 { 66, 67, 68, 0 };
+#endif
 
 #define MAX_NUM_ARGVS	50
 
@@ -75,6 +80,7 @@
 cvar_t	*com_blood;
 cvar_t	*com_buildScript;	// for automated data building scripts
 cvar_t	*com_introPlayed;
+cvar_t  *com_novmcompat;	// set to 1 to indicate VMs are run by the new engine.
 cvar_t	*cl_paused;
 cvar_t	*sv_paused;
 cvar_t  *cl_packetdelay;
@@ -2271,8 +2277,14 @@
 	fileHandle_t	f;
 	char			buffer[33];
 	char			fbuffer[MAX_OSPATH];
-
+#ifdef ELITEFORCE
+	int index = 0;
+	char curchar;
+	
+	sprintf(fbuffer, "%s/efq3.key", filename);
+#else
 	sprintf(fbuffer, "%s/q3key", filename);
+#endif
 
 	FS_SV_FOpenFileRead( fbuffer, &f );
 	if ( !f ) {
@@ -2282,14 +2294,68 @@
 
 	Com_Memset( buffer, 0, sizeof(buffer) );
 
+#ifdef ELITEFORCE
+	// check for the normal CD key
+	while(index < 16)
+	{
+		if(FS_Read(&curchar, 1, f) != 1)
+		{
+			Q_strncpyz( cl_cdkey, "                ", 17 );
+			FS_FCloseFile(f);
+			return;
+		}
+		
+		curchar = toupper(curchar);
+
+		if(curchar < '0' || (curchar > '9' && curchar < 'A') || curchar > 'Z')
+			continue;
+		
+		buffer[index] = toupper(curchar);
+		
+		index++;
+	}
+	FS_FCloseFile(f);
+	
+	// check for the expansion pack cd key
+	sprintf(fbuffer, "%s/expefq3.key", filename);
+	FS_SV_FOpenFileRead(fbuffer, &f);
+	
+	if(f)
+	{
+		while(index < 32)
+		{
+			// same game
+
+			if(FS_Read(&curchar, 1, f) != 1)
+			{
+				Q_strncpyz( cl_cdkey, "                ", 17 );
+				FS_FCloseFile(f);
+				return;
+			}
+		
+			curchar = toupper(curchar);
+
+			if(curchar < '0' || (curchar > '9' && curchar < 'A') || curchar > 'Z')
+				continue;
+		
+			buffer[index] = toupper(curchar);
+		
+			index++;
+		}
+		FS_FCloseFile(f);
+	}
+	
+	Q_strncpyz(cl_cdkey, buffer, index+1);
+#else
 	FS_Read( buffer, 16, f );
 	FS_FCloseFile( f );
-
+	
 	if (CL_CDKeyValidate(buffer, NULL)) {
 		Q_strncpyz( cl_cdkey, buffer, 17 );
 	} else {
 		Q_strncpyz( cl_cdkey, "                ", 17 );
 	}
+#endif
 }
 
 /*
@@ -2331,20 +2397,30 @@
 static void Com_WriteCDKey( const char *filename, const char *ikey ) {
 	fileHandle_t	f;
 	char			fbuffer[MAX_OSPATH];
+#ifdef ELITEFORCE
+	char			key[23];
+#else
 	char			key[17];
+#endif
 #ifndef _WIN32
 	mode_t			savedumask;
 #endif
 
-
+#ifdef ELITEFORCE
+	sprintf(fbuffer, "%s/efq3.key", filename);
+#else
 	sprintf(fbuffer, "%s/q3key", filename);
+#endif
 
-
+#ifdef ELITEFORCE
+	Q_strncpyz( key, ikey, 23 );
+	key[22] = '\0';
+#else
 	Q_strncpyz( key, ikey, 17 );
-
 	if(!CL_CDKeyValidate(key, NULL) ) {
 		return;
 	}
+#endif
 
 #ifndef _WIN32
 	savedumask = umask(0077);
@@ -2355,7 +2431,11 @@
 		goto out;
 	}
 
+#ifdef ELITEFORCE
+	FS_Write( key, strlen(key), f );
+#else
 	FS_Write( key, 16, f );
+#endif
 
 	FS_Printf( f, "\n// generated by quake, do not modify\r\n" );
 	FS_Printf( f, "// Do not give this file to ANYONE.\r\n" );
@@ -2436,7 +2516,11 @@
 
 	// skip the q3config.cfg if "safe" is on the command line
 	if ( !Com_SafeMode() ) {
+#ifdef ELITEFORCE
+		Cbuf_AddText ("exec hmconfig.cfg\n");
+#else
 		Cbuf_AddText ("exec q3config.cfg\n");
+#endif
 	}
 
 	Cbuf_AddText ("exec autoexec.cfg\n");
@@ -2487,6 +2571,7 @@
 	com_buildScript = Cvar_Get( "com_buildScript", "0", 0 );
 
 	com_introPlayed = Cvar_Get( "com_introplayed", "0", CVAR_ARCHIVE);
+	com_novmcompat = Cvar_Get( "com_novmcompat", "1", CVAR_ROM);
 
 #if defined(_WIN32) && defined(_DEBUG)
 	com_noErrorInterrupt = Cvar_Get( "com_noErrorInterrupt", "0", 0 );
@@ -2528,6 +2613,9 @@
 
 	// add + commands from command line
 	if ( !Com_AddStartupCommands() ) {
+#ifdef ELITEFORCE
+		Cvar_Set( com_introPlayed->name, "1" );
+#else
 		// if the user didn't give any commands, run default action
 		if ( !com_dedicated->integer ) {
 			Cbuf_AddText ("cinematic idlogo.RoQ\n");
@@ -2536,6 +2624,7 @@
 				Cvar_Set( "nextmap", "cinematic intro.RoQ" );
 			}
 		}
+#endif
 	}
 
 	// start in full screen ui mode
@@ -2597,7 +2686,11 @@
 	}
 	cvar_modifiedFlags &= ~CVAR_ARCHIVE;
 
+#ifdef ELITEFORCE
+	Com_WriteConfigToFile( "hmconfig.cfg" );
+#else
 	Com_WriteConfigToFile( "q3config.cfg" );
+#endif
 
 	// bk001119 - tentative "not needed for dedicated"
 #ifndef DEDICATED
Index: code/game/g_local.h
===================================================================
--- code/game/g_local.h	(revision 965)
+++ code/game/g_local.h	(working copy)
@@ -30,6 +30,7 @@
 
 // the "gameversion" client command will print this plus compile date
 #define	GAMEVERSION	BASEGAME
+#endif
 
 #define BODY_QUEUE_SIZE		8
 
Index: code/game/g_public.h
===================================================================
--- code/game/g_public.h	(revision 965)
+++ code/game/g_public.h	(working copy)
@@ -33,9 +33,19 @@
 
 // TTimo
 // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=551
+#ifdef ELITEFORCE
+#define SVF_SHIELD_BBOX			0x00000002
+#define SVF_CLIENTMASK			0x00000004
+#else
 #define SVF_CLIENTMASK 0x00000002
+#endif
 
 #define SVF_BOT					0x00000008	// set if the entity is a bot
+
+#ifdef ELITEFORCE
+#define SVF_ELIMINATED			0x00000010
+#endif
+
 #define	SVF_BROADCAST			0x00000020	// send to all connected clients
 #define	SVF_PORTAL				0x00000040	// merge a second pvs at origin2 into snapshots
 #define	SVF_USE_CURRENT_ORIGIN	0x00000080	// entity->r.currentOrigin instead of entity->s.origin
@@ -54,7 +64,9 @@
 
 
 typedef struct {
+#ifndef ELITEFORCE
 	entityState_t	s;				// communicated by server to clients
+#endif
 
 	qboolean	linked;				// qfalse if not in any good cluster
 	int			linkcount;
@@ -103,7 +115,281 @@
 //
 // system traps provided by the main engine
 //
+#ifdef ELITEFORCE
 typedef enum {
+        //============== general Quake services ==================
+
+        G_PRINT,                // ( const char *string );
+        // print message on the local console
+
+        G_ERROR,                // ( const char *string );
+        // abort the game
+
+        G_MILLISECONDS, // ( void );
+        // get current time for profiling reasons
+        // this should NOT be used for any game related tasks,
+        // because it is not journaled
+
+        // console variable interaction
+        G_CVAR_REGISTER,        // ( vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags );
+        G_CVAR_UPDATE,  // ( vmCvar_t *vmCvar );
+        G_CVAR_SET,             // ( const char *var_name, const char *value );
+        G_CVAR_VARIABLE_INTEGER_VALUE,  // ( const char *var_name );
+
+        G_CVAR_VARIABLE_STRING_BUFFER,  // ( const char *var_name, char *buffer, int bufsize );
+
+        G_ARGC,                 // ( void );
+        // ClientCommand and ServerCommand parameter access
+
+        G_ARGV,                 // ( int n, char *buffer, int bufferLength );
+
+        G_FS_FOPEN_FILE,        // ( const char *qpath, fileHandle_t *file, fsMode_t mode );
+        G_FS_READ,              // ( void *buffer, int len, fileHandle_t f );
+        G_FS_WRITE,             // ( const void *buffer, int len, fileHandle_t f );
+        G_FS_FCLOSE_FILE,               // ( fileHandle_t f );
+
+        G_SEND_CONSOLE_COMMAND, // ( const char *text );
+        // add commands to the console as if they were typed in
+        // for map changing, etc
+
+
+        //=========== server specific functionality =============
+
+        G_LOCATE_GAME_DATA,             // ( gentity_t *gEnts, int numGEntities, int sizeofGEntity_t,
+        //                                                      playerState_t *clients, int sizeofGameClient );
+        // the game needs to let the server system know where and how big the gentities
+        // are, so it can look at them directly without going through an interface
+
+        G_DROP_CLIENT,          // ( int clientNum, const char *reason );
+        // kick a client off the server with a message
+
+        G_SEND_SERVER_COMMAND,  // ( int clientNum, const char *fmt, ... );
+        // reliably sends a command string to be interpreted by the given
+        // client.  If clientNum is -1, it will be sent to all clients
+
+        G_SET_CONFIGSTRING,     // ( int num, const char *string );
+        // config strings hold all the index strings, and various other information
+        // that is reliably communicated to all clients
+        // All of the current configstrings are sent to clients when
+        // they connect, and changes are sent to all connected clients.
+        // All confgstrings are cleared at each level start.
+
+        G_GET_CONFIGSTRING,     // ( int num, char *buffer, int bufferSize );
+
+        G_GET_USERINFO,         // ( int num, char *buffer, int bufferSize );
+        // userinfo strings are maintained by the server system, so they
+        // are persistant across level loads, while all other game visible
+        // data is completely reset
+
+        G_SET_USERINFO,         // ( int num, const char *buffer );
+
+        G_GET_SERVERINFO,       // ( char *buffer, int bufferSize );
+        // the serverinfo info string has all the cvars visible to server browsers
+
+        G_SET_BRUSH_MODEL,      // ( gentity_t *ent, const char *name );
+        // sets mins and maxs based on the brushmodel name
+
+        G_TRACE,        // ( trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum,
+        // collision detection against all linked entities
+
+        G_POINT_CONTENTS,       // ( const vec3_t point, int passEntityNum );
+        // point contents against all linked entities
+
+        G_IN_PVS,                       // ( const vec3_t p1, const vec3_t p2 );
+
+        G_IN_PVS_IGNORE_PORTALS,        // ( const vec3_t p1, const vec3_t p2 );
+
+        G_ADJUST_AREA_PORTAL_STATE,     // ( gentity_t *ent, qboolean open );
+
+        G_AREAS_CONNECTED,      // ( int area1, int area2 );
+
+        G_LINKENTITY,           // ( gentity_t *ent );
+        // an entity will never be sent to a client or used for collision
+        // if it is not passed to linkentity.  If the size, position, or
+        // solidity changes, it must be relinked.
+
+        G_UNLINKENTITY,         // ( gentity_t *ent );
+        // call before removing an interactive entity
+
+        G_ENTITIES_IN_BOX,      // ( const vec3_t mins, const vec3_t maxs, gentity_t **list, int maxcount );
+        // EntitiesInBox will return brush models based on their bounding box,
+        // so exact determination must still be done with EntityContact
+
+        G_ENTITY_CONTACT,       // ( const vec3_t mins, const vec3_t maxs, const gentity_t *ent );
+        // perform an exact check against inline brush models of non-square shape
+
+        // access for bots to get and free a server client (FIXME?)
+        G_BOT_ALLOCATE_CLIENT,  // ( void );
+
+        G_BOT_FREE_CLIENT,      // ( int clientNum );
+
+        G_GET_USERCMD,  // ( int clientNum, usercmd_t *cmd )
+
+        G_GET_ENTITY_TOKEN,     // qboolean ( char *buffer, int bufferSize )
+        // Retrieves the next string token from the entity spawn text, returning
+        // false when all tokens have been parsed.
+        // This should only be done at GAME_INIT time.
+
+        G_FS_GETFILELIST,
+        G_DEBUG_POLYGON_CREATE,
+        G_DEBUG_POLYGON_DELETE,
+
+        BOTLIB_SETUP = 200,                             // ( void );
+        BOTLIB_SHUTDOWN,                                // ( void );
+        BOTLIB_LIBVAR_SET,
+        BOTLIB_LIBVAR_GET,
+        BOTLIB_DEFINE,
+        BOTLIB_START_FRAME,
+        BOTLIB_LOAD_MAP,
+        BOTLIB_UPDATENTITY,
+        BOTLIB_TEST,
+
+        BOTLIB_GET_SNAPSHOT_ENTITY,             // ( int client, int ent );
+        BOTLIB_GET_CONSOLE_MESSAGE,             // ( int client, char *message, int size );
+        BOTLIB_USER_COMMAND,                    // ( int client, usercmd_t *ucmd );
+
+        BOTLIB_AAS_ENTITY_VISIBLE = 300,        //FIXME: remove
+        BOTLIB_AAS_IN_FIELD_OF_VISION,          //FIXME: remove
+        BOTLIB_AAS_VISIBLE_CLIENTS,                     //FIXME: remove
+        BOTLIB_AAS_ENTITY_INFO,
+
+        BOTLIB_AAS_INITIALIZED,
+        BOTLIB_AAS_PRESENCE_TYPE_BOUNDING_BOX,
+        BOTLIB_AAS_TIME,
+
+        BOTLIB_AAS_POINT_AREA_NUM,
+        BOTLIB_AAS_TRACE_AREAS,
+
+        BOTLIB_AAS_POINT_CONTENTS,
+        BOTLIB_AAS_NEXT_BSP_ENTITY,
+        BOTLIB_AAS_VALUE_FOR_BSP_EPAIR_KEY,
+        BOTLIB_AAS_VECTOR_FOR_BSP_EPAIR_KEY,
+        BOTLIB_AAS_FLOAT_FOR_BSP_EPAIR_KEY,
+        BOTLIB_AAS_INT_FOR_BSP_EPAIR_KEY,
+
+        BOTLIB_AAS_AREA_REACHABILITY,
+
+        BOTLIB_AAS_AREA_TRAVEL_TIME_TO_GOAL_AREA,
+
+        BOTLIB_AAS_SWIMMING,
+        BOTLIB_AAS_PREDICT_CLIENT_MOVEMENT,
+
+
+
+        BOTLIB_EA_SAY = 400,
+        BOTLIB_EA_SAY_TEAM,
+        BOTLIB_EA_USE_ITEM,
+        BOTLIB_EA_DROP_ITEM,
+        BOTLIB_EA_USE_INV,
+        BOTLIB_EA_DROP_INV,
+        BOTLIB_EA_GESTURE,
+        BOTLIB_EA_COMMAND,
+
+        BOTLIB_EA_SELECT_WEAPON,
+        BOTLIB_EA_TALK,
+        BOTLIB_EA_ATTACK,
+        BOTLIB_EA_USE,
+        BOTLIB_EA_RESPAWN,
+        BOTLIB_EA_JUMP,
+        BOTLIB_EA_DELAYED_JUMP,
+        BOTLIB_EA_CROUCH,
+        BOTLIB_EA_MOVE_UP,
+        BOTLIB_EA_MOVE_DOWN,
+        BOTLIB_EA_MOVE_FORWARD,
+        BOTLIB_EA_MOVE_BACK,
+        BOTLIB_EA_MOVE_LEFT,
+        BOTLIB_EA_MOVE_RIGHT,
+        BOTLIB_EA_MOVE,
+        BOTLIB_EA_VIEW,
+
+        BOTLIB_EA_END_REGULAR,
+        BOTLIB_EA_GET_INPUT,
+        BOTLIB_EA_RESET_INPUT,
+        BOTLIB_EA_ALT_ATTACK,
+
+
+
+        BOTLIB_AI_LOAD_CHARACTER = 500,
+        BOTLIB_AI_FREE_CHARACTER,
+        BOTLIB_AI_CHARACTERISTIC_FLOAT,
+        BOTLIB_AI_CHARACTERISTIC_BFLOAT,
+        BOTLIB_AI_CHARACTERISTIC_INTEGER,
+        BOTLIB_AI_CHARACTERISTIC_BINTEGER,
+        BOTLIB_AI_CHARACTERISTIC_STRING,
+
+        BOTLIB_AI_ALLOC_CHAT_STATE,
+        BOTLIB_AI_FREE_CHAT_STATE,
+        BOTLIB_AI_QUEUE_CONSOLE_MESSAGE,
+        BOTLIB_AI_REMOVE_CONSOLE_MESSAGE,
+        BOTLIB_AI_NEXT_CONSOLE_MESSAGE,
+        BOTLIB_AI_NUM_CONSOLE_MESSAGE,
+        BOTLIB_AI_INITIAL_CHAT,
+        BOTLIB_AI_REPLY_CHAT,
+        BOTLIB_AI_CHAT_LENGTH,
+        BOTLIB_AI_ENTER_CHAT,
+        BOTLIB_AI_STRING_CONTAINS,
+        BOTLIB_AI_FIND_MATCH,
+        BOTLIB_AI_MATCH_VARIABLE,
+        BOTLIB_AI_UNIFY_WHITE_SPACES,
+        BOTLIB_AI_REPLACE_SYNONYMS,
+        BOTLIB_AI_LOAD_CHAT_FILE,
+        BOTLIB_AI_SET_CHAT_GENDER,
+        BOTLIB_AI_SET_CHAT_NAME,
+
+        BOTLIB_AI_RESET_GOAL_STATE,
+        BOTLIB_AI_RESET_AVOID_GOALS,
+        BOTLIB_AI_PUSH_GOAL,
+        BOTLIB_AI_POP_GOAL,
+        BOTLIB_AI_EMPTY_GOAL_STACK,
+        BOTLIB_AI_DUMP_AVOID_GOALS,
+        BOTLIB_AI_DUMP_GOAL_STACK,
+        BOTLIB_AI_GOAL_NAME,
+        BOTLIB_AI_GET_TOP_GOAL,
+        BOTLIB_AI_GET_SECOND_GOAL,
+        BOTLIB_AI_CHOOSE_LTG_ITEM,
+        BOTLIB_AI_CHOOSE_NBG_ITEM,
+        BOTLIB_AI_TOUCHING_GOAL,
+        BOTLIB_AI_ITEM_GOAL_IN_VIS_BUT_NOT_VISIBLE,
+        BOTLIB_AI_GET_LEVEL_ITEM_GOAL,
+        BOTLIB_AI_AVOID_GOAL_TIME,
+        BOTLIB_AI_INIT_LEVEL_ITEMS,
+        BOTLIB_AI_UPDATE_ENTITY_ITEMS,
+        BOTLIB_AI_LOAD_ITEM_WEIGHTS,
+        BOTLIB_AI_FREE_ITEM_WEIGHTS,
+        BOTLIB_AI_SAVE_GOAL_FUZZY_LOGIC,
+        BOTLIB_AI_ALLOC_GOAL_STATE,
+        BOTLIB_AI_FREE_GOAL_STATE,
+
+        BOTLIB_AI_RESET_MOVE_STATE,
+        BOTLIB_AI_MOVE_TO_GOAL,
+        BOTLIB_AI_MOVE_IN_DIRECTION,
+        BOTLIB_AI_RESET_AVOID_REACH,
+        BOTLIB_AI_RESET_LAST_AVOID_REACH,
+        BOTLIB_AI_REACHABILITY_AREA,
+        BOTLIB_AI_MOVEMENT_VIEW_TARGET,
+        BOTLIB_AI_ALLOC_MOVE_STATE,
+        BOTLIB_AI_FREE_MOVE_STATE,
+        BOTLIB_AI_INIT_MOVE_STATE,
+
+        BOTLIB_AI_CHOOSE_BEST_FIGHT_WEAPON,
+        BOTLIB_AI_GET_WEAPON_INFO,
+        BOTLIB_AI_LOAD_WEAPON_WEIGHTS,
+        BOTLIB_AI_ALLOC_WEAPON_STATE,
+        BOTLIB_AI_FREE_WEAPON_STATE,
+        BOTLIB_AI_RESET_WEAPON_STATE,
+
+        BOTLIB_AI_GENETIC_PARENTS_AND_CHILD_SELECTION,
+        BOTLIB_AI_INTERBREED_GOAL_FUZZY_LOGIC,
+        BOTLIB_AI_MUTATE_GOAL_FUZZY_LOGIC,
+        BOTLIB_AI_GET_NEXT_CAMP_SPOT_GOAL,
+        BOTLIB_AI_GET_MAP_LOCATION_GOAL,
+        BOTLIB_AI_NUM_INITIAL_CHATS,
+        BOTLIB_AI_GET_CHAT_MESSAGE,
+        BOTLIB_AI_REMOVE_FROM_AVOID_GOALS,
+        BOTLIB_AI_PREDICT_VISIBLE_POSITION
+} gameImport_t;
+#else
+typedef enum {
 	//============== general Quake services ==================
 
 	G_PRINT,		// ( const char *string );
@@ -389,8 +675,8 @@
 	BOTLIB_PC_SOURCE_FILE_AND_LINE
 
 } gameImport_t;
+#endif
 
-
 //
 // functions exported by the game subsystem
 //
Index: code/game/bg_public.h
===================================================================
--- code/game/bg_public.h	(revision 965)
+++ code/game/bg_public.h	(working copy)
@@ -263,6 +263,11 @@
 #define EF_AWARD_DENIED		0x00040000		// denied
 #define EF_TEAMVOTED		0x00080000		// already cast a team vote
 
+#ifdef ELITEFORCE
+#define EF_SHIELD_BOX_X		0x00000800
+#define EF_SHIELD_BOX_Y		0x00400000
+#endif
+
 // NOTE: may not have more than 16
 typedef enum {
 	PW_NONE,
Index: code/botlib/be_ai_chat.c
===================================================================
--- code/botlib/be_ai_chat.c	(revision 965)
+++ code/botlib/be_ai_chat.c	(working copy)
@@ -2797,10 +2797,17 @@
 void BotEnterChat(int chatstate, int clientto, int sendto)
 {
 	bot_chatstate_t *cs;
-
+	int clientnum;
+	
 	cs = BotChatStateFromHandle(chatstate);
 	if (!cs) return;
 
+	#ifdef ELITEFORCE
+	clientnum = clientto;
+	#else
+	clientnum = cs->client;
+	#endif
+
 	if (strlen(cs->chatmessage))
 	{
 		BotRemoveTildes(cs->chatmessage);
@@ -2810,13 +2817,15 @@
 		else {
 			switch(sendto) {
 				case CHAT_TEAM:
-					EA_Command(cs->client, va("say_team %s", cs->chatmessage));
+					EA_Command(clientnum, va("say_team %s", cs->chatmessage));
 					break;
+#ifndef ELITEFORCE
 				case CHAT_TELL:
-					EA_Command(cs->client, va("tell %d %s", clientto, cs->chatmessage));
+					EA_Command(clientnum, va("tell %d %s", clientto, cs->chatmessage));
 					break;
+#endif
 				default: //CHAT_ALL
-					EA_Command(cs->client, va("say %s", cs->chatmessage));
+					EA_Command(clientnum, va("say %s", cs->chatmessage));
 					break;
 			}
 		}
@@ -2868,13 +2877,19 @@
 // Returns:					-
 // Changes Globals:		-
 //===========================================================================
+#ifdef ELITEFORCE
+void BotSetChatName(int chatstate, char *name)
+#else
 void BotSetChatName(int chatstate, char *name, int client)
+#endif
 {
 	bot_chatstate_t *cs;
 
 	cs = BotChatStateFromHandle(chatstate);
 	if (!cs) return;
+#ifndef ELITEFORCE
 	cs->client = client;
+#endif
 	Com_Memset(cs->name, 0, sizeof(cs->name));
 	strncpy(cs->name, name, sizeof(cs->name));
 	cs->name[sizeof(cs->name)-1] = '\0';
@@ -2975,11 +2990,13 @@
 	file = LibVarString("matchfile", "match.c");
 	matchtemplates = BotLoadMatchTemplates(file);
 	//
+#ifndef ELITEFORCE
 	if (!LibVarValue("nochat", "0"))
 	{
 		file = LibVarString("rchatfile", "rchat.c");
 		replychats = BotLoadReplyChat(file);
 	} //end if
+#endif
 
 	InitConsoleMessageHeap();
 
Index: code/botlib/be_ea.h
===================================================================
--- code/botlib/be_ea.h	(revision 965)
+++ code/botlib/be_ea.h	(working copy)
@@ -45,6 +45,13 @@
 void EA_MoveLeft(int client);
 void EA_MoveRight(int client);
 void EA_Attack(int client);
+#ifdef ELITEFORCE
+void EA_AltAttack(int client);
+void EA_UseItem(int client, char *it);
+void EA_DropItem(int client, char *it);
+void EA_UseInv(int client, char *inv);
+void EA_DropInv(int client, char *inv);
+#endif
 void EA_Respawn(int client);
 void EA_Talk(int client);
 void EA_Gesture(int client);
Index: code/botlib/be_ai_goal.c
===================================================================
--- code/botlib/be_ai_goal.c	(revision 965)
+++ code/botlib/be_ai_goal.c	(working copy)
@@ -374,7 +374,11 @@
 
 	if (levelitemheap) FreeMemory(levelitemheap);
 
+#ifdef ELITEFORCE
+	max_levelitems = (int) LibVarValue("max_levelitems", "1024");
+#else
 	max_levelitems = (int) LibVarValue("max_levelitems", "256");
+#endif
 	levelitemheap = (levelitem_t *) GetClearedMemory(max_levelitems * sizeof(levelitem_t));
 
 	for (i = 0; i < max_levelitems-1; i++)
Index: code/botlib/be_ai_chat.h
===================================================================
--- code/botlib/be_ai_chat.h	(revision 965)
+++ code/botlib/be_ai_chat.h	(working copy)
@@ -109,5 +109,8 @@
 //store the gender of the bot in the chat state
 void BotSetChatGender(int chatstate, int gender);
 //store the bot name in the chat state
+#ifdef ELITEFORCE
+void BotSetChatName(int chatstate, char *name);
+#else
 void BotSetChatName(int chatstate, char *name, int client);
-
+#endif
Index: code/botlib/be_interface.c
===================================================================
--- code/botlib/be_interface.c	(revision 965)
+++ code/botlib/be_interface.c	(working copy)
@@ -731,6 +731,13 @@
 	ea->EA_Gesture = EA_Gesture;
 	ea->EA_Talk = EA_Talk;
 	ea->EA_Attack = EA_Attack;
+#ifdef ELITEFORCE
+	ea->EA_AltAttack = EA_AltAttack;
+	ea->EA_UseItem = EA_UseItem;
+	ea->EA_DropItem = EA_DropItem;
+	ea->EA_UseInv = EA_UseInv;
+	ea->EA_DropInv = EA_DropInv;
+#endif
 	ea->EA_Use = EA_Use;
 	ea->EA_Respawn = EA_Respawn;
 	ea->EA_Crouch = EA_Crouch;
Index: code/botlib/be_ai_weap.c
===================================================================
--- code/botlib/be_ai_weap.c	(revision 965)
+++ code/botlib/be_ai_weap.c	(working copy)
@@ -417,7 +417,11 @@
 	if (!ws->weaponweightconfig) return 0;
 
 	bestweight = 0;
+#ifdef ELITEFORCE
+	bestweapon = 1;
+#else
 	bestweapon = 0;
+#endif
 	for (i = 0; i < wc->numweapons; i++)
 	{
 		if (!wc->weaponinfo[i].valid) continue;
Index: code/botlib/botlib.h
===================================================================
--- code/botlib/botlib.h	(revision 965)
+++ code/botlib/botlib.h	(working copy)
@@ -81,6 +81,9 @@
 //action flags
 #define ACTION_ATTACK			0x0000001
 #define ACTION_USE				0x0000002
+#ifdef ELITEFORCE
+#define ACTION_ALTATTACK		0x0000004
+#endif
 #define ACTION_RESPAWN			0x0000008
 #define ACTION_JUMP				0x0000010
 #define ACTION_MOVEUP			0x0000020
@@ -275,6 +278,13 @@
 	void	(*EA_Gesture)(int client);
 	void	(*EA_Talk)(int client);
 	void	(*EA_Attack)(int client);
+#ifdef ELITEFORCE
+	void	(*EA_AltAttack)(int client);
+	void	(*EA_UseItem)(int client, char *it);
+	void	(*EA_DropItem)(int client, char *it);
+	void	(*EA_UseInv)(int client, char *inv);
+	void	(*EA_DropInv)(int client, char *inv);
+#endif
 	void	(*EA_Use)(int client);
 	void	(*EA_Respawn)(int client);
 	void	(*EA_MoveUp)(int client);
@@ -330,7 +340,11 @@
 	void	(*BotReplaceSynonyms)(char *string, unsigned long int context);
 	int		(*BotLoadChatFile)(int chatstate, char *chatfile, char *chatname);
 	void	(*BotSetChatGender)(int chatstate, int gender);
+#ifdef ELITEFORCE
+	void	(*BotSetChatName)(int chatstate, char *name);
+#else
 	void	(*BotSetChatName)(int chatstate, char *name, int client);
+#endif
 	//-----------------------------------
 	// be_ai_goal.h
 	//-----------------------------------
Index: code/botlib/be_aas_entity.c
===================================================================
--- code/botlib/be_aas_entity.c	(revision 965)
+++ code/botlib/be_aas_entity.c	(working copy)
@@ -51,7 +51,20 @@
 	ET_PLAYER,
 	ET_ITEM,
 	ET_MISSILE,
+#ifdef ELITEFORCE
+	ET_ALT_MISSILE,
+	ET_MOVER,
+	ET_BEAM,
+	ET_PORTAL,
+	ET_SPEAKER,
+	ET_PUSH_TRIGGER,
+	ET_TELEPORT_TRIGGER,
+	ET_INVISIBLE,
+	ET_USEABLE,
+	ET_EVENTS
+#else
 	ET_MOVER
+#endif
 };
 
 //===========================================================================
Index: code/botlib/be_ea.c
===================================================================
--- code/botlib/be_ea.c	(revision 965)
+++ code/botlib/be_ea.c	(working copy)
@@ -171,6 +171,22 @@
 // Returns:				-
 // Changes Globals:		-
 //===========================================================================
+#ifdef ELITEFORCE
+void EA_AltAttack(int client)
+{
+	bot_input_t *bi;
+
+	bi = &botinputs[client];
+
+	bi->actionflags |= ACTION_ALTATTACK;
+} //end of the function EA_AltAttack
+//===========================================================================
+//
+// Parameter:			-
+// Returns:				-
+// Changes Globals:		-
+//===========================================================================
+#endif
 void EA_Talk(int client)
 {
 	bot_input_t *bi;
@@ -205,7 +221,11 @@
 
 	bi = &botinputs[client];
 
+#ifdef ELITEFORCE
+	bi->actionflags |= ACTION_ATTACK;
+#else
 	bi->actionflags |= ACTION_RESPAWN;
+#endif
 } //end of the function EA_Respawn
 //===========================================================================
 //
Index: code/cgame/cg_public.h
===================================================================
--- code/cgame/cg_public.h	(revision 965)
+++ code/cgame/cg_public.h	(working copy)
@@ -131,6 +131,7 @@
 	CG_SETUSERCMDVALUE,
 	CG_R_REGISTERSHADERNOMIP,
 	CG_MEMORY_REMAINING,
+#ifndef ELITEFORCE
 	CG_R_REGISTERFONT,
 	CG_KEY_ISDOWN,
 	CG_KEY_GETCATCHER,
@@ -170,7 +171,10 @@
 	CG_STARTCAMERA,
 	CG_GETCAMERAINFO,
 */
-
+#else
+        CG_R_REGISTERSHADER3D,  //59
+        CG_CVAR_SET_NO_MODIFY,  // 60
+#endif      
 	CG_MEMSET = 100,
 	CG_MEMCPY,
 	CG_STRNCPY,
@@ -182,7 +186,9 @@
 	CG_CEIL,
 	CG_TESTPRINTINT,
 	CG_TESTPRINTFLOAT,
+#ifndef ELITEFORCE
 	CG_ACOS
+#endif
 } cgameImport_t;
 
 
@@ -225,7 +231,7 @@
 
 	CG_LAST_ATTACKER,
 //	int (*CG_LastAttacker)( void );
-
+#ifndef ELITEFORCE
 	CG_KEY_EVENT, 
 //	void	(*CG_KeyEvent)( int key, qboolean down );
 
@@ -233,6 +239,7 @@
 //	void	(*CG_MouseEvent)( int dx, int dy );
 	CG_EVENT_HANDLING
 //	void (*CG_EventHandling)(int type);
+#endif
 } cgameExport_t;
 
 //----------------------------------------------
Index: code/ui/ui_public.h
===================================================================
--- code/ui/ui_public.h	(revision 965)
+++ code/ui/ui_public.h	(working copy)
@@ -81,6 +81,12 @@
 	UI_GETGLCONFIG,
 	UI_GETCLIENTSTATE,
 	UI_GETCONFIGSTRING,
+#ifdef ELITEFORCE
+	UI_LAN_GETLOCALSERVERCOUNT,
+	UI_LAN_GETLOCALSERVERADDRESSSTRING,
+	UI_LAN_GETGLOBALSERVERCOUNT,
+	UI_LAN_GETGLOBALSERVERADDRESSSTRING,
+#endif                                
 	UI_LAN_GETPINGQUEUECOUNT,
 	UI_LAN_CLEARPING,
 	UI_LAN_GETPING,
@@ -88,6 +94,10 @@
 	UI_CVAR_REGISTER,
 	UI_CVAR_UPDATE,
 	UI_MEMORY_REMAINING,
+#ifdef ELITEFORCE
+	UI_SET_CDKEY,
+	UI_R_MODELBOUNDS,
+#else
 	UI_GET_CDKEY,
 	UI_SET_CDKEY,
 	UI_R_REGISTERFONT,
@@ -124,6 +134,7 @@
 	// 1.32
 	UI_FS_SEEK,
 	UI_SET_PBCLSTATUS,
+#endif
 
 	UI_MEMSET = 100,
 	UI_MEMCPY,
@@ -182,7 +193,9 @@
 
 	UI_DRAW_CONNECT_SCREEN,
 //	void	UI_DrawConnectScreen( qboolean overlay );
+#ifndef ELITEFORCE
 	UI_HASUNIQUECDKEY
+#endif
 // if !overlay, the background will be drawn, otherwise it will be
 // overlayed over whatever the cgame has drawn.
 // a GetClientState syscall will be made to get the current strings
Index: code/client/cl_input.c
===================================================================
--- code/client/cl_input.c	(revision 965)
+++ code/client/cl_input.c	(working copy)
@@ -353,8 +353,10 @@
 void CL_MouseEvent( int dx, int dy, int time ) {
 	if ( cls.keyCatchers & KEYCATCH_UI ) {
 		VM_Call( uivm, UI_MOUSE_EVENT, dx, dy );
+#ifndef ELITEFORCE
 	} else if (cls.keyCatchers & KEYCATCH_CGAME) {
 		VM_Call (cgvm, CG_MOUSE_EVENT, dx, dy);
+#endif
 	} else {
 		cl.mouseDx[cl.mouseIndex] += dx;
 		cl.mouseDy[cl.mouseIndex] += dy;
@@ -694,7 +696,10 @@
 	usercmd_t	nullcmd;
 	int			packetNum;
 	int			oldPacketNum;
-	int			count, key;
+	int			count;
+	#ifndef ELITEFORCE
+	int			key;
+	#endif
 
 	// don't send anything if playing back a demo
 	if ( clc.demoplaying || cls.state == CA_CINEMATIC ) {
@@ -704,9 +709,21 @@
 	Com_Memset( &nullcmd, 0, sizeof(nullcmd) );
 	oldcmd = &nullcmd;
 
-	MSG_Init( &buf, data, sizeof(data) );
+	#ifdef ELITEFORCE
+	if(clc.compat)
+	{
+		MSG_InitOOB( &buf, data, sizeof(data) );
+		buf.compat = clc.compat;
+	}
+	else
+	{	
+	#endif
+		MSG_Init( &buf, data, sizeof(data) );
+		MSG_Bitstream( &buf );
+	#ifdef ELITEFORCE
+	}
+	#endif
 
-	MSG_Bitstream( &buf );
 	// write the current serverId so the server
 	// can tell if this is from the current gameState
 	MSG_WriteLong( &buf, cl.serverId );
@@ -756,18 +773,24 @@
 		// write the command count
 		MSG_WriteByte( &buf, count );
 
+#ifndef ELITEFORCE
 		// use the checksum feed in the key
 		key = clc.checksumFeed;
 		// also use the message acknowledge
 		key ^= clc.serverMessageSequence;
 		// also use the last acknowledged server command in the key
 		key ^= Com_HashKey(clc.serverCommands[ clc.serverCommandSequence & (MAX_RELIABLE_COMMANDS-1) ], 32);
+#endif
 
 		// write all the commands, including the predicted command
 		for ( i = 0 ; i < count ; i++ ) {
 			j = (cl.cmdNumber - count + i + 1) & CMD_MASK;
 			cmd = &cl.cmds[j];
+#ifdef ELITEFORCE
+			MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
+#else
 			MSG_WriteDeltaUsercmdKey (&buf, key, oldcmd, cmd);
+#endif
 			oldcmd = cmd;
 		}
 	}
@@ -874,6 +897,12 @@
 	Cmd_AddCommand ("-button3", IN_Button3Up);
 	Cmd_AddCommand ("+button4", IN_Button4Down);
 	Cmd_AddCommand ("-button4", IN_Button4Up);
+#ifdef ELITEFORCE
+	Cmd_AddCommand ("+altattack", IN_Button5Down);
+	Cmd_AddCommand ("-altattack", IN_Button5Up);
+	Cmd_AddCommand ("+use", IN_Button6Down);
+	Cmd_AddCommand ("-use", IN_Button6Up);
+#endif
 	Cmd_AddCommand ("+button5", IN_Button5Down);
 	Cmd_AddCommand ("-button5", IN_Button5Up);
 	Cmd_AddCommand ("+button6", IN_Button6Down);
Index: code/client/snd_codec.c
===================================================================
--- code/client/snd_codec.c	(revision 965)
+++ code/client/snd_codec.c	(working copy)
@@ -105,6 +105,9 @@
 #if USE_CODEC_VORBIS
 	S_CodecRegister(&ogg_codec);
 #endif
+#if USE_CODEC_MP3
+	S_CodecRegister(&mp3_codec);
+#endif
 }
 
 /*
@@ -133,22 +136,111 @@
 S_CodecLoad
 =================
 */
-void *S_CodecLoad(const char *filename, snd_info_t *info)
+
+#ifdef ELITEFORCE
+qboolean S_EFCheckExtension(char *filename)
 {
-	snd_codec_t *codec;
+	fileHandle_t hnd;
 	char fn[MAX_QPATH];
+	int stringlen = strlen(filename);
+	char *extptr;
+	
+	strncpy(fn, filename, stringlen+1);
+	extptr = strrchr(fn, '.');
 
-	codec = S_FindCodecForFile(filename);
-	if(!codec)
+	if(!extptr)
 	{
-		Com_Printf("Unknown extension for %s\n", filename);
-		return NULL;
+		extptr = &fn[stringlen];
+		
+		extptr[0] = '.';
+		extptr[1] = 'w';
+		extptr[2] = 'a';
+		extptr[3] = 'v';
+		extptr[4] = '\0';
+		
+		stringlen += 4;
 	}
+	
+	FS_FOpenFileRead(fn, &hnd, qtrue);
 
+	if(!hnd)
+	{
+		if(!strcmp(++extptr, "wav"))
+		{
+			extptr[0] = 'm';
+			extptr[1] = 'p';
+			extptr[2] = '3';
+
+			FS_FOpenFileRead(fn, &hnd, qtrue);
+			
+			if(!hnd)
+				return qfalse;
+		}
+		else
+			return qfalse;
+	}
+	
+	FS_FCloseFile(hnd);
+	strcpy(filename, fn);
+
+	return qtrue;
+}
+
+qboolean S_EFGetFileName(char *filename)
+{
+	char fn[MAX_QPATH];
+	qboolean dschoermen = qfalse;
+
+	if(!Q_stricmp(Cvar_VariableString("s_language"), "DEUTSCH"))
+		dschoermen = qtrue;
+
+	strncpy(fn, filename, sizeof(fn) - 10);
+
+	if(dschoermen && strstr(filename, "sound/voice") == filename)
+	{
+		fn[8] = 'x';
+		fn[9] = '_';
+		fn[10] = 'd';
+	
+		if(S_EFCheckExtension(fn))
+		{
+			strcpy(filename, fn);
+			return qtrue;
+		}
+	}
+
+	if(S_EFCheckExtension(filename))
+		return qtrue;
+	
+	return qfalse;
+}
+#endif
+
+void *S_CodecLoad(const char *filename, snd_info_t *info)
+{
+        snd_codec_t *codec;
+        char fn[MAX_QPATH];
+
+#ifdef ELITEFORCE
 	strncpy(fn, filename, sizeof(fn));
-	COM_DefaultExtension(fn, sizeof(fn), codec->ext);
+	if(!S_EFGetFileName(fn))
+		return NULL;
+        codec = S_FindCodecForFile(fn);
+#else
+        codec = S_FindCodecForFile(filename);
+#endif
+        if(!codec)
+        {
+                Com_Printf("Unknown extension for %s\n", filename);
+                return NULL;
+        }
 
-	return codec->load(fn, info);
+#ifndef ELITEFORCE
+        strncpy(fn, filename, sizeof(fn));
+        COM_DefaultExtension(fn, sizeof(fn), codec->ext);
+#endif
+
+        return codec->load(fn, info);
 }
 
 /*
Index: code/client/cl_scrn.c
===================================================================
--- code/client/cl_scrn.c	(revision 965)
+++ code/client/cl_scrn.c	(working copy)
@@ -160,7 +160,7 @@
 void SCR_DrawSmallChar( int x, int y, int ch ) {
 	int row, col;
 	float frow, fcol;
-	float size;
+	float vsize, hsize;
 
 	ch &= 255;
 
@@ -177,11 +177,16 @@
 
 	frow = row*0.0625;
 	fcol = col*0.0625;
-	size = 0.0625;
+	vsize = 0.0625;
+#ifdef ELITEFORCE
+	hsize = 0.03125;
+#else
+	hsize = 0.0625;
+#endif
 
 	re.DrawStretchPic( x, y, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT,
 					   fcol, frow, 
-					   fcol + size, frow + size, 
+					   fcol + hsize, frow + vsize, 
 					   cls.charSetShader );
 }
 
@@ -252,6 +257,16 @@
 	SCR_DrawStringExt( x, y, BIGCHAR_WIDTH, s, color, qtrue );
 }
 
+#ifdef ELITEFORCE
+void SCR_DrawSmallString(int x, int y, const char *s, float alpha)
+{
+	float   color[4];
+	
+	color[0] = color[1] = color[2] = 1.0;
+	color[3] = alpha;
+	SCR_DrawSmallStringExt(x, y, s, color, qfalse);
+}
+#endif
 
 /*
 ==================
Index: code/client/client.h
===================================================================
--- code/client/client.h	(revision 965)
+++ code/client/client.h	(working copy)
@@ -219,6 +219,10 @@
 	int			timeDemoStart;		// cls.realtime before first frame
 	int			timeDemoBaseTime;	// each frame will be at this time + frameNum * 50
 
+#ifdef ELITEFORCE
+        qboolean	compat;		// Compatibility mode for old EliteForce servers.
+#endif
+
 	// big stuff at end of structure so most offsets are 15 bits or less
 	netchan_t	netchan;
 } clientConnection_t;
@@ -495,6 +499,9 @@
 
 void	SCR_DrawBigString( int x, int y, const char *s, float alpha );			// draws a string with embedded color control characters with fade
 void	SCR_DrawBigStringColor( int x, int y, const char *s, vec4_t color );	// ignores embedded color control characters
+#ifdef ELITEFORCE
+void	SCR_DrawSmallString( int x, int y, const char *s, float alpha );	// draws a string with embedded color control characters with fade
+#endif
 void	SCR_DrawSmallStringExt( int x, int y, const char *string, float *setColor, qboolean forceColor );
 void	SCR_DrawSmallChar( int x, int y, int ch );
 
Index: code/client/snd_codec.h
===================================================================
--- code/client/snd_codec.h	(revision 965)
+++ code/client/snd_codec.h	(working copy)
@@ -95,4 +95,13 @@
 int S_OGG_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer);
 #endif // USE_CODEC_VORBIS
 
+// MP3 codec
+#ifdef USE_CODEC_MP3
+extern snd_codec_t mp3_codec;
+void *S_MP3_CodecLoad(const char *filename, snd_info_t *info);
+snd_stream_t *S_MP3_CodecOpenStream(const char *filename);
+void S_MP3_CodecCloseStream(snd_stream_t *stream);
+int S_MP3_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer);
+#endif // USE_CODEC_MP3
+
 #endif // !_SND_CODEC_H_
Index: code/client/cl_parse.c
===================================================================
--- code/client/cl_parse.c	(revision 965)
+++ code/client/cl_parse.c	(working copy)
@@ -207,8 +207,11 @@
 
 	// get the reliable sequence acknowledge number
 	// NOTE: now sent with all server to client messages
-	//clc.reliableAcknowledge = MSG_ReadLong( msg );
-
+	#ifdef ELITEFORCE
+	if(msg->compat)
+		clc.reliableAcknowledge = MSG_ReadLong( msg );
+	#endif
+	
 	// read in the new snapshot to a temporary buffer
 	// we will only copy to cl.snap if it is valid
 	Com_Memset (&newSnap, 0, sizeof(newSnap));
@@ -459,9 +462,12 @@
 	while ( 1 ) {
 		cmd = MSG_ReadByte( msg );
 
-		if ( cmd == svc_EOF ) {
+		#ifdef ELITEFORCE
+		if((msg->compat && cmd <= 0) || cmd == svc_EOF)
+		#else
+		if ( cmd == svc_EOF )
+		#endif
 			break;
-		}
 		
 		if ( cmd == svc_configstring ) {
 			int		len;
@@ -494,9 +500,16 @@
 		}
 	}
 
-	clc.clientNum = MSG_ReadLong(msg);
+	#ifdef ELITEFORCE
+	if(!msg->compat)
+	#endif
+		clc.clientNum = MSG_ReadLong(msg);
+	
 	// read the checksum feed
-	clc.checksumFeed = MSG_ReadLong( msg );
+	#ifdef ELITEFORCE
+	if(!clc.demoplaying || !msg->compat)
+	#endif
+		clc.checksumFeed = MSG_ReadLong( msg );
 
 	// parse useful values out of CS_SERVERINFO
 	CL_ParseServerInfo();
@@ -660,15 +673,22 @@
 		Com_Printf ("------------------\n");
 	}
 
-	MSG_Bitstream(msg);
+	#ifdef ELITEFORCE
+	if(!msg->compat)
+	{
+	#endif
+		MSG_Bitstream(msg);
 
-	// get the reliable sequence acknowledge number
-	clc.reliableAcknowledge = MSG_ReadLong( msg );
-	// 
-	if ( clc.reliableAcknowledge < clc.reliableSequence - MAX_RELIABLE_COMMANDS ) {
-		clc.reliableAcknowledge = clc.reliableSequence;
+		// get the reliable sequence acknowledge number
+		clc.reliableAcknowledge = MSG_ReadLong( msg );
+		// 
+		if ( clc.reliableAcknowledge < clc.reliableSequence - MAX_RELIABLE_COMMANDS ) {
+			clc.reliableAcknowledge = clc.reliableSequence;
+		}
+	#ifdef ELITEFORCE
 	}
-
+	#endif
+	
 	//
 	// parse the message
 	//
@@ -680,7 +700,12 @@
 
 		cmd = MSG_ReadByte( msg );
 
-		if ( cmd == svc_EOF) {
+		#ifdef ELITEFORCE
+		if(cmd == svc_EOF || (msg->compat && cmd == -1))
+		#else
+		if ( cmd == svc_EOF)
+		#endif
+		{
 			SHOWNET( msg, "END OF MESSAGE" );
 			break;
 		}
Index: code/client/snd_codec_mp3.c
===================================================================
--- code/client/snd_codec_mp3.c	(revision 0)
+++ code/client/snd_codec_mp3.c	(revision 0)
@@ -0,0 +1,716 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
+Copyright (C) 2005-2006 Joerg Dietrich <dietrich_joerg@gmx.de>
+Copyright (C) 2006 Thilo Schulz <arny@ats.s.bawue.de>
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Quake III Arena source code; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+===========================================================================
+*/
+
+// MP3 support is enabled by this define
+#if USE_CODEC_MP3
+
+// includes for the Q3 sound system
+#include "client.h"
+#include "snd_codec.h"
+
+// includes for the MP3 codec
+#include <mad.h>
+
+#define MP3_SAMPLE_WIDTH		2
+#define MP3_PCMSAMPLES_PERSLICE		32
+
+// buffer size used when reading through the mp3
+#define MP3_DATA_BUFSIZ			128*1024
+
+// undefine this if you don't want any dithering.
+#define MP3_DITHERING
+
+// Q3 MP3 codec
+snd_codec_t mp3_codec =
+{
+	".mp3",
+	S_MP3_CodecLoad,
+	S_MP3_CodecOpenStream,
+	S_MP3_CodecReadStream,
+	S_MP3_CodecCloseStream,
+	NULL
+};
+
+// structure used for info purposes
+struct snd_codec_mp3_info
+{
+	byte encbuf[MP3_DATA_BUFSIZ];	// left over bytes not consumed
+					// by the decoder.
+	struct mad_stream madstream;	// uses encbuf as buffer.
+	struct mad_frame madframe;	// control structures for libmad.
+	struct mad_synth madsynth;
+
+	byte *pcmbuf;			// buffer for not-used samples.
+	int buflen;			// length of buffer data.
+	int pcmbufsize;			// amount of allocated memory for
+					// pcmbuf. This should have at least
+					// the size of a decoded mp3 frame.	
+
+	byte *dest;			// copy decoded data here.
+	int destlen;			// amount of already copied data.
+	int destsize;			// amount of bytes we must decode.
+};
+
+/*************** MP3 utility functions ***************/
+
+/*
+=================
+S_MP3_ReadData
+=================
+*/
+
+// feed libmad with data
+int S_MP3_ReadData(snd_stream_t *stream, struct mad_stream *madstream, byte *encbuf, int encbufsize)
+{
+	int retval;
+	int leftover;
+	
+	if(!stream)
+		return -1;
+	
+	leftover =  madstream->bufend - madstream->next_frame;
+	if(leftover > 0)
+		memmove(encbuf, madstream->this_frame, leftover);
+
+
+	// Fill the buffer right to the end
+	
+	retval = FS_Read(&encbuf[leftover], encbufsize - leftover, stream->file);
+
+	if(retval <= 0)
+	{
+		// EOF reached, that's ok.
+		return 0;
+	}
+	
+	mad_stream_buffer(madstream, encbuf, retval + leftover);
+	
+	return retval;
+}
+
+
+/*
+=================
+S_MP3_Scanfile
+
+to determine the samplecount, we apparently must get *all* headers :(
+I basically used the xmms-mad plugin source to see how this stuff works.
+
+returns a value < 0 on error.
+=================
+*/
+
+int S_MP3_Scanfile(snd_stream_t *stream)
+{
+	struct mad_stream madstream;
+	struct mad_header madheader;
+	int retval;
+	int samplecount;
+	byte encbuf[MP3_DATA_BUFSIZ];
+
+	// error out on invalid input.
+	if(!stream)
+		return -1;
+
+	mad_stream_init(&madstream);
+	mad_header_init(&madheader);
+	
+	while(1)
+	{
+		retval = S_MP3_ReadData(stream, &madstream, encbuf, sizeof(encbuf));
+		if(retval < 0)
+			return -1;
+		else if(retval == 0)
+			break;
+		
+		// Start decoding the headers.
+		while(1)
+		{
+			if((retval = mad_header_decode(&madheader, &madstream)) < 0)
+			{
+				if(madstream.error == MAD_ERROR_BUFLEN)
+				{
+					// We need to read more data
+					break;
+				}
+
+				if(!MAD_RECOVERABLE (madstream.error))
+				{
+					// unrecoverable error... we must bail out.
+					return retval;
+				}
+
+				mad_stream_skip(&madstream, madstream.skiplen);
+				continue;
+			}
+			
+			// we got a valid header.
+			
+			if(madheader.layer != MAD_LAYER_III)
+			{
+				// we don't support non-mp3s
+				return -1;
+			}
+
+			if(!stream->info.samples)
+			{
+				// This here is the very first frame. Set initial values now,
+				// that we expect to stay constant throughout the whole mp3.
+				
+				stream->info.rate = madheader.samplerate;
+				stream->info.width = MP3_SAMPLE_WIDTH;
+				stream->info.channels = MAD_NCHANNELS(&madheader);
+				stream->info.samples = 0;
+				stream->info.size = 0;				// same here.
+				stream->info.dataofs = 0;
+			}
+			else
+			{
+				// Check whether something changed that shouldn't.
+				
+				if(stream->info.rate != madheader.samplerate ||
+				   stream->info.channels != MAD_NCHANNELS(&madheader))
+					return -1;
+			}
+
+			// Update the counters
+			samplecount = MAD_NSBSAMPLES(&madheader) * MP3_PCMSAMPLES_PERSLICE;
+			stream->info.samples += samplecount;
+			stream->info.size += samplecount * stream->info.channels * stream->info.width;			
+		}
+	}
+	
+	// Reset the file pointer so we can do the real decoding.
+	FS_Seek(stream->file, 0, FS_SEEK_SET);
+	
+	return 0;
+}
+
+/************************ dithering functions ***************************/
+
+#ifdef MP3_DITHERING
+
+// All dithering done here is taken from the GPL'ed xmms-mad plugin.
+
+/* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura.       */
+/* Any feedback is very welcome. For any question, comments,       */
+/* see http://www.math.keio.ac.jp/matumoto/emt.html or email       */
+/* matumoto@math.keio.ac.jp                                        */
+
+/* Period parameters */
+#define MP3_DITH_N 624
+#define MP3_DITH_M 397
+#define MATRIX_A 0x9908b0df   /* constant vector a */
+#define UPPER_MASK 0x80000000 /* most significant w-r bits */
+#define LOWER_MASK 0x7fffffff /* least significant r bits */
+
+/* Tempering parameters */
+#define TEMPERING_MASK_B 0x9d2c5680
+#define TEMPERING_MASK_C 0xefc60000
+#define TEMPERING_SHIFT_U(y)  (y >> 11)
+#define TEMPERING_SHIFT_S(y)  (y << 7)
+#define TEMPERING_SHIFT_T(y)  (y << 15)
+#define TEMPERING_SHIFT_L(y)  (y >> 18)
+
+static unsigned long mt[MP3_DITH_N]; /* the array for the state vector  */
+static int mti=MP3_DITH_N+1; /* mti==MP3_DITH_N+1 means mt[MP3_DITH_N] is not initialized */
+
+/* initializing the array with a NONZERO seed */
+void sgenrand(unsigned long seed)
+{
+    /* setting initial seeds to mt[MP3_DITH_N] using         */
+    /* the generator Line 25 of Table 1 in          */
+    /* [KNUTH 1981, The Art of Computer Programming */
+    /*    Vol. 2 (2nd Ed.), pp102]                  */
+    mt[0]= seed & 0xffffffff;
+    for (mti=1; mti<MP3_DITH_N; mti++)
+        mt[mti] = (69069 * mt[mti-1]) & 0xffffffff;
+}
+
+unsigned long genrand(void)
+{
+    unsigned long y;
+    static unsigned long mag01[2]={0x0, MATRIX_A};
+    /* mag01[x] = x * MATRIX_A  for x=0,1 */
+
+    if (mti >= MP3_DITH_N) { /* generate MP3_DITH_N words at one time */
+        int kk;
+
+        if (mti == MP3_DITH_N+1)   /* if sgenrand() has not been called, */
+            sgenrand(4357); /* a default initial seed is used   */
+
+        for (kk=0;kk<MP3_DITH_N-MP3_DITH_M;kk++) {
+            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+            mt[kk] = mt[kk+MP3_DITH_M] ^ (y >> 1) ^ mag01[y & 0x1];
+        }
+        for (;kk<MP3_DITH_N-1;kk++) {
+            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+            mt[kk] = mt[kk+(MP3_DITH_M-MP3_DITH_N)] ^ (y >> 1) ^ mag01[y & 0x1];
+        }
+        y = (mt[MP3_DITH_N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
+        mt[MP3_DITH_N-1] = mt[MP3_DITH_M-1] ^ (y >> 1) ^ mag01[y & 0x1];
+
+        mti = 0;
+    }
+
+    y = mt[mti++];
+    y ^= TEMPERING_SHIFT_U(y);
+    y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
+    y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
+    y ^= TEMPERING_SHIFT_L(y);
+
+    return y;
+}
+
+long triangular_dither_noise(int nbits) {
+    // parameter nbits : the peak-to-peak amplitude desired (in bits)
+    //  use with nbits set to    2 + nber of bits to be trimmed.
+    // (because triangular is made from two uniformly distributed processes,
+    // it starts at 2 bits peak-to-peak amplitude)
+    // see The Theory of Dithered Quantization by Robert Alexander Wannamaker
+    // for complete proof of why that's optimal
+
+    long v = (genrand()/2 - genrand()/2); // in ]-2^31, 2^31[
+    //int signe = (v>0) ? 1 : -1;
+    long P = 1 << (32 - nbits); // the power of 2
+    v /= P;
+    // now v in ]-2^(nbits-1), 2^(nbits-1) [
+
+    return v;
+}
+
+#endif // MP3_DITHERING
+
+/************************ decoder functions ***************************/
+
+/*
+=================
+S_MP3_Scale
+
+Converts the signal to 16 bit LE-PCM data and does dithering.
+
+- borrowed from xmms-mad plugin source.
+=================
+*/
+
+/*
+ * xmms-mad - mp3 plugin for xmms
+ * Copyright (C) 2001-2002 Sam Clegg
+ */
+
+signed int S_MP3_Scale(mad_fixed_t sample)
+{
+	int n_bits_to_loose = MAD_F_FRACBITS + 1 - 16;
+#ifdef MP3_DITHERING
+	int dither;
+#endif
+	
+	// round
+	sample += (1L << (n_bits_to_loose - 1));
+
+#ifdef MP3_DITHERING
+	dither = triangular_dither_noise(n_bits_to_loose + 1);
+	sample += dither;
+#endif
+
+	/* clip */
+	if (sample >= MAD_F_ONE)
+		sample = MAD_F_ONE - 1;
+	else if (sample < -MAD_F_ONE)
+		sample = -MAD_F_ONE;
+
+	/* quantize */
+	return sample >> n_bits_to_loose;
+}
+
+
+
+/*
+=================
+S_MP3_PCMCopy
+
+Copy and convert pcm data until bytecount bytes have been written.
+return the position in pcm->samples.
+indicate the amount of actually written bytes in wrotecnt.
+=================
+*/
+
+int S_MP3_PCMCopy(byte *buf, struct mad_pcm *pcm, int bufofs,
+			 int sampleofs, int bytecount, int *wrotecnt)
+{
+	int written = 0;
+	signed int sample;
+	int framesize = pcm->channels * MP3_SAMPLE_WIDTH;
+
+	// add new pcm data.
+	while(written < bytecount && sampleofs < pcm->length)
+	{
+		sample = S_MP3_Scale(pcm->samples[0][sampleofs]);
+
+#ifdef Q3_BIG_ENDIAN
+		// output to 16 bit big endian PCM
+		buf[bufofs++] = (sample >> 8) & 0xff;
+		buf[bufofs++] = sample & 0xff;
+#else
+		// output to 16 bit little endian PCM
+		buf[bufofs++] = sample & 0xff;
+		buf[bufofs++] = (sample >> 8) & 0xff;
+#endif
+		
+		if(pcm->channels == 2)
+		{
+			sample = S_MP3_Scale(pcm->samples[1][sampleofs]);
+
+#ifdef Q3_BIG_ENDIAN
+			buf[bufofs++] = (sample >> 8) & 0xff;
+			buf[bufofs++] = sample & 0xff;
+#else
+			buf[bufofs++] = sample & 0xff;
+			buf[bufofs++] = (sample >> 8) & 0xff;
+#endif
+		}
+		
+		sampleofs++;
+		written += framesize;
+	}	
+
+	if(wrotecnt)
+		*wrotecnt = written;
+
+	return sampleofs;
+}
+
+
+/*
+=================
+S_MP3_Decode
+=================
+*/
+
+// gets executed for every decoded frame.
+int S_MP3_Decode(snd_stream_t *stream)
+{
+	struct snd_codec_mp3_info *mp3info;
+	struct mad_stream *madstream;
+	struct mad_frame *madframe;
+	struct mad_synth *madsynth;
+	struct mad_pcm *pcm;
+	int cursize;
+	int samplecount;
+	int needcount;
+	int wrote;
+	int retval;
+
+	if(!stream)
+		return -1;
+
+	mp3info = stream->ptr;
+	madstream = &mp3info->madstream;
+	madframe = &mp3info->madframe;
+
+	if(mad_frame_decode(madframe, madstream))
+	{
+		if(madstream->error == MAD_ERROR_BUFLEN)
+		{
+			// we need more data. Read another chunk.
+			retval = S_MP3_ReadData(stream, madstream, mp3info->encbuf, sizeof(mp3info->encbuf));
+
+			// call myself again now that buffer is full.
+			if(retval > 0)
+				retval = S_MP3_Decode(stream);
+		}
+		else if(MAD_RECOVERABLE(madstream->error))
+		{
+			mad_stream_skip(madstream, madstream->skiplen);
+			return S_MP3_Decode(stream);
+		}
+		else
+			retval = -1;
+
+		return retval;
+	}
+
+	// check whether this really is an mp3
+	if(madframe->header.layer != MAD_LAYER_III)
+		return -1;
+
+	// generate pcm data
+	madsynth = &mp3info->madsynth;
+	mad_synth_frame(madsynth, madframe);
+
+	pcm = &madsynth->pcm;
+
+	// perform a few checks to see whether something changed that shouldn't.
+		
+	if(stream->info.rate != pcm->samplerate ||
+	   stream->info.channels != pcm->channels)
+	{
+		return -1;
+	}
+	// see whether we have got enough data now.
+	cursize = pcm->length * pcm->channels * stream->info.width;
+	needcount = mp3info->destsize - mp3info->destlen;
+
+	// Copy exactly as many samples as required.
+	samplecount = S_MP3_PCMCopy(mp3info->dest, pcm,
+				    mp3info->destlen, 0, needcount, &wrote);
+	mp3info->destlen += wrote;
+	
+	if(samplecount < pcm->length)
+	{
+		// Not all samples got copied. Copy the rest into the pcm buffer.
+		samplecount = S_MP3_PCMCopy(mp3info->pcmbuf, pcm,
+					    mp3info->buflen,
+					    samplecount,
+					    mp3info->pcmbufsize - mp3info->buflen,
+					    &wrote);
+		mp3info->buflen += wrote;
+		
+
+		if(samplecount < pcm->length)
+		{
+			// The pcm buffer was not large enough. Make it bigger.
+			byte *newbuf = Z_Malloc(cursize);
+			
+			if(mp3info->pcmbuf)
+			{
+				memcpy(newbuf, mp3info->pcmbuf, mp3info->buflen);
+				Z_Free(mp3info->pcmbuf);
+			}
+			
+			mp3info->pcmbuf = newbuf;
+			mp3info->pcmbufsize = cursize;
+			
+			samplecount = S_MP3_PCMCopy(mp3info->pcmbuf, pcm,
+						    mp3info->buflen,
+						    samplecount,
+						    mp3info->pcmbufsize - mp3info->buflen,
+						    &wrote);
+			mp3info->buflen += wrote;		
+		}		
+		
+		// we're definitely done.
+		retval = 0;
+	}
+	else if(mp3info->destlen >= mp3info->destsize)
+		retval = 0;
+	else
+		retval = 1;
+
+	return retval;
+}
+
+/*************** Callback functions for quake3 ***************/
+
+/*
+=================
+S_MP3_CodecOpenStream
+=================
+*/
+
+snd_stream_t *S_MP3_CodecOpenStream(const char *filename)
+{
+	snd_stream_t *stream;
+	struct snd_codec_mp3_info *mp3info;
+
+	// Open the stream
+	stream = S_CodecUtilOpen(filename, &mp3_codec);
+	if(!stream || stream->length <= 0)
+		return NULL;
+
+	// We have to scan through the MP3 to determine the important mp3 info.
+	if(S_MP3_Scanfile(stream) < 0)
+	{
+		// scanning didn't work out...
+		S_CodecUtilClose(stream);
+		return NULL;
+	}
+
+	// Initialize the mp3 info structure we need for streaming
+	mp3info = Z_Malloc(sizeof(*mp3info));
+	if(!mp3info)
+	{
+		S_CodecUtilClose(stream);
+		return NULL;
+	}
+
+	stream->ptr = mp3info;
+
+	// initialize the libmad control structures.
+	mad_stream_init(&mp3info->madstream);
+	mad_frame_init(&mp3info->madframe);
+	mad_synth_init(&mp3info->madsynth);
+
+	if(S_MP3_ReadData(stream, &mp3info->madstream, mp3info->encbuf, sizeof(mp3info->encbuf)) <= 0)
+	{
+		// we didnt read anything, that's bad.
+		S_MP3_CodecCloseStream(stream);
+		return NULL;
+	}
+
+	return stream;
+}
+
+/*
+=================
+S_MP3_CodecCloseStream
+=================
+*/
+
+// free all memory we allocated.
+void S_MP3_CodecCloseStream(snd_stream_t *stream)
+{
+	struct snd_codec_mp3_info *mp3info;
+	
+	if(!stream)
+		return;
+		
+	// free all data in our mp3info tree
+
+	if(stream->ptr)
+	{
+		mp3info = stream->ptr;
+
+		if(mp3info->pcmbuf)
+			Z_Free(mp3info->pcmbuf);
+
+		mad_synth_finish(&mp3info->madsynth);
+		mad_frame_finish(&mp3info->madframe);
+		mad_stream_finish(&mp3info->madstream);
+	
+		Z_Free(stream->ptr);
+	}
+
+	S_CodecUtilClose(stream);
+}
+
+/*
+=================
+S_MP3_CodecReadStream
+=================
+*/
+int S_MP3_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer)
+{
+	struct snd_codec_mp3_info *mp3info;
+	int retval;
+	
+	if(!stream)
+		return -1;
+		
+	mp3info = stream->ptr;
+
+	// Make sure we get complete frames all the way through.
+	bytes -= bytes % (stream->info.channels * stream->info.width);
+
+	if(mp3info->buflen)
+	{
+		if(bytes < mp3info->buflen)
+		{
+			// we still have enough bytes in our decoded pcm buffer
+			memcpy(buffer, mp3info->pcmbuf, bytes);
+		
+			// remove the portion from our buffer.
+			mp3info->buflen -= bytes;
+			memmove(mp3info->pcmbuf, &mp3info->pcmbuf[bytes], mp3info->buflen);
+			return bytes;
+		}
+		else
+		{
+			// copy over the samples we already have.
+			memcpy(buffer, mp3info->pcmbuf, mp3info->buflen);
+			mp3info->destlen = mp3info->buflen;
+			mp3info->buflen = 0;
+		}
+	}
+	else
+		mp3info->destlen = 0;
+	
+	mp3info->dest = buffer;
+	mp3info->destsize = bytes;
+
+	do
+	{
+		retval = S_MP3_Decode(stream);
+	} while(retval > 0);
+	
+	// if there was an error return nothing.
+	if(retval < 0)
+		return 0;
+	
+	return mp3info->destlen;
+}
+
+/*
+=====================================================================
+S_MP3_CodecLoad
+
+We handle S_MP3_CodecLoad as a special case of the streaming functions 
+where we read the whole stream at once.
+======================================================================
+*/
+void *S_MP3_CodecLoad(const char *filename, snd_info_t *info)
+{
+	snd_stream_t *stream;
+	byte *pcmbuffer;
+
+	// check if input is valid
+	if(!filename)
+		return NULL;
+
+	stream = S_MP3_CodecOpenStream(filename);
+	
+	if(!stream)
+		return NULL;
+		
+        // copy over the info
+        info->rate = stream->info.rate;
+        info->width = stream->info.width;
+        info->channels = stream->info.channels;
+        info->samples = stream->info.samples;
+        info->dataofs = stream->info.dataofs;
+	
+	// allocate enough buffer for all pcm data
+	pcmbuffer = Z_Malloc(stream->info.size);
+	if(!pcmbuffer)
+	{
+		S_MP3_CodecCloseStream(stream);
+		return NULL;
+	}
+
+	info->size = S_MP3_CodecReadStream(stream, stream->info.size, pcmbuffer);
+
+	if(info->size <= 0)
+	{
+		// we didn't read anything at all. darn.
+		Z_Free(pcmbuffer);
+		pcmbuffer = NULL;
+	}
+
+	S_MP3_CodecCloseStream(stream);
+
+	return pcmbuffer;
+}
+
+#endif // USE_CODEC_MP3
Index: code/client/cl_main.c
===================================================================
--- code/client/cl_main.c	(revision 965)
+++ code/client/cl_main.c	(working copy)
@@ -291,14 +291,24 @@
 	if ( Cmd_Argc() == 2 ) {
 		s = Cmd_Argv(1);
 		Q_strncpyz( demoName, s, sizeof( demoName ) );
-		Com_sprintf (name, sizeof(name), "demos/%s.dm_%d", demoName, PROTOCOL_VERSION );
+#ifdef ELITEFORCE
+		if(clc.compat)
+			Com_sprintf (name, sizeof(name), "demos/%s.efdemo", demoName);
+		else
+#endif
+			Com_sprintf (name, sizeof(name), "demos/%s.dm_%d", demoName, PROTOCOL_VERSION );
 	} else {
 		int		number;
 
 		// scan for a free demo name
 		for ( number = 0 ; number <= 9999 ; number++ ) {
 			CL_DemoFilename( number, demoName );
-			Com_sprintf (name, sizeof(name), "demos/%s.dm_%d", demoName, PROTOCOL_VERSION );
+			#ifdef ELITEFORCE
+			if(clc.compat)
+				Com_sprintf (name, sizeof(name), "demos/%s.efdemo", demoName);
+			else
+			#endif
+				Com_sprintf (name, sizeof(name), "demos/%s.dm_%d", demoName, PROTOCOL_VERSION );
 
 			if (!FS_FileExists(name))
 				break;	// file doesn't exist
@@ -327,11 +337,23 @@
 	clc.demowaiting = qtrue;
 
 	// write out the gamestate message
-	MSG_Init (&buf, bufData, sizeof(bufData));
-	MSG_Bitstream(&buf);
+	#ifdef ELITEFORCE
+	if(clc.compat)
+	{
+		MSG_InitOOB(&buf, bufData, sizeof(bufData));
+		buf.compat = qtrue;
+	}
+	else
+	{
+	#endif
+		MSG_Init (&buf, bufData, sizeof(bufData));
+		MSG_Bitstream(&buf);
 
-	// NOTE, MRE: all server->client messages now acknowledge
-	MSG_WriteLong( &buf, clc.reliableSequence );
+		// NOTE, MRE: all server->client messages now acknowledge
+		MSG_WriteLong( &buf, clc.reliableSequence );
+	#ifdef ELITEFORCE
+	}
+	#endif
 
 	MSG_WriteByte (&buf, svc_gamestate);
 	MSG_WriteLong (&buf, clc.serverCommandSequence );
@@ -358,18 +380,31 @@
 		MSG_WriteDeltaEntity (&buf, &nullstate, ent, qtrue );
 	}
 
-	MSG_WriteByte( &buf, svc_EOF );
+	#ifdef ELITEFORCE
+	if(buf.compat)
+		MSG_WriteByte(&buf, 0);
+	else
+	#endif
+		MSG_WriteByte( &buf, svc_EOF );
 	
 	// finished writing the gamestate stuff
 
-	// write the client num
-	MSG_WriteLong(&buf, clc.clientNum);
-	// write the checksum feed
-	MSG_WriteLong(&buf, clc.checksumFeed);
+	#ifdef ELITEFORCE
+	if(!buf.compat)
+	{
+	#endif
+		// write the client num
+		MSG_WriteLong(&buf, clc.clientNum);
 
-	// finished writing the client packet
-	MSG_WriteByte( &buf, svc_EOF );
+		// write the checksum feed
+		MSG_WriteLong(&buf, clc.checksumFeed);
 
+		// finished writing the client packet
+		MSG_WriteByte( &buf, svc_EOF );
+	#ifdef ELITEFORCE
+	}
+	#endif
+
 	// write it to the demo file
 	len = LittleLong( clc.serverMessageSequence - 1 );
 	FS_Write (&len, 4, clc.demofile);
@@ -434,7 +469,15 @@
 	clc.serverMessageSequence = LittleLong( s );
 
 	// init the message
-	MSG_Init( &buf, bufData, sizeof( bufData ) );
+	#ifdef ELITEFORCE
+	if(clc.compat)
+	{
+		MSG_InitOOB(&buf, bufData, sizeof(bufData));
+		buf.compat = qtrue;
+	}
+	else
+	#endif
+		MSG_Init( &buf, bufData, sizeof( bufData ) );
 
 	// get the length
 	r = FS_Read (&buf.cursize, 4, clc.demofile);
@@ -467,10 +510,26 @@
 CL_WalkDemoExt
 ====================
 */
+#ifdef ELITEFORCE
+static void CL_WalkDemoExt(char *arg, char *name, int *demofile, qboolean *compat)
+#else
 static void CL_WalkDemoExt(char *arg, char *name, int *demofile)
+#endif
 {
 	int i = 0;
 	*demofile = 0;
+	
+	#ifdef ELITEFORCE
+	Com_sprintf(name, MAX_OSPATH, "demos/%s.efdemo", arg);
+	FS_FOpenFileRead(name, demofile, qtrue);
+	if(*demofile)
+	{
+		Com_Printf("Demo file: %s\n", name);
+		*compat = qtrue;
+		return;
+	}
+	#endif
+	
 	while(demo_protocols[i])
 	{
 		Com_sprintf (name, MAX_OSPATH, "demos/%s.dm_%d", arg, demo_protocols[i]);
@@ -499,6 +558,9 @@
 	char		*arg, *ext_test;
 	int			protocol, i;
 	char		retry[MAX_OSPATH];
+	#ifdef ELITEFORCE
+	qboolean compat = qfalse;	// For demos using the old EF protocol.
+	#endif
 
 	if (Cmd_Argc() != 2) {
 		Com_Printf ("playdemo <demoname>\n");
@@ -513,31 +575,52 @@
 	// open the demo file
 	arg = Cmd_Argv(1);
 	
-	// check for an extension .dm_?? (?? is protocol)
-	ext_test = arg + strlen(arg) - 6;
-	if ((strlen(arg) > 6) && (ext_test[0] == '.') && ((ext_test[1] == 'd') || (ext_test[1] == 'D')) && ((ext_test[2] == 'm') || (ext_test[2] == 'M')) && (ext_test[3] == '_'))
+#ifdef ELITEFORCE
+	ext_test = arg + strlen(arg) - 7;
+	if(!strcmp(ext_test, ".efdemo"))
 	{
-		protocol = atoi(ext_test+4);
-		i=0;
-		while(demo_protocols[i])
+		Com_sprintf (name, sizeof(name), "demos/%s", arg);
+		FS_FOpenFileRead(name, &clc.demofile, qtrue);
+		compat = qtrue;
+	}
+	else
+	{
+#endif
+		// check for an extension .dm_?? (?? is protocol)
+		ext_test = arg + strlen(arg) - 6;
+		if ((strlen(arg) > 6) && (ext_test[0] == '.') && ((ext_test[1] == 'd') || (ext_test[1] == 'D')) && ((ext_test[2] == 'm') || (ext_test[2] == 'M')) && (ext_test[3] == '_'))
 		{
-			if (demo_protocols[i] == protocol)
-				break;
-			i++;
-		}
-		if (demo_protocols[i])
-		{
-			Com_sprintf (name, sizeof(name), "demos/%s", arg);
-			FS_FOpenFileRead( name, &clc.demofile, qtrue );
+			protocol = atoi(ext_test+4);
+			i=0;
+			while(demo_protocols[i])
+			{
+				if (demo_protocols[i] == protocol)
+					break;
+				i++;
+			}
+			if (demo_protocols[i])
+			{
+				Com_sprintf (name, sizeof(name), "demos/%s", arg);
+				FS_FOpenFileRead( name, &clc.demofile, qtrue );
+			} else {
+				Com_Printf("Protocol %d not supported for demos\n", protocol);
+				Q_strncpyz(retry, arg, sizeof(retry));
+				retry[strlen(retry)-6] = 0;
+				#ifdef ELITEFORCE
+				CL_WalkDemoExt(retry, name, &clc.demofile, &compat);
+				#else
+				CL_WalkDemoExt( retry, name, &clc.demofile );
+				#endif
+			}
 		} else {
-			Com_Printf("Protocol %d not supported for demos\n", protocol);
-			Q_strncpyz(retry, arg, sizeof(retry));
-			retry[strlen(retry)-6] = 0;
-			CL_WalkDemoExt( retry, name, &clc.demofile );
+#ifdef ELITEFORCE
+			CL_WalkDemoExt(arg, name, &clc.demofile, &compat);
 		}
-	} else {
-		CL_WalkDemoExt( arg, name, &clc.demofile );
 	}
+#else
+			CL_WalkDemoExt( arg, name, &clc.demofile );
+		}
+#endif
 	
 	if (!clc.demofile) {
 		Com_Error( ERR_DROP, "couldn't open %s", name);
@@ -549,6 +632,11 @@
 
 	cls.state = CA_CONNECTED;
 	clc.demoplaying = qtrue;
+
+	#ifdef ELITEFORCE
+	clc.compat = compat;
+	#endif
+
 	Q_strncpyz( cls.servername, Cmd_Argv(1), sizeof( cls.servername ) );
 
 	// read demo messages until connected
@@ -1168,7 +1256,10 @@
 	// "cp"
 	// "Yf"
 	Com_sprintf(cMsg, sizeof(cMsg), "Yf ");
-	Q_strcat(cMsg, sizeof(cMsg), va("%d ", cl.serverId) );
+#ifdef ELITEFORCE
+	if(!clc.compat)
+#endif	
+		Q_strcat(cMsg, sizeof(cMsg), va("%d ", cl.serverId) );
 	Q_strcat(cMsg, sizeof(cMsg), pChecksums);
 	for (i = 0; i < 2; i++) {
 		cMsg[i] += 10;
@@ -1542,20 +1633,20 @@
                   "Go to the setting menu to turn on autodownload, or get the file elsewhere\n\n", missingfiles );
     }
   }
-  else if ( FS_ComparePaks( clc.downloadList, sizeof( clc.downloadList ) , qtrue ) ) {
+  else if ( FS_ComparePaks( clc.downloadList, sizeof( clc.downloadList ) , qtrue ) )
+  {
+  	Com_Printf("Need paks: %s\n", clc.downloadList );
 
-    Com_Printf("Need paks: %s\n", clc.downloadList );
+	if ( *clc.downloadList )
+	{
+		// if autodownloading is not enabled on the server
+		cls.state = CA_CONNECTED;
+		CL_NextDownload();
+		return;
+	}
+  }
 
-		if ( *clc.downloadList ) {
-			// if autodownloading is not enabled on the server
-			cls.state = CA_CONNECTED;
-			CL_NextDownload();
-			return;
-		}
-
-	}
-		
-	CL_DownloadsComplete();
+  CL_DownloadsComplete();
 }
 
 /*
@@ -1602,7 +1693,12 @@
 		port = Cvar_VariableValue ("net_qport");
 
 		Q_strncpyz( info, Cvar_InfoString( CVAR_USERINFO ), sizeof( info ) );
-		Info_SetValueForKey( info, "protocol", va("%i", PROTOCOL_VERSION ) );
+		#ifdef ELITEFORCE
+		if(clc.compat)
+			Info_SetValueForKey( info, "protocol", va("%i", EFPROTOCOL_VERSION ) );
+		else
+		#endif
+			Info_SetValueForKey( info, "protocol", va("%i", PROTOCOL_VERSION ) );
 		Info_SetValueForKey( info, "qport", va("%i", port ) );
 		Info_SetValueForKey( info, "challenge", va("%i", clc.challenge ) );
 		
@@ -1618,7 +1714,11 @@
 		data[10+i] = 0;
 
     // NOTE TTimo don't forget to set the right data length!
-		NET_OutOfBandData( NS_CLIENT, clc.serverAddress, (byte *) &data[0], i+10 );
+    		#ifdef ELITEFORCE
+			NET_OutOfBandPrint( NS_CLIENT, clc.serverAddress, (byte *) &data[0]);
+		#else
+			NET_OutOfBandData( NS_CLIENT, clc.serverAddress, (byte *) &data[0], i+10 );
+		#endif
 		// the most current userinfo has been sent, so watch for any
 		// newer changes to userinfo variables
 		cvar_modifiedFlags &= ~CVAR_USERINFO;
@@ -1728,6 +1828,9 @@
 	int				numservers;
 	byte*			buffptr;
 	byte*			buffend;
+	#ifdef ELITEFORCE
+	char strbyte[3] = "FF";
+	#endif
 	
 	Com_Printf("CL_ServersResponsePacket\n");
 
@@ -1757,6 +1860,21 @@
 			break;
 		}
 
+#ifdef ELITEFORCE
+		// EliteForce uses a slightly different format with bytes encoded
+		// in hex values.
+		for(i = 0; i < 6; i++)
+		{
+			strbyte[0] = toupper(*buffptr++);
+			strbyte[1] = toupper(*buffptr++);
+
+			if(i < 4)
+				addresses[numservers].ip[i] = strtoul(strbyte, NULL, 16);
+			else
+				((unsigned char *) &addresses[numservers].port)[i - 4] =
+					strtoul(strbyte, NULL, 16);
+		}
+#else
 		// parse out ip
 		addresses[numservers].ip[0] = *buffptr++;
 		addresses[numservers].ip[1] = *buffptr++;
@@ -1767,7 +1885,7 @@
 		addresses[numservers].port = (*buffptr++)<<8;
 		addresses[numservers].port += *buffptr++;
 		addresses[numservers].port = BigShort( addresses[numservers].port );
-
+#endif
 		// syntax check
 		if (*buffptr != '\\') {
 			break;
@@ -1791,6 +1909,10 @@
 		}
 	}
 
+	#ifdef ELITEFORCE
+	count = cls.numglobalservers;
+	max = MAX_GLOBAL_SERVERS;
+	#else
 	if (cls.masterNum == 0) {
 		count = cls.numglobalservers;
 		max = MAX_GLOBAL_SERVERS;
@@ -1798,10 +1920,15 @@
 		count = cls.nummplayerservers;
 		max = MAX_OTHER_SERVERS;
 	}
+	#endif
 
 	for (i = 0; i < numservers && count < max; i++) {
 		// build net address
+		#ifdef ELITEFORCE
+		serverInfo_t *server = &cls.globalServers[count];
+		#else
 		serverInfo_t *server = (cls.masterNum == 0) ? &cls.globalServers[count] : &cls.mplayerServers[count];
+		#endif
 
 		CL_InitServerInfo( server, &addresses[i] );
 		// advance to next slot
@@ -1809,7 +1936,9 @@
 	}
 
 	// if getting the global list
+#ifndef ELITEFORCE
 	if (cls.masterNum == 0) {
+#endif
 		if ( cls.numGlobalServerAddresses < MAX_GLOBAL_SERVERS ) {
 			// if we couldn't store the servers in the main list anymore
 			for (; i < numservers && count >= max; i++) {
@@ -1823,15 +1952,21 @@
 				addr->port  = addresses[i].port;
 			}
 		}
+#ifndef ELITEFORCE
 	}
+#endif
 
+#ifndef ELITEFORCE
 	if (cls.masterNum == 0) {
+#endif
 		cls.numglobalservers = count;
 		total = count + cls.numGlobalServerAddresses;
+#ifndef ELITEFORCE
 	} else {
 		cls.nummplayerservers = count;
 		total = count;
 	}
+#endif
 
 	Com_Printf("%d servers parsed (total %d)\n", numservers, total);
 }
@@ -1894,6 +2029,9 @@
 			return;
 		}
 		Netchan_Setup (NS_CLIENT, &clc.netchan, from, Cvar_VariableValue( "net_qport" ) );
+		#ifdef ELITEFORCE
+		clc.netchan.compat = clc.compat;
+		#endif
 		cls.state = CA_CONNECTED;
 		clc.lastPacketSentTime = -9999;		// send first packet immediately
 		return;
@@ -1939,8 +2077,20 @@
 	// echo request from server
 	if ( !Q_stricmp(c, "print") ) {
 		s = MSG_ReadString( msg );
-		Q_strncpyz( clc.serverMessage, s, sizeof( clc.serverMessage ) );
-		Com_Printf( "%s", s );
+		#ifdef ELITEFORCE
+		if(!Q_strncmp(s, "Server uses protocol version 24.\n", 33))
+		{
+			clc.compat = qtrue;
+			cls.state = CA_CONNECTING;
+		}
+		else
+		{
+		#endif
+			Q_strncpyz( clc.serverMessage, s, sizeof( clc.serverMessage ) );
+			Com_Printf( "%s", s );
+		#ifdef ELITEFORCE
+		}
+		#endif
 		return;
 	}
 
@@ -1965,7 +2115,10 @@
 	int		headerBytes;
 
 	clc.lastPacketTime = cls.realtime;
-
+	#ifdef ELITEFORCE
+	msg->compat = clc.compat;
+	#endif
+	
 	if ( msg->cursize >= 4 && *(int *)msg->data == -1 ) {
 		CL_ConnectionlessPacket( from, msg );
 		return;
@@ -2267,7 +2420,11 @@
 	re.BeginRegistration( &cls.glconfig );
 
 	// load character sets
+#ifdef ELITEFORCE
+	cls.charSetShader = re.RegisterShaderNoMip( "gfx/2d/charsgrid_med" );
+#else
 	cls.charSetShader = re.RegisterShader( "gfx/2d/bigchars" );
+#endif
 	cls.whiteShader = re.RegisterShader( "white" );
 	cls.consoleShader = re.RegisterShader( "console" );
 	g_console_field_width = cls.glconfig.vidWidth / SMALLCHAR_WIDTH - 2;
@@ -2548,7 +2705,11 @@
 	cl_pitchspeed = Cvar_Get ("cl_pitchspeed", "140", CVAR_ARCHIVE);
 	cl_anglespeedkey = Cvar_Get ("cl_anglespeedkey", "1.5", 0);
 
+#ifdef ELITEFORCE
+	cl_maxpackets = Cvar_Get ("cl_maxpackets", "43", CVAR_ARCHIVE );
+#else
 	cl_maxpackets = Cvar_Get ("cl_maxpackets", "30", CVAR_ARCHIVE );
+#endif
 	cl_packetdup = Cvar_Get ("cl_packetdup", "1", CVAR_ARCHIVE );
 
 	cl_run = Cvar_Get ("cl_run", "1", CVAR_ARCHIVE);
@@ -2599,12 +2760,14 @@
 	Cvar_Get ("name", "UnnamedPlayer", CVAR_USERINFO | CVAR_ARCHIVE );
 	Cvar_Get ("rate", "3000", CVAR_USERINFO | CVAR_ARCHIVE );
 	Cvar_Get ("snaps", "20", CVAR_USERINFO | CVAR_ARCHIVE );
-	Cvar_Get ("model", "sarge", CVAR_USERINFO | CVAR_ARCHIVE );
-	Cvar_Get ("headmodel", "sarge", CVAR_USERINFO | CVAR_ARCHIVE );
+	Cvar_Get ("model", "munro/red", CVAR_USERINFO | CVAR_ARCHIVE );
+	#ifndef ELITEFORCE
+	Cvar_Get ("headmodel", "munro", CVAR_USERINFO | CVAR_ARCHIVE );
 	Cvar_Get ("team_model", "james", CVAR_USERINFO | CVAR_ARCHIVE );
 	Cvar_Get ("team_headmodel", "*james", CVAR_USERINFO | CVAR_ARCHIVE );
 	Cvar_Get ("g_redTeam", "Stroggs", CVAR_SERVERINFO | CVAR_ARCHIVE);
 	Cvar_Get ("g_blueTeam", "Pagans", CVAR_SERVERINFO | CVAR_ARCHIVE);
+	#endif
 	Cvar_Get ("color1",  "4", CVAR_USERINFO | CVAR_ARCHIVE );
 	Cvar_Get ("color2", "5", CVAR_USERINFO | CVAR_ARCHIVE );
 	Cvar_Get ("handicap", "100", CVAR_USERINFO | CVAR_ARCHIVE );
@@ -2615,7 +2778,6 @@
 	Cvar_Get ("password", "", CVAR_USERINFO);
 	Cvar_Get ("cg_predictItems", "1", CVAR_USERINFO | CVAR_ARCHIVE );
 
-
 	// cgame might not be initialized before menu is used
 	Cvar_Get ("cg_viewsize", "100", CVAR_ARCHIVE );
 
@@ -2780,11 +2942,28 @@
 	char	*infoString;
 	int		prot;
 
+#ifdef ELITEFORCE
+	// eliteforce doesn't send a \n after infoResponse..
+	infoString = strchr(msg->data, '"');
+	if(!infoString)
+		return;
+	msg->readcount = (int) ((byte *) ++infoString - msg->data);
+	msg->bit = msg->readcount << 3;
+	// find the second " character and empty it.
+	infoString = strchr(infoString, '"');
+	if(infoString)
+		*infoString = '\0';
+#endif
+
 	infoString = MSG_ReadString( msg );
 
 	// if this isn't the correct protocol version, ignore it
 	prot = atoi( Info_ValueForKey( infoString, "protocol" ) );
+#ifdef ELITEFORCE
+	if ( prot != PROTOCOL_VERSION && prot != EFPROTOCOL_VERSION ) {
+#else
 	if ( prot != PROTOCOL_VERSION ) {
+#endif
 		Com_DPrintf( "Different protocol info packet: %s\n", infoString );
 		return;
 	}
@@ -2822,7 +3001,11 @@
 					type = 0;
 					break;
 			}
+#ifdef ELITEFORCE
+			Info_SetValueForKey( cl_pinglist[i].info, "nettype", str );
+#else
 			Info_SetValueForKey( cl_pinglist[i].info, "nettype", va("%d", type) );
+#endif
 			CL_SetServerInfoByAddress(from, infoString, cl_pinglist[i].time);
 
 			return;
@@ -3122,9 +3305,16 @@
 	int			count;
 	char		*buffptr;
 	char		command[1024];
+	#ifdef ELITEFORCE
+	char *msname;
+	#endif
 	
 	if ( Cmd_Argc() < 3) {
+		#ifdef ELITEFORCE
+		Com_Printf( "usage: globalservers <master# 0-4> <protocol> [keywords]\n");
+		#else
 		Com_Printf( "usage: globalservers <master# 0-1> <protocol> [keywords]\n");
+		#endif
 		return;	
 	}
 
@@ -3135,19 +3325,48 @@
 	// reset the list, waiting for response
 	// -1 is used to distinguish a "no response"
 
+
+	#ifdef ELITEFORCE
+
+	switch(cls.masterNum)
+	{
+		case 0: msname = Cvar_VariableString("sv_master1");
+		break;
+		case 1: msname = Cvar_VariableString("sv_master2");
+		break;
+		case 2: msname = Cvar_VariableString("sv_master3");
+		break;
+		case 3: msname = Cvar_VariableString("sv_master4");
+		break;
+		case 4: msname = Cvar_VariableString("sv_master5");
+		break;
+		default: msname = MASTER_SERVER_NAME;
+		break;
+	}
+	
+	NET_StringToAdr(msname, &to);
+		
+	if(!strchr(msname, ':'))
+		to.port = BigShort(PORT_MASTER);
+		
+	#else
+	NET_StringToAdr( MASTER_SERVER_NAME, &to );
+
 	if( cls.masterNum == 1 ) {
-		NET_StringToAdr( MASTER_SERVER_NAME, &to );
 		cls.nummplayerservers = -1;
 		cls.pingUpdateSource = AS_MPLAYER;
 	}
 	else {
-		NET_StringToAdr( MASTER_SERVER_NAME, &to );
+	#endif
 		cls.numglobalservers = -1;
 		cls.pingUpdateSource = AS_GLOBAL;
+	#ifndef ELITEFORCE
 	}
+	to.port = BigShort(PORT_MASTER);
+	#endif
 	to.type = NA_IP;
-	to.port = BigShort(PORT_MASTER);
 
+
 	sprintf( command, "getservers %s", Cmd_Argv(2) );
 
 	// tack on keywords
Index: code/client/snd_dma.c
===================================================================
--- code/client/snd_dma.c	(revision 965)
+++ code/client/snd_dma.c	(working copy)
@@ -338,10 +338,20 @@
 	sfx->inMemory = qfalse;
 	sfx->soundCompressed = compressed;
 
-  S_memoryLoad(sfx);
+	S_memoryLoad(sfx);
 
 	if ( sfx->defaultSound ) {
+		#ifdef ELITEFORCE
+		int hash = S_HashSFXName(name);
+		// free the slot up.
+		sfx->soundName[0] = '\0';
+		sfx->inMemory = qfalse;
+		sfx->defaultSound = qfalse;
+		// the new entry is head anyways.
+		sfxHash[hash] = sfx->next;
+		#else
 		Com_Printf( S_COLOR_YELLOW "WARNING: could not find %s - using default\n", sfx->soundName );
+		#endif
 		return 0;
 	}
 
@@ -364,7 +374,11 @@
 		Com_Memset( s_knownSfx, 0, sizeof( s_knownSfx ) );
 		Com_Memset(sfxHash, 0, sizeof(sfx_t *)*LOOP_HASH);
 
+#ifdef ELITEFORCE
+		S_Base_RegisterSound("sound/null.wav", qfalse); // Eliteforce specific sound.
+#else
 		S_Base_RegisterSound("sound/feedback/hit.wav", qfalse);		// changed to a sound in baseq3
+#endif
 	}
 }
 
@@ -1303,9 +1317,11 @@
 		return;
 	}
 
+	#ifndef ELITEFORCE
 	if(s_backgroundStream->info.channels != 2 || s_backgroundStream->info.rate != 22050) {
 		Com_Printf(S_COLOR_YELLOW "WARNING: music file %s is not 22k stereo\n", intro );
 	}
+	#endif
 }
 
 /*
Index: code/client/cl_console.c
===================================================================
--- code/client/cl_console.c	(revision 965)
+++ code/client/cl_console.c	(working copy)
@@ -64,7 +64,6 @@
 
 vec4_t	console_color = {1.0, 1.0, 1.0, 1.0};
 
-
 /*
 ================
 Con_ToggleConsole_f
@@ -552,8 +551,23 @@
 	// draw the chat line
 	if ( cls.keyCatchers & KEYCATCH_MESSAGE )
 	{
+#ifdef ELITEFORCE
 		if (chat_team)
 		{
+			SCR_DrawSmallString (8, v, "say_team:", 1.0f );
+			skip = 11;
+		}
+		else
+		{
+			SCR_DrawSmallString (8, v, "say:", 1.0f );
+			skip = 6;
+		}
+
+		Field_Draw(&chatField, skip * SMALLCHAR_WIDTH, v,
+			SCREEN_WIDTH - ( skip + 1 ) * SMALLCHAR_WIDTH, qtrue);
+#else
+		if (chat_team)
+		{
 			SCR_DrawBigString (8, v, "say_team:", 1.0f );
 			skip = 10;
 		}
@@ -565,6 +579,7 @@
 
 		Field_BigDraw( &chatField, skip * BIGCHAR_WIDTH, v,
 			SCREEN_WIDTH - ( skip + 1 ) * BIGCHAR_WIDTH, qtrue );
+#endif
 
 		v += BIGCHAR_HEIGHT;
 	}
Index: code/client/snd_openal.c
===================================================================
--- code/client/snd_openal.c	(revision 965)
+++ code/client/snd_openal.c	(working copy)
@@ -286,7 +286,12 @@
 	data = S_CodecLoad(knownSfx[sfx].filename, &info);
 	if(!data)
 	{
+#ifdef ELITEFORCE
+		S_AL_BufferUnload(sfx);
+		*knownSfx[sfx].filename = '\0';
+#else
 		S_AL_BufferUseDefault(sfx);
+#endif
 		return;
 	}
 
@@ -381,7 +386,11 @@
 	numSfx = 0;
 
 	// Load the default sound, and lock it
+#ifdef ELITEFORCE
+	default_sfx = S_AL_BufferFind("sound/null.wav");
+#else
 	default_sfx = S_AL_BufferFind("sound/feedback/hit.wav");
+#endif
 	S_AL_BufferUse(default_sfx);
 	knownSfx[default_sfx].isLocked = qtrue;
 
@@ -429,6 +438,12 @@
 
 	if( s_alPrecache->integer && (!knownSfx[sfx].inMemory) && (!knownSfx[sfx].isDefault))
 		S_AL_BufferLoad(sfx);
+
+#ifdef ELITEFORCE
+	if(! *knownSfx[sfx].filename)
+        	return 0;
+#endif
+                        
 	knownSfx[sfx].lastUsedTime = Com_Milliseconds();
 
 	return sfx;
Index: code/client/cl_keys.c
===================================================================
--- code/client/cl_keys.c	(revision 965)
+++ code/client/cl_keys.c	(working copy)
@@ -1094,13 +1094,14 @@
 			return;
 		}
 
+#ifndef ELITEFORCE
 		// escape always gets out of CGAME stuff
 		if (cls.keyCatchers & KEYCATCH_CGAME) {
 			cls.keyCatchers &= ~KEYCATCH_CGAME;
 			VM_Call (cgvm, CG_EVENT_HANDLING, CGAME_EVENT_NONE);
 			return;
 		}
-
+#endif
 		if ( !( cls.keyCatchers & KEYCATCH_UI ) ) {
 			if ( cls.state == CA_ACTIVE && !clc.demoplaying ) {
 				VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_INGAME );
@@ -1112,8 +1113,11 @@
 			}
 			return;
 		}
-
+#ifdef ELITEFORCE
+		VM_Call( uivm, UI_KEY_EVENT, key );
+#else
 		VM_Call( uivm, UI_KEY_EVENT, key, down );
+#endif
 		return;
 	}
 
@@ -1128,12 +1132,13 @@
 
 		CL_AddKeyUpCommands( key, kb );
 
+#ifndef ELITEFORCE
 		if ( cls.keyCatchers & KEYCATCH_UI && uivm ) {
 			VM_Call( uivm, UI_KEY_EVENT, key, down );
 		} else if ( cls.keyCatchers & KEYCATCH_CGAME && cgvm ) {
 			VM_Call( cgvm, CG_KEY_EVENT, key, down );
 		} 
-
+#endif
 		return;
 	}
 
@@ -1145,10 +1150,12 @@
 		if ( uivm ) {
 			VM_Call( uivm, UI_KEY_EVENT, key, down );
 		} 
+#ifndef ELITEFORCE
 	} else if ( cls.keyCatchers & KEYCATCH_CGAME ) {
 		if ( cgvm ) {
 			VM_Call( cgvm, CG_KEY_EVENT, key, down );
 		} 
+#endif
 	} else if ( cls.keyCatchers & KEYCATCH_MESSAGE ) {
 		Message_Key( key );
 	} else if ( cls.state == CA_DISCONNECTED ) {
Index: code/client/cl_cgame.c
===================================================================
--- code/client/cl_cgame.c	(revision 965)
+++ code/client/cl_cgame.c	(working copy)
@@ -296,7 +296,10 @@
 		// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=552
 		// allow server to indicate why they were disconnected
 		if ( argc >= 2 )
+		{
+			Cbuf_AddText(va("err_dialog \"%s\"", Cmd_Argv(1)));
 			Com_Error (ERR_SERVERDISCONNECT, va( "Server Disconnected - %s", Cmd_Argv( 1 ) ) );
+		}
 		else
 			Com_Error (ERR_SERVERDISCONNECT,"Server disconnected\n");
 	}
@@ -453,17 +456,21 @@
 	case CG_FS_FCLOSEFILE:
 		FS_FCloseFile( args[1] );
 		return 0;
+#ifndef ELITEFORCE
 	case CG_FS_SEEK:
 		return FS_Seek( args[1], args[2], args[3] );
+#endif
 	case CG_SENDCONSOLECOMMAND:
 		Cbuf_AddText( VMA(1) );
 		return 0;
 	case CG_ADDCOMMAND:
 		CL_AddCgameCommand( VMA(1) );
 		return 0;
+#ifndef ELITEFORCE
 	case CG_REMOVECOMMAND:
 		Cmd_RemoveCommand( VMA(1) );
 		return 0;
+#endif
 	case CG_SENDCLIENTCOMMAND:
 		CL_AddReliableCommand( VMA(1) );
 		return 0;
@@ -484,8 +491,10 @@
 		return CM_InlineModel( args[1] );
 	case CG_CM_TEMPBOXMODEL:
 		return CM_TempBoxModel( VMA(1), VMA(2), /*int capsule*/ qfalse );
+#ifndef ELITEFORCE
 	case CG_CM_TEMPCAPSULEMODEL:
 		return CM_TempBoxModel( VMA(1), VMA(2), /*int capsule*/ qtrue );
+#endif
 	case CG_CM_POINTCONTENTS:
 		return CM_PointContents( VMA(1), args[2] );
 	case CG_CM_TRANSFORMEDPOINTCONTENTS:
@@ -493,15 +502,19 @@
 	case CG_CM_BOXTRACE:
 		CM_BoxTrace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], /*int capsule*/ qfalse );
 		return 0;
+#ifndef ELITEFORCE
 	case CG_CM_CAPSULETRACE:
 		CM_BoxTrace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], /*int capsule*/ qtrue );
 		return 0;
+#endif
 	case CG_CM_TRANSFORMEDBOXTRACE:
 		CM_TransformedBoxTrace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], VMA(8), VMA(9), /*int capsule*/ qfalse );
 		return 0;
+#ifndef ELITEFORCE
 	case CG_CM_TRANSFORMEDCAPSULETRACE:
 		CM_TransformedBoxTrace( VMA(1), VMA(2), VMA(3), VMA(4), VMA(5), args[6], args[7], VMA(8), VMA(9), /*int capsule*/ qtrue );
 		return 0;
+#endif
 	case CG_CM_MARKFRAGMENTS:
 		return re.MarkFragments( args[1], VMA(2), VMA(3), args[4], VMA(5), args[6], VMA(7) );
 	case CG_S_STARTSOUND:
@@ -516,12 +529,14 @@
 	case CG_S_ADDLOOPINGSOUND:
 		S_AddLoopingSound( args[1], VMA(2), VMA(3), args[4] );
 		return 0;
+#ifndef ELITEFORCE
 	case CG_S_ADDREALLOOPINGSOUND:
 		S_AddRealLoopingSound( args[1], VMA(2), VMA(3), args[4] );
 		return 0;
 	case CG_S_STOPLOOPINGSOUND:
 		S_StopLoopingSound( args[1] );
 		return 0;
+#endif
 	case CG_S_UPDATEENTITYPOSITION:
 		S_UpdateEntityPosition( args[1], VMA(2) );
 		return 0;
@@ -531,7 +546,12 @@
 	case CG_S_REGISTERSOUND:
 		return S_RegisterSound( VMA(1), args[2] );
 	case CG_S_STARTBACKGROUNDTRACK:
-		S_StartBackgroundTrack( VMA(1), VMA(2) );
+#ifdef ELITEFORCE
+		if(!VMA(1) || !*((char *) VMA(1)))
+			S_StopBackgroundTrack();
+		else
+#endif
+			S_StartBackgroundTrack(VMA(1), VMA(2));
 		return 0;
 	case CG_R_LOADWORLDMAP:
 		re.LoadWorld( VMA(1) );
@@ -544,8 +564,10 @@
 		return re.RegisterShader( VMA(1) );
 	case CG_R_REGISTERSHADERNOMIP:
 		return re.RegisterShaderNoMip( VMA(1) );
+#ifndef ELITEFORCE
 	case CG_R_REGISTERFONT:
 		re.RegisterFont( VMA(1), args[2], VMA(3));
+#endif
 	case CG_R_CLEARSCENE:
 		re.ClearScene();
 		return 0;
@@ -555,17 +577,21 @@
 	case CG_R_ADDPOLYTOSCENE:
 		re.AddPolyToScene( args[1], args[2], VMA(3), 1 );
 		return 0;
+#ifndef ELITEFORCE
 	case CG_R_ADDPOLYSTOSCENE:
 		re.AddPolyToScene( args[1], args[2], VMA(3), args[4] );
 		return 0;
 	case CG_R_LIGHTFORPOINT:
 		return re.LightForPoint( VMA(1), VMA(2), VMA(3), VMA(4) );
+#endif
 	case CG_R_ADDLIGHTTOSCENE:
 		re.AddLightToScene( VMA(1), VMF(2), VMF(3), VMF(4), VMF(5) );
 		return 0;
+#ifndef ELITEFORCE
 	case CG_R_ADDADDITIVELIGHTTOSCENE:
 		re.AddAdditiveLightToScene( VMA(1), VMF(2), VMF(3), VMF(4), VMF(5) );
 		return 0;
+#endif
 	case CG_R_RENDERSCENE:
 		re.RenderScene( VMA(1) );
 		return 0;
@@ -602,6 +628,7 @@
 		return 0;
 	case CG_MEMORY_REMAINING:
 		return Hunk_MemoryRemaining();
+#ifndef ELITEFORCE
   case CG_KEY_ISDOWN:
 		return Key_IsDown( args[1] );
   case CG_KEY_GETCATCHER:
@@ -611,9 +638,9 @@
     return 0;
   case CG_KEY_GETKEY:
 		return Key_GetKey( VMA(1) );
+#endif
 
 
-
 	case CG_MEMSET:
 		Com_Memset( VMA(1), args[2], args[3] );
 		return 0;
@@ -635,9 +662,9 @@
 		return FloatAsInt( floor( VMF(1) ) );
 	case CG_CEIL:
 		return FloatAsInt( ceil( VMF(1) ) );
+#ifndef ELITEFORCE
 	case CG_ACOS:
 		return FloatAsInt( Q_acos( VMF(1) ) );
-
 	case CG_PC_ADD_GLOBAL_DEFINE:
 		return botlib_export->PC_AddGlobalDefine( VMA(1) );
 	case CG_PC_LOAD_SOURCE:
@@ -695,7 +722,12 @@
 		return re.GetEntityToken( VMA(1), args[2] );
 	case CG_R_INPVS:
 		return re.inPVS( VMA(1), VMA(2) );
-
+#else
+	case CG_R_REGISTERSHADER3D:
+		return re.RegisterShader3D( VMA(1) );
+	case CG_CVAR_SET_NO_MODIFY:
+		return qfalse;
+#endif
 	default:
 	        assert(0); // bk010102
 		Com_Error( ERR_DROP, "Bad cgame system trap: %i", args[0] );
Index: code/client/cl_ui.c
===================================================================
--- code/client/cl_ui.c	(revision 965)
+++ code/client/cl_ui.c	(working copy)
@@ -88,7 +88,7 @@
 	FS_FCloseFile(fileOut);
 }
 
-
+#ifndef ELITEFORCE
 /*
 ====================
 LAN_ResetPings
@@ -217,8 +217,8 @@
 		}
 	}
 }
+#endif
 
-
 /*
 ====================
 LAN_GetServerCount
@@ -241,7 +241,6 @@
 	}
 	return 0;
 }
-
 /*
 ====================
 LAN_GetLocalServerAddressString
@@ -277,6 +276,7 @@
 	buf[0] = '\0';
 }
 
+#ifndef ELITEFORCE
 /*
 ====================
 LAN_GetServerInfo
@@ -395,7 +395,6 @@
 	}
 	return NULL;
 }
-
 /*
 ====================
 LAN_CompareServers
@@ -465,6 +464,8 @@
 	return res;
 }
 
+#endif
+
 /*
 ====================
 LAN_GetPingQueueCount
@@ -501,6 +502,7 @@
 	CL_GetPingInfo( n, buf, buflen );
 }
 
+#ifndef ELITEFORCE
 /*
 ====================
 LAN_MarkServerVisible
@@ -589,6 +591,8 @@
 	return qfalse;
 }
 
+#endif
+
 /*
 =======================
 LAN_UpdateVisiblePings
@@ -680,7 +684,7 @@
 	cls.keyCatchers = catcher;
 }
 
-
+#ifndef ELITEFORCE
 /*
 ====================
 CLUI_GetCDKey
@@ -697,8 +701,8 @@
 		buf[16] = 0;
 	}
 }
+#endif
 
-
 /*
 ====================
 CLUI_SetCDKey
@@ -713,7 +717,12 @@
 		// set the flag so the fle will be written at the next opportunity
 		cvar_modifiedFlags |= CVAR_ARCHIVE;
 	} else {
+		#ifdef ELITEFORCE
+		Com_Memcpy(cl_cdkey, buf, 22);
+		cl_cdkey[22] = '\0';
+		#else
 		Com_Memcpy( cl_cdkey, buf, 16 );
+		#endif
 		// set the flag so the fle will be written at the next opportunity
 		cvar_modifiedFlags |= CVAR_ARCHIVE;
 	}
@@ -841,8 +850,10 @@
 	case UI_FS_GETFILELIST:
 		return FS_GetFileList( VMA(1), VMA(2), VMA(3), args[4] );
 
+#ifndef ELITEFORCE
 	case UI_FS_SEEK:
 		return FS_Seek( args[1], args[2], args[3] );
+#endif
 	
 	case UI_R_REGISTERMODEL:
 		return re.RegisterModel( VMA(1) );
@@ -948,6 +959,7 @@
 	case UI_GETCONFIGSTRING:
 		return GetConfigString( args[1], VMA(2), args[3] );
 
+#ifndef ELITEFORCE
 	case UI_LAN_LOADCACHEDSERVERS:
 		LAN_LoadCachedServers();
 		return 0;
@@ -962,6 +974,7 @@
 	case UI_LAN_REMOVESERVER:
 		LAN_RemoveServer(args[1], VMA(2));
 		return 0;
+#endif
 
 	case UI_LAN_GETPINGQUEUECOUNT:
 		return LAN_GetPingQueueCount();
@@ -978,13 +991,26 @@
 		LAN_GetPingInfo( args[1], VMA(2), args[3] );
 		return 0;
 
+#ifdef ELITEFORCE
+	case UI_LAN_GETLOCALSERVERCOUNT:
+		return LAN_GetServerCount(AS_LOCAL);
+
+	case UI_LAN_GETLOCALSERVERADDRESSSTRING:
+		LAN_GetServerAddressString( AS_LOCAL, args[1], VMA(2), args[3] );
+		return 0;
+	case UI_LAN_GETGLOBALSERVERCOUNT:
+		return LAN_GetServerCount(AS_GLOBAL);
+
+	case UI_LAN_GETGLOBALSERVERADDRESSSTRING:
+		LAN_GetServerAddressString( AS_GLOBAL, args[1], VMA(2), args[3] );
+		return 0;
+#else
 	case UI_LAN_GETSERVERCOUNT:
 		return LAN_GetServerCount(args[1]);
 
 	case UI_LAN_GETSERVERADDRESSSTRING:
 		LAN_GetServerAddressString( args[1], args[2], VMA(3), args[4] );
 		return 0;
-
 	case UI_LAN_GETSERVERINFO:
 		LAN_GetServerInfo( args[1], args[2], VMA(3), args[4] );
 		return 0;
@@ -1011,24 +1037,33 @@
 
 	case UI_LAN_COMPARESERVERS:
 		return LAN_CompareServers( args[1], args[2], args[3], args[4], args[5] );
+#endif
 
 	case UI_MEMORY_REMAINING:
 		return Hunk_MemoryRemaining();
 
+#ifndef ELITEFORCE
 	case UI_GET_CDKEY:
 		CLUI_GetCDKey( VMA(1), args[2] );
 		return 0;
+#endif
 
 	case UI_SET_CDKEY:
 		CLUI_SetCDKey( VMA(1) );
+#ifdef ELITEFORCE
+		return qtrue;
+#else
 		return 0;
+#endif
 	
+#ifndef ELITEFORCE
 	case UI_SET_PBCLSTATUS:
 		return 0;	
 
 	case UI_R_REGISTERFONT:
 		re.RegisterFont( VMA(1), args[2], VMA(3));
 		return 0;
+#endif
 
 	case UI_MEMSET:
 		Com_Memset( VMA(1), args[2], args[3] );
@@ -1060,6 +1095,7 @@
 	case UI_CEIL:
 		return FloatAsInt( ceil( VMF(1) ) );
 
+#ifndef ELITEFORCE
 	case UI_PC_ADD_GLOBAL_DEFINE:
 		return botlib_export->PC_AddGlobalDefine( VMA(1) );
 	case UI_PC_LOAD_SOURCE:
@@ -1105,8 +1141,8 @@
 
 	case UI_VERIFY_CDKEY:
 		return CL_CDKeyValidate(VMA(1), VMA(2));
+#endif
 
-
 		
 	default:
 		Com_Error( ERR_DROP, "Bad UI system trap: %i", args[0] );
@@ -1162,6 +1198,10 @@
 //		Com_Printf(S_COLOR_YELLOW "WARNING: loading old Quake III Arena User Interface version %d\n", v );
 		// init for this gamestate
 		VM_Call( uivm, UI_INIT, (cls.state >= CA_AUTHORIZING && cls.state < CA_ACTIVE));
+
+		#ifdef ELITEFORCE
+		Cvar_SetValue("ui_cdkeychecked2", 1);
+		#endif
 	}
 	else if (v != UI_API_VERSION) {
 		Com_Error( ERR_DROP, "User Interface is version %d, expected %d", v, UI_API_VERSION );
@@ -1170,15 +1210,23 @@
 	else {
 		// init for this gamestate
 		VM_Call( uivm, UI_INIT, (cls.state >= CA_AUTHORIZING && cls.state < CA_ACTIVE) );
+
+		#ifdef ELITEFORCE
+		Cvar_SetValue("ui_cdkeychecked2", 1);
+		#endif
 	}
 }
 
 qboolean UI_usesUniqueCDKey( void ) {
+#ifdef ELITEFORCE
+	return qfalse;
+#else
 	if (uivm) {
 		return (VM_Call( uivm, UI_HASUNIQUECDKEY) == qtrue);
 	} else {
 		return qfalse;
 	}
+#endif
 }
 
 /*
Index: code/client/cl_net_chan.c
===================================================================
--- code/client/cl_net_chan.c	(revision 965)
+++ code/client/cl_net_chan.c	(working copy)
@@ -35,6 +35,8 @@
 
 ==============
 */
+
+#ifndef ELITEFORCE
 static void CL_Netchan_Encode( msg_t *msg ) {
 	int serverId, messageAcknowledge, reliableAcknowledge;
 	int i, index, srdc, sbit, soob;
@@ -79,6 +81,7 @@
 		*(msg->data + i) = (*(msg->data + i)) ^ key;
 	}
 }
+#endif
 
 /*
 ==============
@@ -89,6 +92,8 @@
 
 ==============
 */
+
+#ifndef ELITEFORCE
 static void CL_Netchan_Decode( msg_t *msg ) {
 	long reliableAcknowledge, i, index;
 	byte key, *string;
@@ -125,6 +130,7 @@
 		*(msg->data + i) = *(msg->data + i) ^ key;
 	}
 }
+#endif
 
 /*
 =================
@@ -141,9 +147,14 @@
 ================
 */
 void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg ) {
-	MSG_WriteByte( msg, clc_EOF );
+#ifdef ELITEFORCE
+	if(!chan->compat)
+#endif
+		MSG_WriteByte( msg, clc_EOF );
 
+#ifndef ELITEFORCE
 	CL_Netchan_Encode( msg );
+#endif
 	Netchan_Transmit( chan, msg->cursize, msg->data );
 }
 
@@ -161,7 +172,9 @@
 	ret = Netchan_Process( chan, msg );
 	if (!ret)
 		return qfalse;
+#ifndef ELITEFORCE
 	CL_Netchan_Decode( msg );
+#endif
 	newsize += msg->cursize;
 	return qtrue;
 }
Index: Makefile
===================================================================
--- Makefile	(revision 965)
+++ Makefile	(working copy)
@@ -31,6 +31,7 @@
 BUILD_SERVER     =
 BUILD_GAME_SO    =
 BUILD_GAME_QVM   =
+BUILD_ELITEFORCE =
 
 #############################################################################
 #
@@ -116,6 +117,10 @@
 USE_CODEC_VORBIS=0
 endif
 
+ifndef USE_CODEC_MP3
+USE_CODEC_MP3=0
+endif
+
 ifndef USE_LOCAL_HEADERS
 USE_LOCAL_HEADERS=1
 endif
@@ -142,18 +147,29 @@
 SDLHDIR=$(MOUNT_DIR)/SDL12
 LIBSDIR=$(MOUNT_DIR)/libs
 
-# extract version info
-VERSION=$(shell grep "\#define Q3_VERSION" $(CMDIR)/q_shared.h | \
-  sed -e 's/.*".* \([^ ]*\)"/\1/')
+ifeq ($(BUILD_ELITEFORCE),1)
+  # extract version info
+  CFLAGS += -DELITEFORCE
+  VERSION=$(shell grep "\#define Q3_VERSION" $(CMDIR)/q_shared.h | \
+    sed -e 's/.*".* \([^ ]*\)"/\1/' | head -n 1)
 
+  USE_SVN=0
+
+else
+
+  VERSION=$(shell grep "\#define Q3_VERSION" $(CMDIR)/q_shared.h | \
+      sed -e 's/.*".* \([^ ]*\)"/\1/' | tail -n 1)
+
 USE_SVN=
-ifeq ($(wildcard .svn),.svn)
-  SVN_REV=$(shell LANG=C svnversion .)
-  ifneq ($(SVN_REV),)
-    SVN_VERSION=$(VERSION)_SVN$(SVN_REV)
-    USE_SVN=1
+  ifeq ($(wildcard .svn),.svn)
+    SVN_REV=$(shell LANG=C svnversion .)
+    ifneq ($(SVN_REV),)
+      SVN_VERSION=$(VERSION)_SVN$(SVN_REV)
+      USE_SVN=1
+    endif
   endif
 endif
+
 ifneq ($(USE_SVN),1)
     SVN_VERSION=$(VERSION)
 endif
@@ -211,6 +227,10 @@
     BASE_CFLAGS += -DUSE_CODEC_VORBIS=1
   endif
 
+  ifeq ($(USE_CODEC_MP3),1)
+    BASE_CFLAGS += -DUSE_CODEC_MP3=1
+  endif
+
   ifeq ($(USE_SDL),1)
     BASE_CFLAGS += -DUSE_SDL_VIDEO=1 -DUSE_SDL_SOUND=1 $(shell sdl-config --cflags)
     GL_CFLAGS =
@@ -246,7 +266,7 @@
     BASE_CFLAGS += -DNO_VM_COMPILED
   endif
 
-  DEBUG_CFLAGS = $(BASE_CFLAGS) -g -O0
+  DEBUG_CFLAGS = $(BASE_CFLAGS) -g3 -ggdb3
 
   RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG $(OPTIMIZE)
 
@@ -255,8 +275,10 @@
   SHLIBLDFLAGS=-shared $(LDFLAGS)
 
   THREAD_LDFLAGS=-lpthread
-  LDFLAGS=-ldl -lm
+  LDFLAGS=-ldl -lm 
+  LDFLAGS += -L/emul/linux/x86/usr/lib
 
+
   ifeq ($(USE_SDL),1)
     CLIENT_LDFLAGS=$(shell sdl-config --libs)
   else
@@ -279,6 +301,10 @@
     CLIENT_LDFLAGS += -lvorbisfile -lvorbis -logg
   endif
 
+  ifeq ($(USE_CODEC_MP3),1)
+    CLIENT_LDFLAGS += -lmad
+  endif
+
   ifeq ($(ARCH),i386)
     # linux32 make ...
     BASE_CFLAGS += -m32
@@ -388,6 +414,10 @@
     CLIENT_LDFLAGS += -lvorbisfile -lvorbis -logg
   endif
 
+  ifeq ($(USE_CODEC_MP3),1)
+    BASE_CFLAGS += -DUSE_CODEC_MP3=1
+  endif
+
   ifeq ($(USE_SDL),1)
     BASE_CFLAGS += -DUSE_SDL_VIDEO=1 -DUSE_SDL_SOUND=1 -D_THREAD_SAFE=1 \
       -I$(SDLHDIR)/include
@@ -419,6 +449,10 @@
 
   NOTSHLIBCFLAGS=-mdynamic-no-pic
 
+  ifeq ($(USE_CODEC_MP3),1)
+    CLIENT_LDFLAGS += -lmad
+  endif
+
 else # ifeq darwin
 
 
@@ -450,6 +484,10 @@
     BASE_CFLAGS += -DUSE_CODEC_VORBIS=1
   endif
 
+  ifeq ($(USE_CODEC_MP3),1)
+    BASE_CFLAGS += -DUSE_CODEC_MP3=1
+  endif
+
   GL_CFLAGS =
   MINGW_CFLAGS = -DDONT_TYPEDEF_INT32
 
@@ -481,6 +519,10 @@
     CLIENT_LDFLAGS += -lvorbisfile -lvorbis -logg
   endif
 
+  ifeq ($(USE_CODEC_MP3),1)
+    CLIENT_LDFLAGS += -lmad
+  endif
+
   ifeq ($(ARCH),x86)
     # build 32bit
     BASE_CFLAGS += -m32
@@ -522,6 +564,10 @@
     BASE_CFLAGS += -DUSE_CODEC_VORBIS=1
   endif
 
+  ifeq ($(USE_CODEC_MP3),1)
+    BASE_CFLAGS += -DUSE_CODEC_MP3=1
+  endif
+
   ifeq ($(USE_SDL),1)
     BASE_CFLAGS += $(shell sdl-config --cflags) -DUSE_SDL_VIDEO=1 -DUSE_SDL_SOUND=1
   endif
@@ -570,6 +616,9 @@
     CLIENT_LDFLAGS += -lvorbisfile -lvorbis -logg
   endif
 
+  ifeq ($(USE_CODEC_MP3),1)
+    CLIENT_LDFLAGS += -lmad
+  endif
 
 else # ifeq freebsd
 
@@ -890,6 +939,7 @@
   $(B)/client/snd_codec.o \
   $(B)/client/snd_codec_wav.o \
   $(B)/client/snd_codec_ogg.o \
+  $(B)/client/snd_codec_mp3.o \
   \
   $(B)/client/qal.o \
   $(B)/client/snd_openal.o \
@@ -1112,6 +1162,7 @@
 $(B)/client/snd_codec.o : $(CDIR)/snd_codec.c; $(DO_CC)
 $(B)/client/snd_codec_wav.o : $(CDIR)/snd_codec_wav.c; $(DO_CC)
 $(B)/client/snd_codec_ogg.o : $(CDIR)/snd_codec_ogg.c; $(DO_CC)
+$(B)/client/snd_codec_mp3.o : $(CDIR)/snd_codec_mp3.c; $(DO_CC)
 
 $(B)/client/qal.o : $(CDIR)/qal.c; $(DO_CC)
 $(B)/client/snd_openal.o : $(CDIR)/snd_openal.c; $(DO_CC)
