Index: README
===================================================================
--- README	(revision 2058)
+++ README	(working copy)
@@ -77,32 +77,23 @@
 The following variables may be set, either on the command line or in
 Makefile.local:
 
-  CFLAGS             - use this for custom CFLAGS
-  V                  - set to show cc command line when building
-  DEFAULT_BASEDIR    - extra path to search for baseq3 and such
-  BUILD_SERVER       - build the 'ioq3ded' server binary
-  BUILD_CLIENT       - build the 'ioquake3' client binary
-  BUILD_CLIENT_SMP   - build the 'ioquake3-smp' client binary
-  BUILD_GAME_SO      - build the game shared libraries
-  BUILD_GAME_QVM     - build the game qvms
-  BUILD_STANDALONE   - build binaries suited for stand-alone games
-  USE_OPENAL         - use OpenAL where available
-  USE_OPENAL_DLOPEN  - link with OpenAL at runtime
-  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_MUMBLE         - enable Mumble support
-  USE_VOIP           - enable built-in VoIP support
-  USE_INTERNAL_SPEEX - build internal speex library instead of dynamically
-                       linking against system libspeex
-  USE_OLD_VM64       - use Ludwig Nussel's old JIT compiler implementation
-                       for x86_64
-  USE_INTERNAL_ZLIB  - build and link against internal zlib
-  USE_INTERNAL_JPEG  - build and link against internal JPEG library
-  USE_LOCAL_HEADERS  - use headers local to ioq3 instead of system ones
-  DEBUG_CFLAGS       - C compiler flags to use for building debug version
-  COPYDIR            - the target installation directory
-  TEMPDIR            - specify user defined directory for temp files
+  CFLAGS            - use this for custom CFLAGS
+  V                 - set to show cc command line when building
+  DEFAULT_BASEDIR   - extra path to search for baseq3 and such
+  BUILD_SERVER      - build the 'ioq3ded' server binary
+  BUILD_CLIENT      - build the 'ioquake3' client binary
+  BUILD_CLIENT_SMP  - build the 'ioquake3-smp' client binary
+  BUILD_GAME_SO     - build the game shared libraries
+  BUILD_GAME_QVM    - build the game qvms
+  BUILD_STANDALONE  - build binaries suited for stand-alone games
+  USE_OPENAL        - use OpenAL where available
+  USE_OPENAL_DLOPEN - link with OpenAL at runtime
+  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
+  COPYDIR           - the target installation directory
 
 The defaults for these variables differ depending on the target platform.
 
@@ -117,32 +108,7 @@
   cl_cURLLib                        - filename of cURL library to load
   cl_consoleKeys                    - space delimited list of key names or
                                       characters that toggle the console
-  cl_mouseAccelStyle                - Set to 1 for QuakeLive mouse acceleration
-                                      behaviour, 0 for standard q3
-  cl_mouseAccelOffset               - Tuning the acceleration curve, see below
-  cl_gamename                       - Gamename sent to master server in
-                                      getserversExt query
 
-  in_joystickUseAnalog              - Do not translate joystick axis events
-                                      to keyboard commands
-
-  j_forward                         - Joystick analogue to m_forward,
-                                      for forward movement speed/direction.
-  j_side                            - Joystick analogue to m_side,
-                                      for side movement speed/direction.
-  j_pitch                           - Joystick analogue to m_pitch,
-                                      for pitch rotation speed/direction.
-  j_yaw                             - Joystick analogue to m_yaw,
-                                      for yaw rotation speed/direction.
-  j_forward_axis                    - Selects which joystick axis
-                                      controls forward/back.
-  j_side_axis                       - Selects which joystick axis
-                                      controls left/right.
-  j_pitch_axis                      - Selects which joystick axis
-                                      controls pitch.
-  j_yaw_axis                        - Selects which joystick axis
-                                      controls yaw.
-
   s_useOpenAL                       - use the OpenAL sound backend if available
   s_alPrecache                      - cache OpenAL sounds before use
   s_alGain                          - the value of AL_GAIN for each source
@@ -161,48 +127,26 @@
   s_alDriver                        - which OpenAL library to use
   s_alDevice                        - which OpenAL device to use
   s_alAvailableDevices              - list of available OpenAL devices
-  s_alInputDevice                   - which OpenAL input device to use
-  s_alAvailableInputDevices         - list of available OpenAL input devices
+
   s_sdlBits                         - SDL bit resolution
   s_sdlSpeed                        - SDL sample rate
   s_sdlChannels                     - SDL number of channels
   s_sdlDevSamps                     - SDL DMA buffer size override
   s_sdlMixSamps                     - SDL mix buffer size override
-  s_backend                         - read only, indicates the current sound
-                                      backend
-  s_muteWhenMinimized               - mute sound when minimized
-  s_muteWhenUnfocused               - mute sound when window is unfocused
 
   com_ansiColor                     - enable use of ANSI escape codes in the tty
   com_altivec                       - enable use of altivec on PowerPC systems
-  com_standalone (read only)        - If set to 1, quake3 is running in
-                                      standalone mode
-  com_basegame                      - Use a different base than baseq3. If no
-                                      original Quake3 or TeamArena pak files
-                                      are found, this will enable running in
-                                      standalone mode
-  com_homepath                      - Specify name that is to be appended to the
-                                      home path
+  com_standalone                    - Run in standalone mode
   com_maxfpsUnfocused               - Maximum frames per second when unfocused
   com_maxfpsMinimized               - Maximum frames per second when minimized
-  com_busyWait                      - Will use a busy loop to wait for rendering
-                                      next frame when set to non-zero value
-  com_pipefile                      - Specify filename to create a named pipe 
-                                      through which other processes can control
-                                      the server while it is running. 
-                                      Nonfunctional on Windows.
-
+  s_backend                         - read only, indicates the current sound
+                                      backend
+  s_muteWhenMinimized               - mute sound when minimized
   in_joystickNo                     - select which joystick to use
-  in_availableJoysticks             - list of available Joysticks
   in_keyboardDebug                  - print keyboard debug info
-
+  r_ext_texture_filter_anisotropic  - anisotropic texture filtering
   sv_dlURL                          - the base of the HTTP or FTP site that
                                       holds custom pk3 files for your server
-  sv_banFile                        - Name of the file that is used for storing
-                                      the server bans
-  sv_heartbeat                      - Heartbeat string sent to master server
-  sv_flatline                       - Heartbeat string sent to master server
-                                      when server is killed
 
   net_ip6                           - IPv6 address to bind to
   net_port6                         - port to bind to using the ipv6 address
@@ -216,15 +160,9 @@
                                       ipv6 servers on the local network
   net_mcastiface                    - outgoing interface to use for scan
 
-  protocol                          - Allow changing protocol version
-                                      (startup only)
-
-  r_allowResize                     - make window resizable (SDL only)
-  r_ext_texture_filter_anisotropic  - anisotropic texture filtering
   r_zProj                           - distance of observer camera to projection
                                       plane in quake3 standard units
-  r_greyscale                       - desaturate textures, useful for anaglyph,
-                                      supports values in the range of 0 to 1
+  r_greyscale                       - render black and white images
   r_stereoEnabled                   - enable stereo rendering for techniques
                                       like shutter glasses (untested)
   r_anaglyphMode                    - Enable rendering of anaglyph images
@@ -242,27 +180,16 @@
                                       See also
                                       http://wiki.ioquake3.org/Stereo_Rendering
                                       for more information
-  r_marksOnTriangleMeshes           - Support impact marks on md3 models, MOD
-                                      developers should increase the mark
-                                      triangle limits in cg_marks.c if they
-                                      intend to use this.
   r_sdlDriver                       - read only, indicates the SDL driver
                                       backend being used
-  r_noborder                        - Remove window decoration from window
-                                      managers, like borders and titlebar.
-  r_screenshotJpegQuality           - Controls quality of jpeg screenshots
-                                      captured using screenshotJPEG
-  r_aviMotionJpegQuality            - Controls quality of video capture when
-                                      cl_aviMotionJpeg is enabled
+  sv_banFile                        - Name of the file that is used for storing
+                                      the server bans.
 
 New commands
   video [filename]        - start video capture (use with demo command)
   stopvideo               - stop video capture
-  stopmusic               - stop background music
-  minimize                - Minimize the game and show desktop
 
   print                   - print out the contents of a cvar
-  unset                   - unset a user created cvar
 
   banaddr <range>         - ban an ip address range from joining a game on this
                             server, valid <range> is either playernum or CIDR
@@ -275,10 +202,7 @@
   flushbans               - delete all bans
 
   net_restart             - restart network subsystem to change latched settings
-  game_restart <fs_game>  - Switch to another mod
 
-  which <filename/path>   - print out the path on disk to a loaded item
-
 ------------------------------------------------------------ Miscellaneous -----
 
 Using shared libraries instead of qvm
@@ -297,61 +221,6 @@
   data, nor is it something that we like to spend much time maintaining or
   supporting.
 
-Help! Ioquake3 won't give me an fps of X anymore when setting com_maxfps!
-  Ioquake3 now uses the select() system call to wait for the rendering of the
-  next frame when com_maxfps was hit. This will improve your CPU load
-  considerably in these cases. However, not all systems may support a
-  granularity for its timing functions that is required to perform this waiting
-  correctly. For instance, ioquake3 tells select() to wait 2 milliseconds, but
-  really it can only wait for a multiple of 5ms, i.e. 5, 10, 15, 20... ms.
-  In this case you can always revert back to the old behaviour by setting the
-  cvar com_busyWait to 1.
-
-QuakeLive mouse acceleration (patch and this text written by TTimo from id)
-  I've been using an experimental mouse acceleration code for a while, and
-  decided to make it available to everyone. Don't be too worried if you don't
-  understand the explanations below, this is mostly intended for advanced
-  players:
-  To enable it, set cl_mouseAccelStyle 1 (0 is the default/legacy behavior)
-
-  New style is controlled with 3 cvars:
-
-  sensitivity
-  cl_mouseAccel
-  cl_mouseAccelOffset
-
-  The old code (cl_mouseAccelStyle 0) can be difficult to calibrate because if
-  you have a base sensitivity setup, as soon as you set a non zero acceleration
-  your base sensitivity at low speeds will change as well. The other problem
-  with style 0 is that you are stuck on a square (power of two) acceleration
-  curve.
-
-  The new code tries to solve both problems:
-
-  Once you setup your sensitivity to feel comfortable and accurate enough for
-  low mouse deltas with no acceleration (cl_mouseAccel 0), you can start
-  increasing cl_mouseAccel and tweaking cl_mouseAccelOffset to get the
-  amplification you want for high deltas with little effect on low mouse deltas.
-
-  cl_mouseAccel is a power value. Should be >= 1, 2 will be the same power curve
-  as style 0. The higher the value, the faster the amplification grows with the
-  mouse delta.
-
-  cl_mouseAccelOffset sets how much base mouse delta will be doubled by
-  acceleration. The closer to zero you bring it, the more acceleration will
-  happen at low speeds. This is also very useful if you are changing to a new
-  mouse with higher dpi, if you go from 500 to 1000 dpi, you can divide your
-  cl_mouseAccelOffset by two to keep the same overall 'feel' (you will likely
-  gain in precision when you do that, but that is not related to mouse
-  acceleration).
-
-  Mouse acceleration is tricky to configure, and when you do you'll have to
-  re-learn your aiming. But you will find that it's very much forth it in the
-  long run.
-
-  If you try the new acceleration code and start using it, I'd be very
-  interested by your feedback.
-
 64bit mods
   If you wish to compile external mods as shared libraries on a 64bit platform,
   and the mod source is derived from the id Q3 SDK, you will need to modify the
@@ -395,39 +264,11 @@
   your own binaries. Instead, you can just use the pre-built binaries on the
   website. Just make sure the game is called with:
 
-    +set com_basegame <yournewbase>
-    
-  in any links/scripts you install for your users to start the game. The
-  binary must not detect any original quake3 game pak files. If this
-  condition is met, the game will set com_standalone to 1 and is then running
-  in stand alone mode.
-  
-  If you want the engine to use a different directory in your homepath than
-  e.g. "Quake3" on Windows or ".q3a" on Linux, then set a new name at startup
-  by adding
-  
-    +set com_homepath <homedirname>
-  
-  to the command line. Then you can control which kind of messages to send to
-  the master server:
-  
-    +set sv_heartbeat <heartbeat> +set sv_flatline <flatline>
-    +set cl_gamename <gamename>
-  
-  The <heartbeat> and <flatline> message can be specific to your game. The
-  flatline message is sent to signal the master server that the game server is
-  quitting. Vanilla quake3 uses "QuakeArena-1" both for the heartbeat and
-  flatline messages.
-  The cl_gamename message is for dpmaster to specify which game the client
-  wants a server list for. It is only used in the new ipv6 based getServersExt
-  query.
-  
-  Example line:
-  
-    +set com_basegame basefoo +set com_homepath .foo
-    +set sv_heartbeat fooalive +set sv_flatline foodead
-    +set cl_gamename foo
+    +set com_standalone 1 +set fs_game <yourgamedir>
 
+  in any links/scripts you install for your users to start the game. Note that
+  the com_standalone setting is rendered ineffective, if the binary detects pk3
+  files in the directory "baseq3", so you cannot use that one as game dir.
 
   If you really changed parts that would make vanilla ioquake3 incompatible with
   your mod, we have included another way to conveniently build a stand-alone
@@ -492,6 +333,7 @@
   sv_allowDownload's value is now a bitmask made up of the following
   flags:
     1 - ENABLE
+    2 - do not use HTTP/FTP downloads
     4 - do not use UDP downloads
     8 - do not ask the client to disconnect when using HTTP/FTP
 
@@ -579,6 +421,26 @@
   text. Also, in addition to the nominated console keys, Shift-ESC is hard
   coded to always toggle the console.
 
+Mouse Input On Windows
+  ioq3 uses SDL to abstract away as much as possible from platform specific
+  implementation details. Unfortunately, SDL 1.2 suffers from a number of bugs
+  and limitations with respect to mouse input on the Windows platform. We
+  provide a patch against the SDL subversion 1.2 branch which fixes the
+  following problems:
+
+    * DirectX (and thus DirectInput) driver not functional when using an
+      OpenGL SDL_Surface.
+
+    * DirectX (and thus DirectInput) driver not functional in windowed mode.
+
+    * Mouse buttons 4-7 unusable with the DirectX driver due to DirectInput 5
+      not exposing the required functionality. Use DirectInput 7 instead.
+
+    * Low quality mouse input data when using the windib driver due to use of
+      WM_MOUSEMOVE events. Use GetCursorPos API call instead.
+
+  The patch can be found in misc/sdl-win32-fixes.diff.
+
 PNG support
   ioquake3 supports the use of PNG (Portable Network Graphic) images as
   textures. It should be noted that the use of such images in a map will
Index: README-EF.txt
===================================================================
--- README-EF.txt	(revision 0)
+++ README-EF.txt	(revision 0)
@@ -0,0 +1,397 @@
+README for StarTrek Voyager - Elite Force engine release
+Project page: http://thilo.kickchat.com/efport-progress/
+   - last updated 05.03.2008
+
+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>\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. An OpenAL installation tool comes with this installer and can
+optionally be run from it. If you have got the latest version installed
+already, of course you do not need to reinstall OpenAL.
+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.
+
+########################################
+### MACOSX INSTALLATION INSTRUCTIONS ###
+########################################
+
+Install the normal game from CD if you have not already done so. Make also
+sure to have the expansion pack, or at least the latest patch version 1.2
+that is available for EliteForce, installed.
+Now extract the .dmg file to the installation directory of your EliteForce
+game. Run iostvoyHM-1.37 to start the game.
+
+There have been problems with the MacOSX version of OpenAL and ioquake3.
+This is why OpenAL is disabled per default in this release.
+You can still enable OpenAL sound in the sound configuration menu, though.
+You will have to click the sound quality setting in the sound configuration
+menu to change the backend used. Maybe it works fine for you so you won't
+have to play with the standard sound.
+
+#######################################
+### 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 pak92.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.
+
+#########################################
+### FREEBSD INSTALLATION INSTRUCTIONS ###
+#########################################
+
+Alas, the installer for Linux does not support FreeBSD. However, you can still
+play the game natively. Just follow the manual installation instructions from
+the Linux part and all should be good. The required libraries are the same on
+FreeBSD and Linux.
+
+########################
+### 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
+
+ - Derek O. for a PPC Linux and MacOSX shell
+
+ - Marcin Koziuk for the FreeBSD builds
+
+ -- Thilo Schulz (arny@ats.s.bawue.de)
Index: Makefile.local
===================================================================
--- Makefile.local	(revision 0)
+++ Makefile.local	(revision 0)
@@ -0,0 +1,22 @@
+BUILD_GAME_SO=0
+BUILD_GAME_QVM=0
+BUILD_CLIENT_SMP=0
+BUILD_MISSIONPACK=1
+#BUILD_CLIENT=0
+#BUILD_SERVER=0
+USE_CODEC_VORBIS=0
+USE_CODEC_MP3=1
+USE_OPENAL=1
+USE_OPENAL_DLOPEN=1
+USE_CURL=1
+USE_CURL_DLOPEN=1
+BUILD_ELITEFORCE=1
+#BUILD_STANDALONE=1
+V=0
+#USE_INTERNAL_ZLIB=0
+#DEBUG_CFLAGS=-g3 -ggdb3 -O0
+#DEBUG_CFLAGS=-O0 -pg
+#CLIENT_LDFLAGS=-pg
+USE_INTERNAL_JPEG=1
+USE_LOCAL_HEADERS=1
+USE_OLD_VM64=0
Index: code/renderer/tr_local.h
===================================================================
--- code/renderer/tr_local.h	(revision 2058)
+++ code/renderer/tr_local.h	(working copy)
@@ -143,7 +143,8 @@
 	GF_SAWTOOTH, 
 	GF_INVERSE_SAWTOOTH, 
 
-	GF_NOISE
+	GF_NOISE,
+	GF_RANDOM
 
 } genFunc_t;
 
@@ -999,6 +1000,7 @@
 	float					triangleTable[FUNCTABLE_SIZE];
 	float					sawToothTable[FUNCTABLE_SIZE];
 	float					inverseSawToothTable[FUNCTABLE_SIZE];
+	float                                   noiseTable[FUNCTABLE_SIZE];
 	float					fogTable[FOG_TABLE_SIZE];
 } trGlobals_t;
 
@@ -1058,6 +1060,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
@@ -1150,6 +1155,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 );
@@ -1278,6 +1284,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_init.c
===================================================================
--- code/renderer/tr_init.c	(revision 2058)
+++ code/renderer/tr_init.c	(working copy)
@@ -65,6 +65,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;
@@ -193,6 +196,10 @@
 		
 		GLimp_Init();
 
+#ifdef ELITEFORCE
+		glConfig.textureFilterAnisotropicAvailable = textureFilterAnisotropic;
+#endif
+
 		strcpy( renderer_buffer, glConfig.renderer_string );
 		Q_strlwr( renderer_buffer );
 
@@ -985,7 +992,11 @@
 	// latched and archived variables
 	//
 	r_allowExtensions = ri.Cvar_Get( "r_allowExtensions", "1", CVAR_ARCHIVE | CVAR_LATCH );
+#ifdef ELITEFORCE
+	r_ext_compressed_textures = ri.Cvar_Get( "r_ext_compress_textures", "0", CVAR_ARCHIVE | CVAR_LATCH );
+#else
 	r_ext_compressed_textures = ri.Cvar_Get( "r_ext_compressed_textures", "0", CVAR_ARCHIVE | CVAR_LATCH );
+#endif
 	r_ext_multitexture = ri.Cvar_Get( "r_ext_multitexture", "1", CVAR_ARCHIVE | CVAR_LATCH );
 	r_ext_compiled_vertex_array = ri.Cvar_Get( "r_ext_compiled_vertex_array", "1", CVAR_ARCHIVE | CVAR_LATCH);
 	r_ext_texture_env_add = ri.Cvar_Get( "r_ext_texture_env_add", "1", CVAR_ARCHIVE | CVAR_LATCH);
@@ -1027,7 +1038,11 @@
 	// temporary latched variables that can only change over a restart
 	//
 	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 );
 
@@ -1043,6 +1058,9 @@
 	r_stereoSeparation = ri.Cvar_Get( "r_stereoSeparation", "64", CVAR_ARCHIVE );
 	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 );
@@ -1148,10 +1166,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();
 
@@ -1160,6 +1185,8 @@
 	}
 	Com_Memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) );
 
+	R_NoiseInit();
+
 	//
 	// init function tables
 	//
@@ -1169,6 +1196,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 )
 		{
@@ -1189,8 +1217,6 @@
 
 	R_InitFogTable();
 
-	R_NoiseInit();
-
 	R_Register();
 
 	max_polys = r_maxpolys->integer;
@@ -1315,6 +1341,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 2058)
+++ 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_noise.c
===================================================================
--- code/renderer/tr_noise.c	(revision 2058)
+++ code/renderer/tr_noise.c	(working copy)
@@ -30,6 +30,7 @@
 
 static float s_noise_table[NOISE_SIZE];
 static int s_noise_perm[NOISE_SIZE];
+static int s_random[NOISE_SIZE];
 
 static float GetNoiseValue( int x, int y, int z, int t )
 {
@@ -46,6 +47,7 @@
 	{
 		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;
 	}
 }
 
@@ -89,3 +91,10 @@
 
 	return finalvalue;
 }
+
+// used in the shader functions (GF_RANDOM) to implement a quasi random flickering.
+#define VALR( a ) s_random[ ( a ) & ( NOISE_MASK )]
+int R_RandomOn(float t)
+{
+	return VALR((unsigned int) floor(t));
+}
Index: code/renderer/tr_surface.c
===================================================================
--- code/renderer/tr_surface.c	(revision 2058)
+++ 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 @@
 */
 static 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/renderer/tr_scene.c
===================================================================
--- code/renderer/tr_scene.c	(revision 2058)
+++ code/renderer/tr_scene.c	(working copy)
@@ -311,7 +311,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_shader.c
===================================================================
--- code/renderer/tr_shader.c	(revision 2058)
+++ code/renderer/tr_shader.c	(working copy)
@@ -293,6 +293,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;
@@ -741,6 +745,12 @@
 			{
 				depthFuncBits = 0;
 			}
+#ifdef ELITEFORCE
+			if ( !Q_stricmp( token, "disable" ) )
+			{
+				depthFuncBits = 0;
+			}
+#endif
 			else if ( !Q_stricmp( token, "equal" ) )
 			{
 				depthFuncBits = GLS_DEPTHFUNC_EQUAL;
@@ -2782,7 +2792,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
@@ -2939,8 +2980,8 @@
 			SkipBracedSection(&oldp);
 			p = oldp;
 		}
-			
 		
+
 		if (buffers[i])
 			sum += summand;		
 	}
Index: code/renderer/tr_light.c
===================================================================
--- code/renderer/tr_light.c	(revision 2058)
+++ 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 2058)
+++ code/renderer/tr_types.h	(working copy)
@@ -24,7 +24,7 @@
 #define __TR_TYPES_H
 
 
-#define	MAX_DLIGHTS		32		// can't be increased, because bit flags are used on surfaces
+#define	MAX_DLIGHTS		32			// can't be increased, because bit flags are used on surfaces
 #define	MAX_ENTITIES		1023		// can't be increased without changing drawsurf bit packing
 
 // renderfx flags
@@ -33,24 +33,33 @@
 #define	RF_FIRST_PERSON		0x0004		// only draw through eyes (view weapon, damage blood blob)
 #define	RF_DEPTHHACK		0x0008		// for view weapon Z crunching
 
-#define RF_CROSSHAIR		0x0010		// This item is a cross hair and will draw over everything similar to
+#ifdef ELITEFORCE
+#define RF_FULLBRIGHT		0x0010
+#define RF_CROSSHAIR		0x0020		// This item is a cross hair and will draw over everything similar to
 						// DEPTHHACK in stereo rendering mode, with the difference that the
 						// projection matrix won't be hacked to reduce the stereo separation as
 						// is done for the gun.
+#else
+#define RF_CROSSHAIR            0x0010
+#endif
 
 #define	RF_NOSHADOW		0x0040		// don't add stencil shadows
 
 #define RF_LIGHTING_ORIGIN	0x0080		// use refEntity->lightingOrigin instead of refEntity->origin
-						// for lighting.  This allows entities to sink into the floor
-						// with their origin going solid, and allows all parts of a
-						// player to get the same lighting
-
+									// for lighting.  This allows entities to sink into the floor
+									// with their origin going solid, and allows all parts of a
+									// player to get the same lighting
 #define	RF_SHADOW_PLANE		0x0100		// use refEntity->shadowPlane
 #define	RF_WRAP_FRAMES		0x0200		// 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	0x0001		// used for player configuration screen
-#define RDF_HYPERSPACE		0x0004		// teleportation effect
+#define RDF_NOWORLDMODEL	1		// used for player configuration screen
+#define RDF_HYPERSPACE		4		// teleportation effect
 
 typedef struct {
 	vec3_t		xyz;
@@ -64,7 +73,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,
@@ -76,6 +106,7 @@
 
 	RT_MAX_REF_ENTITY_TYPE
 } refEntityType_t;
+#endif
 
 typedef struct {
 	refEntityType_t	reType;
@@ -108,8 +139,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;
 
 
@@ -130,8 +202,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;
 
 
@@ -179,7 +253,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						numTextureUnits;		// multitexture ability
@@ -192,6 +270,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_public.h
===================================================================
--- code/renderer/tr_public.h	(revision 2058)
+++ 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_shade.c
===================================================================
--- code/renderer/tr_shade.c	(revision 2058)
+++ code/renderer/tr_shade.c	(working copy)
@@ -1109,6 +1109,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++ )
 	{
@@ -1119,7 +1123,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 )
@@ -1152,7 +1174,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_main.c
===================================================================
--- code/renderer/tr_main.c	(revision 2058)
+++ code/renderer/tr_main.c	(working copy)
@@ -1015,18 +1015,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;
 			}
 		}
@@ -1224,6 +1231,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_backend.c
===================================================================
--- code/renderer/tr_backend.c	(revision 2058)
+++ 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/server/sv_world.c
===================================================================
--- code/server/sv_world.c	(revision 2058)
+++ 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 2058)
+++ code/server/sv_game.c	(working copy)
@@ -335,9 +335,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;
@@ -357,14 +358,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:
@@ -423,12 +428,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:
 		Q_SnapVector(VMA(1));
 		return 0;
-
+#endif
 		//====================================
 
 	case BOTLIB_SETUP:
@@ -440,6 +446,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:
@@ -450,7 +460,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:
@@ -467,13 +477,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;
@@ -488,8 +499,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] );
 
@@ -511,11 +524,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:
@@ -532,9 +546,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] );
 		return 0;
+#endif
 	case BOTLIB_EA_GESTURE:
 		botlib_export->ea.EA_Gesture( args[1] );
 		return 0;
@@ -664,7 +680,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:
@@ -714,9 +734,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;
@@ -746,9 +768,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;
@@ -836,7 +860,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: %ld", (long int) args[0] );
 	}
Index: code/server/sv_client.c
===================================================================
--- code/server/sv_client.c	(revision 2058)
+++ code/server/sv_client.c	(working copy)
@@ -97,7 +97,11 @@
 #ifndef STANDALONE
 	// Drop the authorize stuff if this client is coming in via v6 as the auth server does not support ipv6.
 	// Drop also for addresses coming in on local LAN and for stand-alone games independent from id's assets.
+#ifdef ELITEFORCE
 	if(challenge->adr.type == NA_IP && !com_standalone->integer && !Sys_IsLANAddress(from))
+#else
+	if(challenge->adr.type == NA_IP && !com_standalone->integer && !Sys_IsLANAddress(from))
+#endif
 	{
 		// look up the authorize server's IP
 		if (svs.authorizeAddress.type == NA_BAD)
@@ -125,16 +129,23 @@
 			Com_DPrintf( "authorize server timed out\n" );
 		else
 		{
-			// otherwise send their ip to the authorize server
+#ifndef ELITEFORCE
 			cvar_t	*fs;
 			char	game[1024];
+#endif
 
 			// If the client provided us with a client challenge, store it...
 			if(*clientChallenge)
 				challenge->clientChallenge = atoi(clientChallenge);
 			
 			Com_DPrintf( "sending getIpAuthorize for %s\n", NET_AdrToString( from ));
-		
+
+			// otherwise send their ip to the authorize server
+#ifdef ELITEFORCE
+			NET_OutOfBandPrint( NS_SERVER, svs.authorizeAddress,
+				"getIpAuthorize %i %i.%i.%i.%i ",  svs.challenges[i].challenge,
+				from.ip[0], from.ip[1], from.ip[2], from.ip[3] );
+#else
 			strcpy(game, BASEGAME);
 			fs = Cvar_Get ("fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO );
 			if (fs && fs->string[0] != 0) {
@@ -146,7 +157,7 @@
 			NET_OutOfBandPrint( NS_SERVER, svs.authorizeAddress,
 				"getIpAuthorize %i %i.%i.%i.%i %s 0 %s",  challenge->challenge,
 				from.ip[0], from.ip[1], from.ip[2], from.ip[3], game, sv_strictAuth->string );
-			
+#endif
 			return;
 		}
 	}
@@ -302,7 +313,12 @@
 	Q_strncpyz( userinfo, Cmd_Argv(1), sizeof(userinfo) );
 
 	version = atoi( Info_ValueForKey( userinfo, "protocol" ) );
-	if ( version != com_protocol->integer ) {
+#ifdef ELITEFORCE
+	if(version != EFPROTOCOL_VERSION && version != com_protocol->integer)
+#else
+	if(version != com_protocol->integer)
+#endif
+	{
 		NET_OutOfBandPrint( NS_SERVER, from, "print\nServer uses protocol version %i (yours is %i).\n", com_protocol->integer, version );
 		Com_DPrintf ("    rejected connect from version %i\n", version);
 		return;
@@ -483,6 +499,7 @@
 	ent = SV_GentityNum( clientNum );
 	newcl->gentity = ent;
 
+
 	// save the challenge
 	newcl->challenge = challenge;
 
@@ -491,6 +508,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) );
 
@@ -584,7 +610,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 ( isBot ) {
 		SV_BotFreeClient( drop - svs.clients );
@@ -643,11 +674,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
@@ -679,9 +722,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);
@@ -847,6 +898,9 @@
 	int curindex;
 	int rate;
 	int blockspersnap;
+#ifndef ELITEFORCE
+	int missionPack = 0;
+#endif
 	int unreferenced = 1;
 	char errorMessage[1024];
 	char pakbuf[MAX_QPATH], *pakptr;
@@ -858,9 +912,11 @@
 	if(!cl->download)
 	{
 		qboolean idPack = qfalse;
+		#ifndef ELITEFORCE
 		#ifndef STANDALONE
 		qboolean missionPack = qfalse;
 		#endif
+		#endif
 	
  		// Chop off filename extension.
 		Com_sprintf(pakbuf, sizeof(pakbuf), "%s", cl->downloadName);
@@ -889,8 +945,12 @@
 						// now that we know the file is referenced,
 						// check whether it's legal to download it.
 #ifndef STANDALONE
+						#ifdef ELITEFORCE
+						idPack = FS_idPak(pakbuf, BASEGAME, NUM_ID_PAKS);
+						#else
 						missionPack = FS_idPak(pakbuf, BASETA, NUM_TA_PAKS);
 						idPack = missionPack;
+						#endif
 #endif
 						idPack = idPack || FS_idPak(pakbuf, BASEGAME, NUM_ID_PAKS);
 
@@ -914,6 +974,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", (int) (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", (int) (cl - svs.clients), cl->downloadName);
 #ifndef STANDALONE
 				if(missionPack)
@@ -926,6 +990,7 @@
 				{
 					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) ) {
@@ -950,7 +1015,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;
 			
@@ -1180,21 +1248,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) {
@@ -1593,7 +1668,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];
@@ -1617,6 +1695,7 @@
 		return;
 	}
 
+	#ifndef ELITEFORCE
 	// use the checksum feed in the key
 	key = sv.checksumFeed;
 	// also use the message acknowledge
@@ -1624,11 +1703,17 @@
 	// also use the last acknowledged server command in the key
 	key ^= MSG_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;
 	}
 
@@ -1820,7 +1905,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 );
@@ -1886,6 +1974,7 @@
 	do {
 		c = MSG_ReadByte( msg );
 
+
 		// See if this is an extension command after the EOF, which means we
 		//  got data that a legacy server should ignore.
 		if ((c == clc_EOF) && (MSG_LookaheadByte( msg ) == clc_extension)) {
@@ -1898,9 +1987,12 @@
 			}
 		}
 
-		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 2058)
+++ code/server/sv_net_chan.c	(working copy)
@@ -24,6 +24,7 @@
 #include "../qcommon/qcommon.h"
 #include "server.h"
 
+#ifndef ELITEFORCE
 /*
 ==============
 SV_Netchan_Encode
@@ -127,6 +128,7 @@
 		*(msg->data + i) = *(msg->data + i) ^ key;
 	}
 }
+#endif
 
 /*
 =================
@@ -146,7 +148,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;
@@ -174,7 +178,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");
@@ -188,7 +196,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 );
 	}
 }
@@ -203,7 +213,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 2058)
+++ 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 );
@@ -414,6 +420,7 @@
 
 		// if it's 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);
@@ -421,6 +428,7 @@
 					continue;
 				}
 			}
+#endif
 			SV_AddEntitiesVisibleFromPoint( ent->s.origin2, frame, eNums, qtrue );
 		}
 
@@ -633,12 +641,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 2058)
+++ code/server/server.h	(working copy)
@@ -189,6 +189,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 2058)
+++ code/server/sv_init.c	(working copy)
@@ -663,7 +663,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 );
@@ -672,8 +676,14 @@
 	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", "efmaster.tjps.eu", CVAR_ARCHIVE);
+	for(index = 2; index < MAX_MASTER_SERVERS; index++)
+		sv_master[index] = Cvar_Get(va("sv_master%d", index + 1), "", CVAR_ARCHIVE);
+	#else
 	for(index = 1; index < MAX_MASTER_SERVERS; index++)
 		sv_master[index] = Cvar_Get(va("sv_master%d", index + 1), "", CVAR_ARCHIVE);
+	#endif
 
 	sv_reconnectlimit = Cvar_Get ("sv_reconnectlimit", "3", 0);
 	sv_showloss = Cvar_Get ("sv_showloss", "0", 0);
@@ -720,7 +730,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 \"%s\"", message );
+					
+					#ifdef ELITEFORCE
+					if(cl->compat)
+						SV_SendServerCommand(cl, "disconnect Server shutdown: %s", message);
+					else
+					#endif
+						SV_SendServerCommand( cl, "disconnect \"%s\"", message );
 				}
 				// force a snapshot to be sent
 				cl->nextSnapshotTime = -1;
Index: code/server/sv_main.c
===================================================================
--- code/server/sv_main.c	(revision 2058)
+++ code/server/sv_main.c	(working copy)
@@ -319,11 +319,19 @@
 
 		// this command should be changed if the server info / status format
 		// ever incompatably changes
-
+		#ifdef ELITEFORCE
 		if(adr[i][0].type != NA_BAD)
+			NET_OutOfBandPrint(NS_SERVER, adr[i][0], "\\heartbeat\\%d\\gamename\\%s\\",
+					   Cvar_VariableIntegerValue("net_port"), message);
+		if(adr[i][1].type != NA_BAD)
+			NET_OutOfBandPrint(NS_SERVER, adr[i][1], "\\heartbeat\\%d\\gamename\\%s\\",
+					   Cvar_VariableIntegerValue("net_port6"), message);
+		#else
+		if(adr[i][0].type != NA_BAD)
 			NET_OutOfBandPrint( NS_SERVER, adr[i][0], "heartbeat %s\n", message);
 		if(adr[i][1].type != NA_BAD)
 			NET_OutOfBandPrint( NS_SERVER, adr[i][1], "heartbeat %s\n", message);
+		#endif
 	}
 }
 
@@ -639,11 +647,11 @@
 
 	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", com_protocol->integer) );
+#endif
 	Info_SetValueForKey( infostring, "hostname", sv_hostname->string );
 	Info_SetValueForKey( infostring, "mapname", sv_mapname->string );
 	Info_SetValueForKey( infostring, "clients", va("%i", count) );
@@ -651,6 +659,11 @@
 	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 ) );
 	Info_SetValueForKey(infostring, "g_needpass", va("%d", Cvar_VariableIntegerValue("g_needpass")));
 
@@ -671,7 +684,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
 }
 
 /*
@@ -776,9 +797,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 );
@@ -856,6 +879,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/game/g_local.h
===================================================================
--- code/game/g_local.h	(revision 2058)
+++ 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 2058)
+++ 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,8 +64,9 @@
 
 
 typedef struct {
+#ifndef ELITEFORCE
 	entityState_t	unused;			// apparently this field was put here accidentally
-									//  (and is kept only for compatibility, as a struct pad)
+#endif
 
 	qboolean	linked;				// qfalse if not in any good cluster
 	int			linkcount;
@@ -104,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 );
@@ -390,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 2058)
+++ 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/qcommon/q_math.c
===================================================================
--- code/qcommon/q_math.c	(revision 2058)
+++ code/qcommon/q_math.c	(working copy)
@@ -972,7 +972,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 2058)
+++ 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 2058)
+++ 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 2058)
+++ 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 );
@@ -444,7 +474,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 2058)
+++ 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 2058)
+++ code/qcommon/q_shared.h	(working copy)
@@ -38,16 +38,27 @@
   #define HOMEPATH_NAME_WIN		"FooBar"
   #define HOMEPATH_NAME_MACOSX		HOMEPATH_NAME_WIN
 #else
-  #define PRODUCT_NAME			"ioq3"
-  #define BASEGAME			"baseq3"
-  #define CLIENT_WINDOW_TITLE     	"ioquake3"
-  #define CLIENT_WINDOW_MIN_TITLE 	"ioq3"
-  #define GAMENAME_FOR_MASTER		"Quake3Arena"
-  #define HEARTBEAT_FOR_MASTER		"QuakeArena-1"
+  #ifdef ELITEFORCE
+    #define PRODUCT_NAME		"ioST:V HM"
+    #define BASEGAME			"baseEF"
+    #define CLIENT_WINDOW_TITLE     	"iostvoyHM"
+    #define CLIENT_WINDOW_MIN_TITLE 	"iostvoyHM"
+    #define GAMENAME_FOR_MASTER		"STEF1"
+    #define HEARTBEAT_FOR_MASTER	GAMENAME_FOR_MASTER
+    #define HOMEPATH_NAME_UNIX		".stvef"
+    #define HOMEPATH_NAME_WIN		"STVEF"
+  #else
+    #define PRODUCT_NAME		"ioq3"
+    #define BASEGAME			"baseq3"
+    #define CLIENT_WINDOW_TITLE     	"ioquake3"
+    #define CLIENT_WINDOW_MIN_TITLE 	"ioq3"
+    #define GAMENAME_FOR_MASTER		"Quake3Arena"
+    #define HEARTBEAT_FOR_MASTER	"QuakeArena-1"
+    #define HOMEPATH_NAME_UNIX		".q3a"
+    #define HOMEPATH_NAME_WIN		"Quake3"
+#endif
+  #define HOMEPATH_NAME_MACOSX		HOMEPATH_NAME_WIN
   #define FLATLINE_FOR_MASTER		HEARTBEAT_FOR_MASTER
-  #define HOMEPATH_NAME_UNIX		".q3a"
-  #define HOMEPATH_NAME_WIN		"Quake3"
-  #define HOMEPATH_NAME_MACOSX		HOMEPATH_NAME_WIN
 #endif
 
 #define BASETA				"missionpack"
@@ -1075,7 +1086,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
 
@@ -1099,6 +1114,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
@@ -1117,7 +1137,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
 
@@ -1141,20 +1163,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;
 
@@ -1189,14 +1218,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
@@ -1267,7 +1305,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 2058)
+++ code/qcommon/files.c	(working copy)
@@ -174,6 +174,15 @@
 
 // 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
+static const unsigned pak_checksums[] =
+{
+	3376297517u,
+	596947475u,
+	3960871590u,
+	1592359207u,
+};
+#else
 #define	DEMO_PAK0_CHECKSUM	2985612116u
 static const unsigned int pak_checksums[] = {
 	1566731103u,
@@ -186,6 +195,7 @@
 	908855077u,
 	977125798u
 };
+#endif
 
 static const unsigned int missionpak_checksums[] =
 {
@@ -2957,6 +2967,12 @@
 		havepak = qfalse;
 
 		// never autodownload any of the id paks
+#ifdef ELITEFORCE
+  #ifndef STANDALONE
+		if(FS_idPak(fs_serverReferencedPakNames[i], BASEGAME, NUM_ID_PAKS))
+			continue;
+  #endif
+#else
 		if(FS_idPak(fs_serverReferencedPakNames[i], BASEGAME, NUM_ID_PAKS)
 #ifndef STANDALONE
 		   || FS_idPak(fs_serverReferencedPakNames[i], BASETA, NUM_TA_PAKS)
@@ -2965,6 +2981,7 @@
 		{
 			continue;
 		}
+#endif
 
 		// Make sure the server cannot make us write to non-quake3 directories.
 		if(FS_CheckDirTraversal(fs_serverReferencedPakNames[i]))
@@ -3235,6 +3252,7 @@
 }
 
 #ifndef STANDALONE
+#ifdef ELITEFORCE
 /*
 ===================
 FS_CheckPak0
@@ -3247,10 +3265,127 @@
 STANDALONE in q_shared.h
 ===================
 */
+
 static void FS_CheckPak0( void )
 {
 	searchpath_t	*path;
 	pack_t		*curpack;
+	unsigned int foundPak = 0;
+
+	for( path = fs_searchpaths; path; path = path->next )
+	{
+		const char* pakBasename = path->pack->pakBasename;
+
+		if(!path->pack)
+			continue;
+		
+		curpack = path->pack;
+
+		if(!Q_stricmpn( curpack->pakGamename, BASEGAME, MAX_OSPATH )
+			&& strlen(pakBasename) == 4 && !Q_stricmpn( pakBasename, "pak", 3 )
+			&& pakBasename[3] >= '0' && pakBasename[3] <= '0' + NUM_ID_PAKS - 1)
+		{
+			if( curpack->checksum != pak_checksums[pakBasename[3]-'0'] )
+			{
+				if(pakBasename[3] == '0')
+				{
+
+					Com_Printf("\n\n"
+						"**************************************************\n"
+						"WARNING: " BASEGAME "/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",
+						curpack->checksum );
+				}
+				else
+				{
+					Com_Printf("\n\n"
+						"**************************************************\n"
+						"WARNING: pak%d.pk3 is present but its checksum (%u)\n"
+						"is not correct. Please copy the .pk3 files from\n"
+						"Elite Force patches 1.1 and 1.2 to the baseEF directory.\n"
+						"**************************************************\n\n\n",
+						pakBasename[3]-'0', curpack->checksum );
+				}
+			}
+
+			foundPak |= 1<<(pakBasename[3]-'0');
+		}
+		else
+		{
+			int index;
+			
+			// Finally check whether this pak's checksum is listed because the user tried
+			// to trick us by renaming the file, and set foundPak's highest bit to indicate this case.
+			
+			for(index = 0; index < ARRAY_LEN(pak_checksums); index++)
+			{
+				if(curpack->checksum == pak_checksums[index])
+				{
+					Com_Printf("\n\n"
+						"**************************************************\n"
+						"WARNING: %s is renamed pak file %s%cpak%d.pk3\n"
+						"Running in standalone mode won't work\n"
+						"Please rename, or remove this file\n"
+						"**************************************************\n\n\n",
+						curpack->pakFilename, BASEGAME, PATH_SEP, index);
+
+
+					foundPak |= 0x80000000;
+				}
+			}
+		}
+	}
+
+	if(!foundPak && Q_stricmp(com_basegame->string, BASEGAME))
+	{
+		Cvar_Set("com_standalone", "1");
+	}
+	else
+		Cvar_Set("com_standalone", "0");
+
+	if(!com_standalone->integer && (foundPak & 0x07) != 0x07)
+	{
+		char errorText[MAX_STRING_CHARS] = "";
+
+		if((foundPak & 0x01) != 0x01)
+		{
+			Q_strcat(errorText, sizeof(errorText),
+				"\"pak0.pk3\" is missing. Please copy it "
+				"from your legitimate EliteForce CDROM. ");
+		}
+		if((foundPak & 0x1fe) != 0x1fe)
+		{
+			Q_strcat(errorText, sizeof(errorText),
+				"Patch files are missing. Please\n"
+				"copy the .pk3 files from EliteForce patch 1.2 to baseEF.\n");		}
+
+		Q_strcat(errorText, sizeof(errorText),
+			va("Also check that your EliteForce executable is in "
+			"the correct place and that every file "
+			"in the \"%s\" directory is present and readable", BASEGAME));
+
+		Com_Error(ERR_FATAL, "%s", errorText);
+	}
+}
+
+#else
+
+/*
+===================
+FS_CheckPak0
+
+Checks that pak0.pk3 is present and its checksum is correct
+Note: If you're building a game that doesn't depend on the
+Q3 media pak0.pk3, you'll want to remove this function
+===================
+*/
+
+static void FS_CheckPak0( void )
+{
+	searchpath_t	*path;
+	pack_t		*curpack;
 	qboolean founddemo = qfalse;
 	unsigned int foundPak = 0, foundTA = 0;
 
@@ -3278,6 +3413,7 @@
 			{
 				if(pakBasename[3] == '0')
 				{
+
 					Com_Printf("\n\n"
 						"**************************************************\n"
 						"WARNING: " BASEGAME "/pak0.pk3 is present but its checksum (%u)\n"
@@ -3394,7 +3530,6 @@
 				"\"pak0.pk3\" is missing. Please copy it "
 				"from your legitimate Q3 CDROM. ");
 		}
-
 		if((foundPak & 0x1fe) != 0x1fe)
 		{
 			Q_strcat(errorText, sizeof(errorText),
@@ -3432,6 +3567,7 @@
 	}
 }
 #endif
+#endif
 
 /*
 =====================
@@ -3989,6 +4125,7 @@
 		callback( filename );
 	}
 	FS_FreeFileList( filenames );
+
 }
 
 const char *FS_GetCurrentGameDir(void)
Index: code/qcommon/cm_trace.c
===================================================================
--- code/qcommon/cm_trace.c	(revision 2058)
+++ code/qcommon/cm_trace.c	(working copy)
@@ -1155,6 +1155,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 2058)
+++ 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;
@@ -223,6 +230,10 @@
 	int			unsentFragmentStart;
 	int			unsentLength;
 	byte		unsentBuffer[MAX_MSGLEN];
+
+#ifdef ELITEFORCE
+	qboolean	compat;
+#endif
 } netchan_t;
 
 void Netchan_Init( int qport );
@@ -242,29 +253,57 @@
 ==============================================================
 */
 
+#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
+
+  #define PORT_MASTER 27953
+
+#else
+
+  #define	UPDATE_SERVER_NAME	"update.quake3arena.com"
+  #ifndef MASTER_SERVER_NAME
+    #define MASTER_SERVER_NAME	"master.quake3arena.com"
+  #endif
+
+  #define PORT_MASTER 27950
+
 #endif
 
 #ifndef STANDALONE
-  #ifndef AUTHORIZE_SERVER_NAME
-    #define	AUTHORIZE_SERVER_NAME	"authorize.quake3arena.com"
+  #ifdef ELITEFORCE
+    #ifndef AUTHORIZE_SERVER_NAME
+      #define	AUTHORIZE_SERVER_NAME	"authenticate.stef1.ravensoft.com"
+    #endif
+    #ifndef PORT_AUTHORIZE
+    #define	PORT_AUTHORIZE		27953
+    #endif
+  #else
+    #ifndef AUTHORIZE_SERVER_NAME
+      #define	AUTHORIZE_SERVER_NAME	"authorize.quake3arena.com"
+    #endif
+    #ifndef PORT_AUTHORIZE
+    #define	PORT_AUTHORIZE		27952
+    #endif
   #endif
-  #ifndef PORT_AUTHORIZE
-  #define	PORT_AUTHORIZE		27952
-  #endif
 #endif
 
-#define	PORT_MASTER			27950
 #define	PORT_UPDATE			27951
 #define	PORT_SERVER			27960
 #define	NUM_SERVER_PORTS	4		// broadcast scan this many ports after
@@ -584,15 +623,23 @@
 #define FS_CGAME_REF	0x04
 #define FS_QAGAME_REF	0x08
 // number of id paks that will never be autodownloaded from baseq3/missionpack
+#ifdef ELITEFORCE
 #define NUM_ID_PAKS		9
+#else
+#define NUM_ID_PAKS		9
 #define NUM_TA_PAKS		4
+#endif
 
 #define	MAX_FILE_HANDLES	64
 
-#ifdef DEDICATED
-#	define Q3CONFIG_CFG "q3config_server.cfg"
+#ifdef ELITEFORCE
+  #define Q3CONFIG_CFG "hmconfig.cfg"
 #else
-#	define Q3CONFIG_CFG "q3config.cfg"
+  #ifdef DEDICATED
+  #	define Q3CONFIG_CFG "q3config_server.cfg"
+  #else
+  #	define Q3CONFIG_CFG "q3config.cfg"
+  #endif
 #endif
 
 qboolean FS_Initialized( void );
Index: code/qcommon/net_ip.c
===================================================================
--- code/qcommon/net_ip.c	(revision 2058)
+++ code/qcommon/net_ip.c	(working copy)
@@ -128,7 +128,11 @@
 #endif
 
 // use an admin local address per default so that network admins can decide on how to handle quake3 traffic.
+#ifdef ELITEFORCE
+#define NET_MULTICAST_IP6 "ff04::696f:6566"
+#else
 #define NET_MULTICAST_IP6 "ff04::696f:7175:616b:6533"
+#endif
 
 #define	MAX_IPS		32
 
Index: code/qcommon/msg.c
===================================================================
--- code/qcommon/msg.c	(revision 2058)
+++ 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,54 @@
 		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", 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 read %d bits", bits);
+			}
+		}
 	} else {
 //		fp = fopen("c:\\netchan.bin", "a");
 		value &= (0xffffffff>>(32-bits));
@@ -198,23 +238,47 @@
 	}
 
 	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", 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", bits);
+			}
+		}
 	} else {
 		nbits = 0;
 		if (bits&7) {
@@ -245,7 +309,6 @@
 }
 
 
-
 //================================================================================
 
 //
@@ -272,6 +335,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]);
 	}
@@ -300,7 +373,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 );
@@ -311,12 +388,14 @@
 		}
 		Q_strncpyz( string, s, sizeof( string ) );
 
+#ifndef ELITEFORCE
 		// get rid of 0x80+ and '%' chars, because old clients don't like them
 		for ( i = 0 ; i < l ; i++ ) {
 			if ( ((byte *)string)[i] > 127 || string[i] == '%' ) {
 				string[i] = '.';
 			}
 		}
+#endif
 
 		MSG_WriteData (sb, string, l+1);
 	}
@@ -326,7 +405,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 );
@@ -337,12 +420,14 @@
 		}
 		Q_strncpyz( string, s, sizeof( string ) );
 
+#ifndef ELITEFORCE
 		// get rid of 0x80+ and '%' chars, because old clients don't like them
 		for ( i = 0 ; i < l ; i++ ) {
 			if ( ((byte *)string)[i] > 127 || string[i] == '%' ) {
 				string[i] = '.';
 			}
 		}
+#endif
 
 		MSG_WriteData (sb, string, l+1);
 	}
@@ -433,6 +518,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
@@ -443,11 +533,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);
@@ -461,6 +552,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
@@ -471,10 +568,12 @@
 		if ( c == '%' ) {
 			c = '.';
 		}
+#ifndef ELITEFORCE
 		// don't allow higher ascii values
 		if ( c > 127 ) {
 			c = '.';
 		}
+#endif
 
 		string[l] = c;
 		l++;
@@ -489,6 +588,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
@@ -499,11 +603,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);
@@ -520,6 +625,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);
 	}
@@ -684,7 +794,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 );
 }
 
@@ -706,7 +820,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);
 }
 
@@ -743,7 +861,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 );
 }
 
@@ -767,7 +889,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];
@@ -789,6 +915,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
@@ -814,6 +982,61 @@
 // using the stringizing operator to save typing...
 #define	NETF(x) #x,(size_t)&((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 },
@@ -833,7 +1056,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 },
@@ -868,8 +1091,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
@@ -894,6 +1117,10 @@
 	int			trunc;
 	float		fullFloat;
 	int			*fromF, *toF;
+#ifdef ELITEFORCE
+        byte            vector[PVECTOR_BYTES];
+	int                     vectorIndex = -1;
+#endif
 
 	numFields = ARRAY_LEN( entityStateFields );
 
@@ -917,17 +1144,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
@@ -939,35 +1182,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
@@ -980,13 +1275,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
 		}
 	}
 }
@@ -1005,13 +1310,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 );
@@ -1041,7 +1351,10 @@
 	}
 
 	numFields = ARRAY_LEN( entityStateFields );
-	lc = MSG_ReadByte(msg);
+	#ifdef ELITEFORCE
+	if(!msg->compat)
+	#endif
+		lc = MSG_ReadByte(msg);
 
 	if ( lc > numFields || lc < 0 ) {
 		Com_Error( ERR_DROP, "invalid entityState field count" );
@@ -1058,19 +1371,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 );
@@ -1089,9 +1431,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 ) {
@@ -1102,12 +1448,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 ) {
@@ -1131,6 +1484,59 @@
 // using the stringizing operator to save typing...
 #define	PSF(x) #x,(size_t)&((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 },				
@@ -1182,7 +1588,7 @@
 { PSF(jumppad_ent), 10 },
 { PSF(loopSound), 16 }
 };
-
+#endif
 /*
 =============
 MSG_WriteDeltaPlayerstate
@@ -1201,7 +1607,7 @@
 	netField_t		*field;
 	int				*fromF, *toF;
 	float			fullFloat;
-	int				trunc, lc;
+	int				trunc, lc = 0;
 
 	if (!from) {
 		from = &dummy;
@@ -1212,20 +1618,33 @@
 
 	numFields = ARRAY_LEN( playerStateFields );
 
-	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 );
 
@@ -1288,13 +1707,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 );
@@ -1346,7 +1774,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;
@@ -1378,10 +1806,17 @@
 	}
 
 	numFields = ARRAY_LEN( playerStateFields );
-	lc = MSG_ReadByte(msg);
 
-	if ( lc > numFields || lc < 0 ) {
-		Com_Error( ERR_DROP, "invalid playerState field count" );
+	#ifdef ELITEFORCE
+	if(msg->compat)
+		lc = numFields;
+	else
+	#endif	
+	{
+		lc = MSG_ReadByte(msg);
+
+	        if(lc > numFields || lc < 0)
+	                Com_Error(ERR_DROP, "invalid entityState field count");
 	}
 
 	for ( i = 0, field = playerStateFields ; i < lc ; i++, field++ ) {
@@ -1419,16 +1854,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 2058)
+++ code/qcommon/qfiles.h	(working copy)
@@ -283,7 +283,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 2058)
+++ code/qcommon/common.c	(working copy)
@@ -31,15 +31,25 @@
 #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
 
 #define MIN_DEDICATED_COMHUNKMEGS 1
 #define MIN_COMHUNKMEGS		56
 #define DEF_COMHUNKMEGS		64
+#ifdef ELITEFORCE
+#define DEF_COMZONEMEGS		32
+#else
 #define DEF_COMZONEMEGS		24
+#endif
+
 #define DEF_COMHUNKMEGS_S	XSTRING(DEF_COMHUNKMEGS)
 #define DEF_COMZONEMEGS_S	XSTRING(DEF_COMZONEMEGS)
 
@@ -73,6 +83,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;
@@ -2477,8 +2488,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
 	Com_sprintf(fbuffer, sizeof(fbuffer), "%s/q3key", filename);
+#endif
 
 	FS_SV_FOpenFileRead( fbuffer, &f );
 	if ( !f ) {
@@ -2488,14 +2505,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
 }
 
 /*
@@ -2537,20 +2608,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
 	Com_sprintf(fbuffer, sizeof(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);
@@ -2561,7 +2642,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" );
@@ -2785,6 +2870,7 @@
 	Cvar_Get("com_errorMessage", "", CVAR_ROM | CVAR_NORESTART);
 
 	com_introPlayed = Cvar_Get( "com_introplayed", "0", CVAR_ARCHIVE);
+	com_novmcompat = Cvar_Get( "com_novmcompat", "1", CVAR_ROM);
 
 	s = va("%s %s %s", Q3_VERSION, PLATFORM_STRING, __DATE__ );
 	com_version = Cvar_Get ("version", s, CVAR_ROM | CVAR_SERVERINFO );
@@ -2823,6 +2909,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");
@@ -2831,6 +2920,7 @@
 				Cvar_Set( "nextmap", "cinematic intro.RoQ" );
 			}
 		}
+#endif
 	}
 
 	// start in full screen ui mode
Index: code/botlib/be_ai_chat.c
===================================================================
--- code/botlib/be_ai_chat.c	(revision 2058)
+++ code/botlib/be_ai_chat.c	(working copy)
@@ -2810,10 +2810,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);
@@ -2823,13 +2830,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;
 			}
 		}
@@ -2881,13 +2890,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';
@@ -2988,11 +3003,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 2058)
+++ 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 2058)
+++ 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 2058)
+++ 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 2058)
+++ code/botlib/be_interface.c	(working copy)
@@ -740,6 +740,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 2058)
+++ 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 2058)
+++ code/botlib/botlib.h	(working copy)
@@ -81,6 +81,9 @@
 //action flags
 #define ACTION_ATTACK			0x00000001
 #define ACTION_USE			0x00000002
+#ifdef ELITEFORCE
+#define ACTION_ALTATTACK		0x00000004
+#endif
 #define ACTION_RESPAWN			0x00000008
 #define ACTION_JUMP			0x00000010
 #define ACTION_MOVEUP			0x00000020
@@ -276,6 +279,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);
@@ -331,7 +341,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 2058)
+++ 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 2058)
+++ 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 2058)
+++ 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 2058)
+++ 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 2058)
+++ code/client/cl_input.c	(working copy)
@@ -371,8 +371,10 @@
 void CL_MouseEvent( int dx, int dy, int time ) {
 	if ( Key_GetCatcher( ) & KEYCATCH_UI ) {
 		VM_Call( uivm, UI_MOUSE_EVENT, dx, dy );
+#ifndef ELITEFORCE
 	} else if (Key_GetCatcher( ) & KEYCATCH_CGAME) {
 		VM_Call (cgvm, CG_MOUSE_EVENT, dx, dy);
+#endif
 	} else {
 		cl.mouseDx[cl.mouseIndex] += dx;
 		cl.mouseDy[cl.mouseIndex] += dy;
@@ -751,7 +753,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 || clc.state == CA_CINEMATIC ) {
@@ -761,9 +766,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 );
@@ -898,18 +915,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 ^= MSG_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;
 		}
 	}
@@ -1016,6 +1039,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 2058)
+++ code/client/snd_codec.c	(working copy)
@@ -26,6 +26,34 @@
 
 static snd_codec_t *codecs;
 
+static void *S_CodecGetSound(const char *filename, snd_info_t *info);
+
+#ifdef ELITEFORCE
+int sem = qtrue;
+#define VOXDIR "sound/voice"
+
+void *S_MangleNameEF(char *filename, snd_info_t *info)
+{
+	char localName[MAX_QPATH];
+
+	if(
+	    !Q_strncmp(filename, VOXDIR, ARRAY_LEN(VOXDIR) - 1) &&
+	    !Q_stricmp(Cvar_VariableString("s_language"), "DEUTSCH")
+	  )
+	{
+		Q_strncpyz(localName, filename, MAX_QPATH - 10);
+	
+		localName[8] = 'x';
+		localName[9] = '_';
+		localName[10] = 'd';
+	
+		return S_CodecGetSound(localName, info);
+	}
+
+	return NULL;
+}
+#endif
+
 /*
 =================
 S_CodecGetSound
@@ -46,6 +74,12 @@
 
 	Q_strncpyz(localName, filename, MAX_QPATH);
 
+	#ifdef ELITEFORCE
+	rtn = S_MangleNameEF(localName, info);
+	if(rtn)
+		return rtn;
+	#endif
+
 	ext = COM_GetExtension(localName);
 
 	if( *ext )
@@ -110,7 +144,7 @@
 		}
 	}
 
-	Com_Printf(S_COLOR_YELLOW "WARNING: Failed to %s sound %s!\n", info ? "load" : "open", filename);
+	Com_DPrintf(S_COLOR_YELLOW "WARNING: Failed to %s sound %s!\n", info ? "load" : "open", filename);
 
 	return NULL;
 }
@@ -127,6 +161,9 @@
 #ifdef USE_CODEC_VORBIS
 	S_CodecRegister(&ogg_codec);
 #endif
+#if USE_CODEC_MP3
+	S_CodecRegister(&mp3_codec);
+#endif
 
 // Register wav codec last so that it is always tried first when a file extension was not found
 	S_CodecRegister(&wav_codec);
@@ -158,6 +195,7 @@
 S_CodecLoad
 =================
 */
+
 void *S_CodecLoad(const char *filename, snd_info_t *info)
 {
 	return S_CodecGetSound(filename, info);
Index: code/client/cl_scrn.c
===================================================================
--- code/client/cl_scrn.c	(revision 2058)
+++ 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 );
 }
 
@@ -253,6 +258,16 @@
 	SCR_DrawStringExt( x, y, BIGCHAR_WIDTH, s, color, qtrue, noColorEscape );
 }
 
+#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, qfalse);
+}
+#endif
 
 /*
 ==================
Index: code/client/client.h
===================================================================
--- code/client/client.h	(revision 2058)
+++ code/client/client.h	(working copy)
@@ -263,6 +263,10 @@
 	float voipPower;
 #endif
 
+#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;
@@ -571,6 +575,9 @@
 
 void	SCR_DrawBigString( int x, int y, const char *s, float alpha, qboolean noColorEscape );			// draws a string with embedded color control characters with fade
 void	SCR_DrawBigStringColor( int x, int y, const char *s, vec4_t color, qboolean noColorEscape );	// 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, qboolean noColorEscape );
 void	SCR_DrawSmallChar( int x, int y, int ch );
 
Index: code/client/snd_codec.h
===================================================================
--- code/client/snd_codec.h	(revision 2058)
+++ 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 2058)
+++ code/client/cl_parse.c	(working copy)
@@ -210,8 +210,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));
@@ -480,9 +483,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;
@@ -515,9 +521,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 );
 
 	// save old gamedir
 	Cvar_VariableStringBuffer("fs_game", oldGame, sizeof(oldGame));
@@ -844,15 +857,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
 	//
@@ -877,7 +897,12 @@
 			}
 		}
 
-		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 = Hunk_AllocateTempMemory(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.
+		Hunk_FreeTempMemory(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 2058)
+++ code/client/cl_main.c	(working copy)
@@ -636,14 +636,24 @@
 	if ( Cmd_Argc() == 2 ) {
 		s = Cmd_Argv(1);
 		Q_strncpyz( demoName, s, sizeof( demoName ) );
-		Com_sprintf (name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer );
+#ifdef ELITEFORCE
+		if(clc.compat)
+			Com_sprintf(name, sizeof(name), "demos/%s.efdemo", demoName);
+		else
+#endif
+			Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer);
 	} 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.%s%d", demoName, DEMOEXT, com_protocol->integer );
+			#ifdef ELITEFORCE
+			if(clc.compat)
+				Com_sprintf(name, sizeof(name), "demos/%s.efdemo", demoName);
+			else
+			#endif
+				Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer);
 
 			if (!FS_FileExists(name))
 				break;	// file doesn't exist
@@ -672,11 +682,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 );
@@ -703,18 +725,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);
@@ -856,7 +891,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);
@@ -889,11 +932,28 @@
 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;
+	}
 
+	*compat = qfalse;
+	#endif
+	
 	Com_sprintf (name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, com_protocol->integer);
 
 	FS_FOpenFileRead( name, demofile, qtrue );
@@ -950,6 +1010,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 ("demo <demoname>\n");
@@ -962,9 +1025,20 @@
 
 	// open the demo file
 	arg = Cmd_Argv(1);
+
+	CL_Disconnect( qtrue );
 	
-	CL_Disconnect( qtrue );
-
+#ifdef ELITEFORCE
+	ext_test = arg + strlen(arg) - 7;
+	if(!strcmp(ext_test, ".efdemo"))
+	{
+		Com_sprintf (name, sizeof(name), "demos/%s", arg);
+		FS_FOpenFileRead(name, &clc.demofile, qtrue);
+		compat = qtrue;
+	}
+	else
+#endif
+{
 	// check for an extension .DEMOEXT_?? (?? is protocol)
 	ext_test = strrchr(arg, '.');
 	
@@ -995,11 +1069,20 @@
 
 			Q_strncpyz(retry, arg, len + 1);
 			retry[len] = '\0';
+#ifdef ELITEFORCE
+			CL_WalkDemoExt(arg, name, &clc.demofile, &compat);
+#else
 			CL_WalkDemoExt(retry, name, &clc.demofile);
+#endif
 		}
 	}
 	else
+#ifdef ELITEFORCE
+		CL_WalkDemoExt(arg, name, &clc.demofile, &compat);
+#else
 		CL_WalkDemoExt(arg, name, &clc.demofile);
+#endif
+}
 	
 	if (!clc.demofile) {
 		Com_Error( ERR_DROP, "couldn't open %s", name);
@@ -1011,6 +1094,11 @@
 
 	clc.state = CA_CONNECTED;
 	clc.demoplaying = qtrue;
+
+	#ifdef ELITEFORCE
+	clc.compat = compat;
+	#endif
+
 	Q_strncpyz( clc.servername, Cmd_Argv(1), sizeof( clc.servername ) );
 
 	// read demo messages until connected
@@ -1717,7 +1805,12 @@
 	char cMsg[MAX_INFO_VALUE];
 
 	// if we are pure we need to send back a command with our referenced pk3 checksums
-	Com_sprintf(cMsg, sizeof(cMsg), "cp %d %s", cl.serverId, FS_ReferencedPakPureChecksums());
+#ifdef ELITEFORCE
+	if(clc.compat)
+		Com_sprintf(cMsg, sizeof(cMsg), "cp %s", FS_ReferencedPakPureChecksums());
+	else
+#endif
+		Com_sprintf(cMsg, sizeof(cMsg), "cp %d %s", cl.serverId, FS_ReferencedPakPureChecksums());
 
 	CL_AddReliableCommand(cMsg, qfalse);
 }
@@ -2190,7 +2283,12 @@
 		port = Cvar_VariableValue ("net_qport");
 
 		Q_strncpyz( info, Cvar_InfoString( CVAR_USERINFO ), sizeof( info ) );
-		Info_SetValueForKey( info, "protocol", va("%i", com_protocol->integer ) );
+		#ifdef ELITEFORCE
+		if(clc.compat)
+			Info_SetValueForKey( info, "protocol", va("%i", EFPROTOCOL_VERSION ) );
+		else
+		#endif
+			Info_SetValueForKey( info, "protocol", va("%i", com_protocol->integer ) );
 		Info_SetValueForKey( info, "qport", va("%i", port ) );
 		Info_SetValueForKey( info, "challenge", va("%i", clc.challenge ) );
 		
@@ -2206,7 +2304,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, "%s", data);
+		#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;
@@ -2311,6 +2413,9 @@
 	int				numservers;
 	byte*			buffptr;
 	byte*			buffend;
+	#ifdef ELITEFORCE
+	char strbyte[3] = "FF";
+	#endif
 	
 	Com_Printf("CL_ServersResponsePacket\n");
 
@@ -2340,12 +2445,30 @@
 		if (*buffptr == '\\')
 		{
 			buffptr++;
+#ifdef ELITEFORCE
+			if (buffend - buffptr < sizeof(addresses[numservers].ip) * 2 + sizeof(addresses[numservers].port) * 2 + 1)
+				break;
 
+			// 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
 			if (buffend - buffptr < sizeof(addresses[numservers].ip) + sizeof(addresses[numservers].port) + 1)
 				break;
 
 			for(i = 0; i < sizeof(addresses[numservers].ip); i++)
 				addresses[numservers].ip[i] = *buffptr++;
+#endif
 
 			addresses[numservers].type = NA_IP;
 		}
@@ -2361,17 +2484,24 @@
 				addresses[numservers].ip6[i] = *buffptr++;
 			
 			addresses[numservers].type = NA_IP6;
+#ifdef ELITEFORCE
+			// parse out port
+			addresses[numservers].port = (*buffptr++) << 8;
+			addresses[numservers].port += *buffptr++;
+			addresses[numservers].port = BigShort( addresses[numservers].port );
+#endif
 			addresses[numservers].scope_id = from->scope_id;
 		}
 		else
 			// syntax error!
 			break;
 			
+#ifndef ELITEFORCE
 		// parse out port
 		addresses[numservers].port = (*buffptr++) << 8;
 		addresses[numservers].port += *buffptr++;
 		addresses[numservers].port = BigShort( addresses[numservers].port );
-
+#endif
 		// syntax check
 		if (*buffptr != '\\' && *buffptr != '/')
 			break;
@@ -2495,6 +2625,9 @@
 			return;
 		}
 		Netchan_Setup (NS_CLIENT, &clc.netchan, from, Cvar_VariableValue( "net_qport" ) );
+		#ifdef ELITEFORCE
+		clc.netchan.compat = clc.compat;
+		#endif
 		clc.state = CA_CONNECTED;
 		clc.lastPacketSentTime = -9999;		// send first packet immediately
 		return;
@@ -2540,8 +2673,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;
+			clc.state = CA_CONNECTING;
+		}
+		else
+		{
+		#endif
+			Q_strncpyz( clc.serverMessage, s, sizeof( clc.serverMessage ) );
+			Com_Printf( "%s", s );
+		#ifdef ELITEFORCE
+		}
+		#endif
 		return;
 	}
 
@@ -2572,7 +2717,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;
@@ -2882,7 +3030,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;
@@ -3195,7 +3347,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);
@@ -3269,12 +3425,14 @@
 	Cvar_Get ("name", "UnnamedPlayer", CVAR_USERINFO | CVAR_ARCHIVE );
 	Cvar_Get ("rate", "25000", 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 );
@@ -3488,11 +3646,28 @@
 	char	*infoString;
 	int		prot;
 
+#ifdef ELITEFORCE
+	// eliteforce doesn't send a \n after infoResponse..
+	infoString = strchr((char *) 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 != com_protocol->integer ) {
+#endif
 		Com_DPrintf( "Different protocol info packet: %s\n", infoString );
 		return;
 	}
@@ -3502,6 +3677,10 @@
 	{
 		if ( cl_pinglist[i].adr.port && !cl_pinglist[i].time && NET_CompareAdr( from, cl_pinglist[i].adr ) )
 		{
+#ifdef ELITEFORCE
+			char *str = "";
+#endif
+			
 			// calc ping time
 			cl_pinglist[i].time = Sys_Milliseconds() - cl_pinglist[i].start;
 			Com_DPrintf( "ping time %dms from %s\n", cl_pinglist[i].time, NET_AdrToString( from ) );
@@ -3516,15 +3695,25 @@
 				case NA_BROADCAST:
 				case NA_IP:
 					type = 1;
+#ifdef ELITEFORCE
+					str = "udp";
+#endif					
 					break;
 				case NA_IP6:
 					type = 2;
+#ifdef ELITEFORCE
+					str = "udp6";
+#endif					
 					break;
 				default:
 					type = 0;
 					break;
 			}
-			Info_SetValueForKey( cl_pinglist[i].info, "nettype", va("%d", type) );
+#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;
@@ -3843,7 +4032,7 @@
 	// -1 is used to distinguish a "no response"
 
 	i = NET_StringToAdr(masteraddress, &to, NA_UNSPEC);
-	
+
 	if(!i)
 	{
 		Com_Printf( "CL_GlobalServers_f: Error: could not resolve address of master %s\n", masteraddress);
Index: code/client/snd_dma.c
===================================================================
--- code/client/snd_dma.c	(revision 2058)
+++ code/client/snd_dma.c	(working copy)
@@ -369,10 +369,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;
 	}
 
@@ -394,7 +404,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
 	}
 }
 
@@ -1337,9 +1351,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 2058)
+++ 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
@@ -576,8 +575,23 @@
 	// draw the chat line
 	if ( Key_GetCatcher( ) & 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, qtrue);
+#else
+		if (chat_team)
+		{
 			SCR_DrawBigString (8, v, "say_team:", 1.0f, qfalse );
 			skip = 10;
 		}
@@ -589,6 +603,7 @@
 
 		Field_BigDraw( &chatField, skip * BIGCHAR_WIDTH, v,
 			SCREEN_WIDTH - ( skip + 1 ) * BIGCHAR_WIDTH, qtrue, qtrue );
+#endif
 
 		v += BIGCHAR_HEIGHT;
 	}
@@ -625,10 +640,18 @@
 
 	// draw the background
 	y = frac * SCREEN_HEIGHT;
+
 	if ( y < 1 ) {
 		y = 0;
 	}
 	else {
+		#ifdef ELITEFORCE
+		color[0] = 0;
+		color[1] = 0;
+		color[2] = 0;
+		color[3] = 0.85;
+		re.SetColor(color);
+		#endif
 		SCR_DrawPic( 0, 0, SCREEN_WIDTH, y, cls.consoleShader );
 	}
 
@@ -637,8 +660,6 @@
 	color[2] = 0;
 	color[3] = 1;
 	SCR_FillRect( 0, y, SCREEN_WIDTH, 2, color );
-
-
 	// draw the version number
 
 	re.SetColor( g_color_table[ColorIndex(COLOR_RED)] );
Index: code/client/snd_openal.c
===================================================================
--- code/client/snd_openal.c	(revision 2058)
+++ code/client/snd_openal.c	(working copy)
@@ -323,7 +323,12 @@
 	data = S_CodecLoad(curSfx->filename, &info);
 	if(!data)
 	{
+#ifdef ELITEFORCE
+		S_AL_BufferUnload(sfx);
+		*knownSfx[sfx].filename = '\0';
+#else
 		S_AL_BufferUseDefault(sfx);
+#endif
 		return;
 	}
 
@@ -430,7 +435,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;
 
@@ -478,6 +487,12 @@
 
 	if((!knownSfx[sfx].inMemory) && (!knownSfx[sfx].isDefault))
 		S_AL_BufferLoad(sfx, s_alPrecache->integer);
+
+#ifdef ELITEFORCE
+	if(! *knownSfx[sfx].filename)
+        	return 0;
+#endif
+                        
 	knownSfx[sfx].lastUsedTime = Com_Milliseconds();
 
 	if (knownSfx[sfx].isDefault) {
Index: code/client/cl_keys.c
===================================================================
--- code/client/cl_keys.c	(revision 2058)
+++ code/client/cl_keys.c	(working copy)
@@ -1212,13 +1212,14 @@
 			return;
 		}
 
+#ifndef ELITEFORCE
 		// escape always gets out of CGAME stuff
 		if (Key_GetCatcher( ) & KEYCATCH_CGAME) {
 			Key_SetCatcher( Key_GetCatcher( ) & ~KEYCATCH_CGAME );
 			VM_Call (cgvm, CG_EVENT_HANDLING, CGAME_EVENT_NONE);
 			return;
 		}
-
+#endif
 		if ( !( Key_GetCatcher( ) & KEYCATCH_UI ) ) {
 			if ( clc.state == CA_ACTIVE && !clc.demoplaying ) {
 				VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_INGAME );
@@ -1230,8 +1231,11 @@
 			}
 			return;
 		}
-
+#ifdef ELITEFORCE
+		VM_Call( uivm, UI_KEY_EVENT, key );
+#else
 		VM_Call( uivm, UI_KEY_EVENT, key, qtrue );
+#endif
 		return;
 	}
 
@@ -1242,10 +1246,12 @@
 		if ( uivm ) {
 			VM_Call( uivm, UI_KEY_EVENT, key, qtrue );
 		} 
+#ifndef ELITEFORCE
 	} else if ( Key_GetCatcher( ) & KEYCATCH_CGAME ) {
 		if ( cgvm ) {
 			VM_Call( cgvm, CG_KEY_EVENT, key, qtrue );
 		} 
+#endif
 	} else if ( Key_GetCatcher( ) & KEYCATCH_MESSAGE ) {
 		Message_Key( key );
 	} else if ( clc.state == CA_DISCONNECTED ) {
@@ -1288,11 +1294,13 @@
 	if( clc.state != CA_DISCONNECTED )
 		CL_ParseBinding( key, qfalse, time );
 
+#ifndef ELITEFORCE
 	if ( Key_GetCatcher( ) & KEYCATCH_UI && uivm ) {
 		VM_Call( uivm, UI_KEY_EVENT, key, qfalse );
 	} else if ( Key_GetCatcher( ) & KEYCATCH_CGAME && cgvm ) {
 		VM_Call( cgvm, CG_KEY_EVENT, key, qfalse );
 	}
+#endif
 }
 
 /*
Index: code/client/cl_cgame.c
===================================================================
--- code/client/cl_cgame.c	(revision 2058)
+++ code/client/cl_cgame.c	(working copy)
@@ -298,9 +298,19 @@
 		// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=552
 		// allow server to indicate why they were disconnected
 		if ( argc >= 2 )
+		{
+			#ifdef ELITEFORCE
+			Cbuf_AddText(va("err_dialog \"%s\"", Cmd_Argv(1)));
+			#endif
 			Com_Error( ERR_SERVERDISCONNECT, "Server disconnected - %s", Cmd_Argv( 1 ) );
+		}
 		else
+		{
+			#ifdef ELITEFORCE
+			Cbuf_AddText(va("err_dialog \"%s\"", Cmd_Argv(1)));
+			#endif
 			Com_Error( ERR_SERVERDISCONNECT, "Server disconnected" );
+		}
 	}
 
 	if ( !strcmp( cmd, "bcs0" ) ) {
@@ -455,17 +465,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_RemoveCommandSafe( VMA(1) );
 		return 0;
+#endif
 	case CG_SENDCLIENTCOMMAND:
 		CL_AddReliableCommand(VMA(1), qfalse);
 		return 0;
@@ -486,8 +500,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:
@@ -495,15 +511,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:
@@ -518,12 +538,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;
@@ -533,7 +555,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) );
@@ -546,9 +573,11 @@
 		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));
 		return 0;
+#endif
 	case CG_R_CLEARSCENE:
 		re.ClearScene();
 		return 0;
@@ -558,17 +587,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;
@@ -605,6 +638,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:
@@ -615,9 +649,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;
@@ -639,9 +673,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:
@@ -699,7 +733,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);
 		Com_Error( ERR_DROP, "Bad cgame system trap: %ld", (long int) args[0] );
Index: code/client/cl_ui.c
===================================================================
--- code/client/cl_ui.c	(revision 2058)
+++ code/client/cl_ui.c	(working copy)
@@ -84,7 +84,7 @@
 	FS_FCloseFile(fileOut);
 }
 
-
+#ifndef ELITEFORCE
 /*
 ====================
 LAN_ResetPings
@@ -204,8 +204,8 @@
 		}
 	}
 }
+#endif
 
-
 /*
 ====================
 LAN_GetServerCount
@@ -226,7 +226,6 @@
 	}
 	return 0;
 }
-
 /*
 ====================
 LAN_GetLocalServerAddressString
@@ -257,6 +256,7 @@
 	buf[0] = '\0';
 }
 
+#ifndef ELITEFORCE
 /*
 ====================
 LAN_GetServerInfo
@@ -365,7 +365,6 @@
 	}
 	return NULL;
 }
-
 /*
 ====================
 LAN_CompareServers
@@ -435,6 +434,8 @@
 	return res;
 }
 
+#endif
+
 /*
 ====================
 LAN_GetPingQueueCount
@@ -471,6 +472,7 @@
 	CL_GetPingInfo( n, buf, buflen );
 }
 
+#ifndef ELITEFORCE
 /*
 ====================
 LAN_MarkServerVisible
@@ -549,6 +551,8 @@
 	return qfalse;
 }
 
+#endif
+
 /*
 =======================
 LAN_UpdateVisiblePings
@@ -627,6 +631,7 @@
 CLUI_GetCDKey
 ====================
 */
+  #ifndef ELITEFORCE
 static void CLUI_GetCDKey( char *buf, int buflen ) {
 #ifndef STANDALONE
 	cvar_t	*fs;
@@ -642,8 +647,8 @@
 	*buf = 0;
 #endif
 }
+  #endif
 
-
 /*
 ====================
 CLUI_SetCDKey
@@ -659,7 +664,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;
 	}
@@ -794,8 +804,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) );
@@ -902,6 +914,7 @@
 	case UI_GETCONFIGSTRING:
 		return GetConfigString( args[1], VMA(2), args[3] );
 
+#ifndef ELITEFORCE
 	case UI_LAN_LOADCACHEDSERVERS:
 		LAN_LoadCachedServers();
 		return 0;
@@ -916,6 +929,7 @@
 	case UI_LAN_REMOVESERVER:
 		LAN_RemoveServer(args[1], VMA(2));
 		return 0;
+#endif
 
 	case UI_LAN_GETPINGQUEUECOUNT:
 		return LAN_GetPingQueueCount();
@@ -932,13 +946,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;
@@ -965,26 +992,32 @@
 
 	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:
 #ifndef STANDALONE
 		CLUI_SetCDKey( VMA(1) );
+		#ifdef ELITEFORCE
+		return qtrue;
+		#endif
 #endif
 		return 0;
-	
+#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] );
@@ -1016,6 +1049,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:
@@ -1061,6 +1095,7 @@
 
 	case UI_VERIFY_CDKEY:
 		return CL_CDKeyValidate(VMA(1), VMA(2));
+#endif
 		
 	default:
 		Com_Error( ERR_DROP, "Bad UI system trap: %ld", (long int) args[0] );
@@ -1116,6 +1151,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, (clc.state >= CA_AUTHORIZING && clc.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 );
@@ -1124,16 +1163,24 @@
 	else {
 		// init for this gamestate
 		VM_Call( uivm, UI_INIT, (clc.state >= CA_AUTHORIZING && clc.state < CA_ACTIVE) );
+
+		#ifdef ELITEFORCE
+		Cvar_SetValue("ui_cdkeychecked2", 1);
+		#endif
 	}
 }
 
 #ifndef STANDALONE
 qboolean UI_usesUniqueCDKey( void ) {
+#ifdef ELITEFORCE
+	return qfalse;
+#else
 	if (uivm) {
 		return (VM_Call( uivm, UI_HASUNIQUECDKEY) == qtrue);
 	} else {
 		return qfalse;
 	}
+#endif
 }
 #endif
 
Index: code/client/cl_net_chan.c
===================================================================
--- code/client/cl_net_chan.c	(revision 2058)
+++ 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: code/sys/sys_unix.c
===================================================================
--- code/sys/sys_unix.c	(revision 2058)
+++ code/sys/sys_unix.c	(working copy)
@@ -57,7 +57,14 @@
 		if( ( p = getenv( "HOME" ) ) != NULL )
 		{
 			Com_sprintf(homePath, sizeof(homePath), "%s%c", p, PATH_SEP);
-#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/");
 
@@ -65,11 +72,12 @@
 				Q_strcat(homePath, sizeof(homePath), com_homepath->string);
 			else
 				Q_strcat(homePath, sizeof(homePath), HOMEPATH_NAME_MACOSX);
-#else
+  #else
 			if(com_homepath->string[0])
 				Q_strcat(homePath, sizeof(homePath), com_homepath->string);
 			else
 				Q_strcat(homePath, sizeof(homePath), HOMEPATH_NAME_UNIX);
+  #endif
 #endif
 		}
 	}
Index: Makefile
===================================================================
--- Makefile	(revision 2058)
+++ Makefile	(working copy)
@@ -45,6 +45,8 @@
   BUILD_MISSIONPACK=
 endif
 
+BUILD_ELITEFORCE =
+
 ifneq ($(PLATFORM),darwin)
   BUILD_CLIENT_SMP = 0
 endif
@@ -135,6 +137,10 @@
 USE_CODEC_VORBIS=0
 endif
 
+ifndef USE_CODEC_MP3
+USE_CODEC_MP3=0
+endif
+
 ifndef USE_MUMBLE
 USE_MUMBLE=1
 endif
@@ -197,6 +203,10 @@
 SDLHDIR=$(MOUNT_DIR)/SDL12
 LIBSDIR=$(MOUNT_DIR)/libs
 
+ifeq ($(BUILD_ELITEFORCE),1)
+  CFLAGS += -DELITEFORCE
+endif
+
 bin_path=$(shell which $(1) 2> /dev/null)
 
 # We won't need this if we only build the server
@@ -221,7 +231,11 @@
 endif
 
 # version info
-VERSION=1.36
+ifeq ($(BUILD_ELITEFORCE),1)
+  VERSION=1.38
+else
+  VERSION=1.36
+endif
 
 USE_SVN=
 ifeq ($(wildcard .svn),.svn)
@@ -291,6 +305,10 @@
     CLIENT_CFLAGS += -DUSE_CODEC_VORBIS
   endif
 
+  ifeq ($(USE_CODEC_MP3),1)
+    BASE_CFLAGS += -DUSE_CODEC_MP3=1
+  endif
+
   OPTIMIZEVM = -O3 -funroll-loops -fomit-frame-pointer
   OPTIMIZE = $(OPTIMIZEVM) -ffast-math
 
@@ -339,6 +357,7 @@
 
   THREAD_LIBS=-lpthread
   LIBS=-ldl -lm
+  LIBS += -L/emul/linux/x86/usr/lib
 
   CLIENT_LIBS=$(SDL_LIBS) -lGL
 
@@ -358,6 +377,10 @@
     CLIENT_LIBS += -lvorbisfile -lvorbis -logg
   endif
 
+  ifeq ($(USE_CODEC_MP3),1)
+    CLIENT_LDFLAGS += -lmad
+  endif
+
   ifeq ($(USE_MUMBLE),1)
     CLIENT_LIBS += -lrt
   endif
@@ -429,6 +452,10 @@
     CLIENT_LIBS += -lvorbisfile -lvorbis -logg
   endif
 
+  ifeq ($(USE_CODEC_MP3),1)
+    BASE_CFLAGS += -DUSE_CODEC_MP3=1
+  endif
+
   BASE_CFLAGS += -D_THREAD_SAFE=1
 
   ifeq ($(USE_LOCAL_HEADERS),1)
@@ -455,8 +482,11 @@
 
   NOTSHLIBCFLAGS=-mdynamic-no-pic
 
+  ifeq ($(USE_CODEC_MP3),1)
+    CLIENT_LDFLAGS += -lmad
+  endif
+
   TOOLS_CFLAGS += -DMACOS_X
-
 else # ifeq darwin
 
 
@@ -500,6 +530,10 @@
     CLIENT_CFLAGS += -DUSE_CODEC_VORBIS
   endif
 
+  ifeq ($(USE_CODEC_MP3),1)
+    BASE_CFLAGS += -DUSE_CODEC_MP3=1
+  endif
+
   ifeq ($(ARCH),x64)
     OPTIMIZEVM = -O3 -fno-omit-frame-pointer \
       -falign-loops=2 -funroll-loops -falign-jumps=2 -falign-functions=2 \
@@ -546,6 +580,10 @@
     CLIENT_LIBS += -lvorbisfile -lvorbis -logg
   endif
 
+  ifeq ($(USE_CODEC_MP3),1)
+    CLIENT_LDFLAGS += -lmad
+  endif
+
   ifeq ($(ARCH),x86)
     # build 32bit
     BASE_CFLAGS += -m32
@@ -624,6 +662,11 @@
     CLIENT_LIBS += -lvorbisfile -lvorbis -logg
   endif
 
+  ifeq ($(USE_CODEC_MP3),1)
+    CLIENT_CFLAGS += -DUSE_CODEC_MP3=1
+    CLIENT_LDFLAGS += -lmad
+  endif
+
   # cross-compiling tweaks
   ifeq ($(ARCH),i386)
     ifeq ($(CROSS_COMPILING),1)
@@ -636,6 +679,7 @@
     endif
   endif
 
+>>>>>>> .r2058
 else # ifeq freebsd
 
 #############################################################################
@@ -1355,6 +1399,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 \
@@ -1678,6 +1723,7 @@
 endif
 
 
+$(B)/client/snd_codec_mp3.o : $(CDIR)/snd_codec_mp3.c; $(DO_CC)
 
 #############################################################################
 # DEDICATED SERVER
